Repository: reedhong/fomo3d_clone Branch: master Commit: f344599b7e59 Files: 33 Total size: 179.2 KB Directory structure: gitextract_dkcixdu1/ ├── .gitignore ├── README.md ├── bs-config.json ├── contracts/ │ ├── Divies.sol │ ├── F3Devents.sol │ ├── F3DexternalSettings.sol │ ├── FoMo3Dlong.sol │ ├── Hourglass.sol │ ├── JIincForwarder.sol │ ├── PlayerBook.sol │ ├── TeamJust.sol │ ├── interface/ │ │ ├── DiviesInterface.sol │ │ ├── F3DexternalSettingsInterface.sol │ │ ├── HourglassInterface.sol │ │ ├── JIincForwarderInterface.sol │ │ ├── JIincInterfaceForForwarder.sol │ │ ├── PlayerBookInterface.sol │ │ ├── PlayerBookReceiverInterface.sol │ │ ├── TeamJustInterface.sol │ │ └── otherFoMo3D.sol │ ├── library/ │ │ ├── F3DKeysCalcLong.sol │ │ ├── F3Ddatasets.sol │ │ ├── MSFun.sol │ │ ├── NameFilter.sol │ │ ├── SafeMath.sol │ │ └── UintCompressor.sol │ └── modularLong.sol ├── flattener.sh ├── migrations/ │ ├── 1_initial_migration.js │ ├── 2_deploy_petcore.js │ └── 3_deploy_gene.js ├── package.json └── truffle.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ build/* node_modules/* test/* ================================================ FILE: README.md ================================================ ### 说明 本项目通过fomo3d官网合约的入口,把相关所有的合约进行汇总。 在通过继承的机制就行分拆开。 现已经是一个truffle项目。可以通过命令: > truffle compile 直接编译 相关文章: [Fomo3D源码解密:框架篇](https://mp.weixin.qq.com/s/kT94y3kHZKa-JXXWWGqD_A) [破解获得Fomo3d中闭源合约F3DExternalSettings的返回值](https://mp.weixin.qq.com/s/GIDwSMU8_usF13n3rFvW-g) [在以太坊Kovan测试网络中克隆了一套P3D+F3D](https://mp.weixin.qq.com/s/8jfLjD6UgIDfw4fOsJ0rCg) 测试网络的克隆版本: [https://cryptofish.cc/](https://cryptofish.cc/) 欢迎交流咨询: ![](https://github.com/reedhong/fomo3d_clone/blob/master/src/images/wechat.jpeg) ![](https://github.com/reedhong/fomo3d_clone/blob/master/src/images/xiaomiquan.png) 注:小密圈中沉淀了不少内容,欢迎加入! ================================================ FILE: bs-config.json ================================================ { "server": { "baseDir": ["./src", "./build/contracts"] } } ================================================ FILE: contracts/Divies.sol ================================================ pragma solidity ^0.4.24; /** title -Divies- v0.7.1 * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ * _____ _____ * (, / /) /) /) (, / /) /) * ┌─┐ / _ (/_ // // / _ // _ __ _(/ * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ * ┴ ┴ / / .-/ _____ (__ / * (__ / (_/ (, / /)™ * / __ __ __ __ _ __ __ _ _/_ _ _(/ * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ * ______ .-./`) ,---. ,---. .-./`) .-''-. .-'''-. .---. *=========| _ `''. \ .-.') | / | | \ .-.') .'_ _ \ / _ \ \ /=========* * | _ | ) _ \ / `-' \ | | | .' / `-' \ / ( ` ) ' (`' )/`--' | | * |( ''_' ) | `-'`"` | | _ | | `-'`"` . (_ o _) | (_ o _). \ / * | . (_) `. | .---. | _( )_ | .---. | (_,_)___| (_,_). '. v * |(_ ._) ' | | \ (_ o._) / | | ' \ .---. .---. \ : _ _ * | (_.\.' / | | \ (_,_) / | | \ `-' / \ `-' | (_I_) *=========| .' | | \ / | | \ / \ / (_(=)_)========* * '-----'` '---' `---` '---' `'-..-' `-...-' (_I_) * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ * ┌──────────────────────────────────────────────────────────────────────┐ * │ Divies!, is a contract that adds an external dividend system to P3D. │ * │ All eth sent to this contract, can be distributed to P3D holders. │ * │ Uses msg.sender as masternode for initial buy order. │ * └──────────────────────────────────────────────────────────────────────┘ * ┌────────────────────┐ * │ Setup Instructions │ * └────────────────────┘ * (Step 1) import this contracts interface into your contract * * import "./DiviesInterface.sol"; * * (Step 2) set up the interface and point it to this contract * * DiviesInterface private Divies = DiviesInterface(0xc7029Ed9EBa97A096e72607f4340c34049C7AF48); * ┌────────────────────┐ * │ Usage Instructions │ * └────────────────────┘ * call as follows anywhere in your code: * * Divies.deposit.value(amount)(); * ex: Divies.deposit.value(232000000000000000000)(); */ import "./interface/DiviesInterface.sol"; import "./library/SafeMath.sol"; import "./library/UintCompressor.sol"; import "./interface/HourglassInterface.sol"; contract Divies { using SafeMath for uint256; using UintCompressor for uint256; HourglassInterface constant P3Dcontract_ = HourglassInterface(0xB3775fB83F7D12A36E0475aBdD1FCA35c091efBe); uint256 public pusherTracker_ = 100; mapping (address => Pusher) public pushers_; struct Pusher { uint256 tracker; uint256 time; } uint256 public rateLimiter_; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // MODIFIERS //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifier isHuman() { address _addr = msg.sender; uint256 _codeLength; assembly {_codeLength := extcodesize(_addr)} require(_codeLength == 0, "sorry humans only"); _; } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // BALANCE //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function balances() public view returns(uint256) { return (address(this).balance); } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // DEPOSIT //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function deposit() external payable { } // used so the distribute function can call hourglass's withdraw function() external payable {} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // EVENTS //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ event onDistribute( address pusher, uint256 startingBalance, uint256 masternodePayout, uint256 finalBalance, uint256 compressedData ); /* compression key [0-14] - timestamp [15-29] - caller pusher tracker [30-44] - global pusher tracker [45-46] - percent [47] - greedy */ //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // DISTRIBUTE //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function distribute(uint256 _percent) public isHuman() { // make sure _percent is within boundaries require(_percent > 0 && _percent < 100, "please pick a percent between 1 and 99"); // data setup address _pusher = msg.sender; uint256 _bal = address(this).balance; uint256 _mnPayout; uint256 _compressedData; // limit pushers greed (use "if" instead of require for level 42 top kek) if ( pushers_[_pusher].tracker <= pusherTracker_.sub(100) && // pusher is greedy: wait your turn pushers_[_pusher].time.add(1 hours) < now // pusher is greedy: its not even been 1 hour ) { // update pushers wait que pushers_[_pusher].tracker = pusherTracker_; pusherTracker_++; // setup mn payout for event if (P3Dcontract_.balanceOf(_pusher) >= P3Dcontract_.stakingRequirement()) _mnPayout = (_bal / 10) / 3; // setup _stop. this will be used to tell the loop to stop uint256 _stop = (_bal.mul(100 - _percent)) / 100; // buy & sell P3Dcontract_.buy.value(_bal)(_pusher); P3Dcontract_.sell(P3Dcontract_.balanceOf(address(this))); // setup tracker. this will be used to tell the loop to stop uint256 _tracker = P3Dcontract_.dividendsOf(address(this)); // reinvest/sell loop while (_tracker >= _stop) { // lets burn some tokens to distribute dividends to p3d holders P3Dcontract_.reinvest(); P3Dcontract_.sell(P3Dcontract_.balanceOf(address(this))); // update our tracker with estimates (yea. not perfect, but cheaper on gas) _tracker = (_tracker.mul(81)) / 100; } // withdraw P3Dcontract_.withdraw(); } else { _compressedData = _compressedData.insert(1, 47, 47); } // update pushers timestamp (do outside of "if" for super saiyan level top kek) pushers_[_pusher].time = now; // prep event compression data _compressedData = _compressedData.insert(now, 0, 14); _compressedData = _compressedData.insert(pushers_[_pusher].tracker, 15, 29); _compressedData = _compressedData.insert(pusherTracker_, 30, 44); _compressedData = _compressedData.insert(_percent, 45, 46); // fire event emit onDistribute(_pusher, _bal, _mnPayout, address(this).balance, _compressedData); } } ================================================ FILE: contracts/F3Devents.sol ================================================ pragma solidity ^0.4.24; contract F3Devents { // fired whenever a player registers a name event onNewName ( uint256 indexed playerID, address indexed playerAddress, bytes32 indexed playerName, bool isNewPlayer, uint256 affiliateID, address affiliateAddress, bytes32 affiliateName, uint256 amountPaid, uint256 timeStamp ); // fired at end of buy or reload event onEndTx ( uint256 compressedData, uint256 compressedIDs, bytes32 playerName, address playerAddress, uint256 ethIn, uint256 keysBought, address winnerAddr, bytes32 winnerName, uint256 amountWon, uint256 newPot, uint256 P3DAmount, uint256 genAmount, uint256 potAmount, uint256 airDropPot ); // fired whenever theres a withdraw event onWithdraw ( uint256 indexed playerID, address playerAddress, bytes32 playerName, uint256 ethOut, uint256 timeStamp ); // fired whenever a withdraw forces end round to be ran event onWithdrawAndDistribute ( address playerAddress, bytes32 playerName, uint256 ethOut, uint256 compressedData, uint256 compressedIDs, address winnerAddr, bytes32 winnerName, uint256 amountWon, uint256 newPot, uint256 P3DAmount, uint256 genAmount ); // (fomo3d long only) fired whenever a player tries a buy after round timer // hit zero, and causes end round to be ran. event onBuyAndDistribute ( address playerAddress, bytes32 playerName, uint256 ethIn, uint256 compressedData, uint256 compressedIDs, address winnerAddr, bytes32 winnerName, uint256 amountWon, uint256 newPot, uint256 P3DAmount, uint256 genAmount ); // (fomo3d long only) fired whenever a player tries a reload after round timer // hit zero, and causes end round to be ran. event onReLoadAndDistribute ( address playerAddress, bytes32 playerName, uint256 compressedData, uint256 compressedIDs, address winnerAddr, bytes32 winnerName, uint256 amountWon, uint256 newPot, uint256 P3DAmount, uint256 genAmount ); // fired whenever an affiliate is paid event onAffiliatePayout ( uint256 indexed affiliateID, address affiliateAddress, bytes32 affiliateName, uint256 indexed roundID, uint256 indexed buyerID, uint256 amount, uint256 timeStamp ); // received pot swap deposit event onPotSwapDeposit ( uint256 roundID, uint256 amountAddedToPot ); } ================================================ FILE: contracts/F3DexternalSettings.sol ================================================ pragma solidity ^0.4.24; // 看不到代码 合约地址: 0x32967D6c142c2F38AB39235994e2DDF11c37d590 // 根据链上的数据把结果放在这里 contract F3DexternalSettings { constructor() public { //constructor does nothing. } function() public payable { revert(); } function getFastGap() external view returns(uint256){ return 2 minutes; } function getLongGap() external view returns(uint256){ return 2 minutes; } function getFastExtra() external view returns(uint256){ return 10 minutes; } function getLongExtra() external view returns(uint256){ return 10 minutes; } } ================================================ FILE: contracts/FoMo3Dlong.sol ================================================ pragma solidity ^0.4.24; /** * @title -FoMo-3D v0.7.1 * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ * _____ _____ * (, / /) /) /) (, / /) /) * ┌─┐ / _ (/_ // // / _ // _ __ _(/ * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ * ┴ ┴ / / .-/ _____ (__ / * (__ / (_/ (, / /)™ * / __ __ __ __ _ __ __ _ _/_ _ _(/ * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ .--,-``-. *========,---,.======================____==========================/ / '.=======,---,====* * ,' .' | ,' , `. / ../ ; .' .' `\ * ,---.' | ,---. ,-+-,.' _ | ,---. \ ``\ .`- ' ,---.' \ * | | .' ' ,'\ ,-+-. ; , || ' ,'\ ,---,. \___\/ \ : | | .`\ | * : : : / / | ,--.'|' | || / / | ,' .' | \ : | : : | ' | * : | |-, . ; ,. : | | ,', | |, . ; ,. : ,---.' | / / / | ' ' ; : * | : ;/| ' | |: : | | / | |--' ' | |: : | | .' \ \ \ ' | ; . | * | | .' ' | .; : | : | | , ' | .; : : |.' ___ / : | | | : | ' * ' : ' | : | | : | |/ | : | `---' / /\ / : ' : | / ; * | | | \ \ / | | |`-' \ \ / / ,,/ ',- . | | '` ,/ * | : \ `----' | ;/ `----' \ ''\ ; ; : .' *====| | ,'=============='---'==========(long version)===========\ \ .'===| ,.'======* * `----' `--`-,,-' '---' * ╔═╗┌─┐┌─┐┬┌─┐┬┌─┐┬ ┌─────────────────────────┐ ╦ ╦┌─┐┌┐ ╔═╗┬┌┬┐┌─┐ * ║ ║├┤ ├┤ ││ │├─┤│ │ https://exitscam.me │ ║║║├┤ ├┴┐╚═╗│ │ ├┤ * ╚═╝└ └ ┴└─┘┴┴ ┴┴─┘ └─┬─────────────────────┬─┘ ╚╩╝└─┘└─┘╚═╝┴ ┴ └─┘ * ┌────────────────────────────────┘ └──────────────────────────────┐ * │╔═╗┌─┐┬ ┬┌┬┐┬┌┬┐┬ ┬ ╔╦╗┌─┐┌─┐┬┌─┐┌┐┌ ╦┌┐┌┌┬┐┌─┐┬─┐┌─┐┌─┐┌─┐┌─┐ ╔═╗┌┬┐┌─┐┌─┐┬┌─│ * │╚═╗│ ││ │ │││ │ └┬┘ ═ ║║├┤ └─┐││ ┬│││ ═ ║│││ │ ├┤ ├┬┘├┤ ├─┤│ ├┤ ═ ╚═╗ │ ├─┤│ ├┴┐│ * │╚═╝└─┘┴─┘┴─┴┘┴ ┴ ┴ ═╩╝└─┘└─┘┴└─┘┘└┘ ╩┘└┘ ┴ └─┘┴└─└ ┴ ┴└─┘└─┘ ╚═╝ ┴ ┴ ┴└─┘┴ ┴│ * │ ┌──────────┐ ┌───────┐ ┌─────────┐ ┌────────┐ │ * └────┤ Inventor ├───────────┤ Justo ├────────────┤ Sumpunk ├──────────────┤ Mantso ├──┘ * └──────────┘ └───────┘ └─────────┘ └────────┘ * ┌─────────────────────────────────────────────────────────┐ ╔╦╗┬ ┬┌─┐┌┐┌┬┌─┌─┐ ╔╦╗┌─┐ * │ Ambius, Aritz Cracker, Cryptoknight, Crypto McPump, │ ║ ├─┤├─┤│││├┴┐└─┐ ║ │ │ * │ Capex, JogFera, The Shocker, Daok, Randazzz, PumpRabbi, │ ╩ ┴ ┴┴ ┴┘└┘┴ ┴└─┘ ╩ └─┘ * │ Kadaz, Incognito Jo, Lil Stronghands, Ninja Turtle, └───────────────────────────┐ * │ Psaints, Satoshi, Vitalik, Nano 2nd, Bogdanoffs Isaac Newton, Nikola Tesla, │ * │ Le Comte De Saint Germain, Albert Einstein, Socrates, & all the volunteer moderator │ * │ & support staff, content, creators, autonomous agents, and indie devs for P3D. │ * │ Without your help, we wouldn't have the time to code this. │ * └─────────────────────────────────────────────────────────────────────────────────────┘ * * This product is protected under license. Any unauthorized copy, modification, or use without * express written consent from the creators is prohibited. * * WARNING: THIS PRODUCT IS HIGHLY ADDICTIVE. IF YOU HAVE AN ADDICTIVE NATURE. DO NOT PLAY. */ //============================================================================== // _ _ _ _|_ _ . // (/_\/(/_| | | _\ . //============================================================================== import "./interface/DiviesInterface.sol"; import "./interface/otherFoMo3D.sol"; import "./interface/JIincForwarderInterface.sol"; import "./interface/PlayerBookInterface.sol"; import "./interface/F3DexternalSettingsInterface.sol"; import "./interface/HourglassInterface.sol"; import "./library/SafeMath.sol"; import "./library/UintCompressor.sol"; import "./library/NameFilter.sol"; import "./library/UintCompressor.sol"; import "./library/F3DKeysCalcLong.sol"; import "./library/F3Ddatasets.sol"; import "./modularLong.sol"; contract FoMo3Dlong is modularLong { using SafeMath for *; using NameFilter for string; using F3DKeysCalcLong for uint256; otherFoMo3D private otherF3D_; DiviesInterface constant private Divies = DiviesInterface(0xc7029Ed9EBa97A096e72607f4340c34049C7AF48); JIincForwarderInterface constant private Jekyll_Island_Inc = JIincForwarderInterface(0xdd4950F977EE28D2C132f1353D1595035Db444EE); PlayerBookInterface constant private PlayerBook = PlayerBookInterface(0xD60d353610D9a5Ca478769D371b53CEfAA7B6E4c); F3DexternalSettingsInterface constant private extSettings = F3DexternalSettingsInterface(0x32967D6c142c2F38AB39235994e2DDF11c37d590); //============================================================================== // _ _ _ |`. _ _ _ |_ | _ _ . // (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings) //=================_|=========================================================== string constant public name = "FoMo3D Long Official"; string constant public symbol = "F3D"; uint256 private rndExtra_ = extSettings.getLongExtra(); // length of the very first ICO uint256 private rndGap_ = extSettings.getLongGap(); // length of ICO phase, set to 1 year for EOS. uint256 constant private rndInit_ = 1 hours; // round timer starts at this uint256 constant private rndInc_ = 30 seconds; // every full key purchased adds this much to the timer uint256 constant private rndMax_ = 24 hours; // max length a round timer can be //============================================================================== // _| _ _|_ _ _ _ _|_ _ . // (_|(_| | (_| _\(/_ | |_||_) . (data used to store game info that changes) //=============================|================================================ uint256 public airDropPot_; // person who gets the airdrop wins part of this pot uint256 public airDropTracker_ = 0; // incremented each time a "qualified" tx occurs. used to determine winning air drop uint256 public rID_; // round id number / total rounds that have happened //**************** // PLAYER DATA //**************** mapping (address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address mapping (bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name mapping (uint256 => F3Ddatasets.Player) public plyr_; // (pID => data) player data mapping (uint256 => mapping (uint256 => F3Ddatasets.PlayerRounds)) public plyrRnds_; // (pID => rID => data) player round data by player id & round id 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) //**************** // ROUND DATA //**************** mapping (uint256 => F3Ddatasets.Round) public round_; // (rID => data) round data mapping (uint256 => mapping(uint256 => uint256)) public rndTmEth_; // (rID => tID => data) eth in per team, by round id and team id //**************** // TEAM FEE DATA , Team的费用分配数据 //**************** mapping (uint256 => F3Ddatasets.TeamFee) public fees_; // (team => fees) fee distribution by team mapping (uint256 => F3Ddatasets.PotSplit) public potSplit_; // (team => fees) pot split distribution by team //============================================================================== // _ _ _ __|_ _ __|_ _ _ . // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) //============================================================================== constructor() public { // Team allocation structures // 0 = whales // 1 = bears // 2 = sneks // 3 = bulls // Team allocation percentages // (F3D, P3D) + (Pot , Referrals, Community) // Referrals / Community rewards are mathematically designed to come from the winner's share of the pot. fees_[0] = F3Ddatasets.TeamFee(30,6); //50% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot fees_[1] = F3Ddatasets.TeamFee(43,0); //43% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot fees_[2] = F3Ddatasets.TeamFee(56,10); //20% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot fees_[3] = F3Ddatasets.TeamFee(43,8); //35% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot // how to split up the final pot based on which team was picked // (F3D, P3D) potSplit_[0] = F3Ddatasets.PotSplit(15,10); //48% to winner, 25% to next round, 2% to com potSplit_[1] = F3Ddatasets.PotSplit(25,0); //48% to winner, 25% to next round, 2% to com potSplit_[2] = F3Ddatasets.PotSplit(20,20); //48% to winner, 10% to next round, 2% to com potSplit_[3] = F3Ddatasets.PotSplit(30,10); //48% to winner, 10% to next round, 2% to com } //============================================================================== // _ _ _ _|. |`. _ _ _ . // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) //============================================================================== /** * @dev used to make sure no one can interact with contract until it has * been activated. */ modifier isActivated() { require(activated_ == true, "its not ready yet. check ?eta in discord"); _; } /** * @dev prevents contracts from interacting with fomo3d */ modifier isHuman() { address _addr = msg.sender; uint256 _codeLength; assembly {_codeLength := extcodesize(_addr)} require(_codeLength == 0, "sorry humans only"); _; } /** * @dev sets boundaries for incoming tx */ modifier isWithinLimits(uint256 _eth) { require(_eth >= 1000000000, "pocket lint: not a valid currency"); require(_eth <= 100000000000000000000000, "no vitalik, no"); _; } //============================================================================== // _ |_ |. _ |` _ __|_. _ _ _ . // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) //====|========================================================================= /** * @dev emergency buy uses last stored affiliate ID and team snek */ function() isActivated() isHuman() isWithinLimits(msg.value) public payable { // set up our tx event data and determine if player is new or not F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); // fetch player id uint256 _pID = pIDxAddr_[msg.sender]; // buy core buyCore(_pID, plyr_[_pID].laff, 2, _eventData_); } /** * @dev converts all incoming ethereum to keys. * -functionhash- 0x8f38f309 (using ID for affiliate) * -functionhash- 0x98a0871d (using address for affiliate) * -functionhash- 0xa65b37a1 (using name for affiliate) * @param _affCode the ID/address/name of the player who gets the affiliate fee * @param _team what team is the player playing for? */ function buyXid(uint256 _affCode, uint256 _team) isActivated() isHuman() isWithinLimits(msg.value) public payable { // set up our tx event data and determine if player is new or not F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); // fetch player id uint256 _pID = pIDxAddr_[msg.sender]; // manage affiliate residuals // if no affiliate code was given or player tried to use their own, lolz if (_affCode == 0 || _affCode == _pID) { // use last stored affiliate code _affCode = plyr_[_pID].laff; // if affiliate code was given & its not the same as previously stored } else if (_affCode != plyr_[_pID].laff) { // update last affiliate plyr_[_pID].laff = _affCode; } // verify a valid team was selected _team = verifyTeam(_team); // buy core buyCore(_pID, _affCode, _team, _eventData_); } function buyXaddr(address _affCode, uint256 _team) isActivated() isHuman() isWithinLimits(msg.value) public payable { // set up our tx event data and determine if player is new or not F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); // fetch player id uint256 _pID = pIDxAddr_[msg.sender]; // manage affiliate residuals uint256 _affID; // if no affiliate code was given or player tried to use their own, lolz if (_affCode == address(0) || _affCode == msg.sender) { // use last stored affiliate code _affID = plyr_[_pID].laff; // if affiliate code was given } else { // get affiliate ID from aff Code _affID = pIDxAddr_[_affCode]; // if affID is not the same as previously stored if (_affID != plyr_[_pID].laff) { // update last affiliate plyr_[_pID].laff = _affID; } } // verify a valid team was selected _team = verifyTeam(_team); // buy core buyCore(_pID, _affID, _team, _eventData_); } function buyXname(bytes32 _affCode, uint256 _team) isActivated() isHuman() isWithinLimits(msg.value) public payable { // set up our tx event data and determine if player is new or not F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); // fetch player id uint256 _pID = pIDxAddr_[msg.sender]; // manage affiliate residuals uint256 _affID; // if no affiliate code was given or player tried to use their own, lolz if (_affCode == '' || _affCode == plyr_[_pID].name) { // use last stored affiliate code _affID = plyr_[_pID].laff; // if affiliate code was given } else { // get affiliate ID from aff Code _affID = pIDxName_[_affCode]; // if affID is not the same as previously stored if (_affID != plyr_[_pID].laff) { // update last affiliate plyr_[_pID].laff = _affID; } } // verify a valid team was selected _team = verifyTeam(_team); // buy core buyCore(_pID, _affID, _team, _eventData_); } /** * @dev essentially the same as buy, but instead of you sending ether * from your wallet, it uses your unwithdrawn earnings. * -functionhash- 0x349cdcac (using ID for affiliate) * -functionhash- 0x82bfc739 (using address for affiliate) * -functionhash- 0x079ce327 (using name for affiliate) * @param _affCode the ID/address/name of the player who gets the affiliate fee * @param _team what team is the player playing for? * @param _eth amount of earnings to use (remainder returned to gen vault) */ function reLoadXid(uint256 _affCode, uint256 _team, uint256 _eth) isActivated() isHuman() isWithinLimits(_eth) public { // set up our tx event data F3Ddatasets.EventReturns memory _eventData_; // fetch player ID uint256 _pID = pIDxAddr_[msg.sender]; // manage affiliate residuals // if no affiliate code was given or player tried to use their own, lolz if (_affCode == 0 || _affCode == _pID) { // use last stored affiliate code _affCode = plyr_[_pID].laff; // if affiliate code was given & its not the same as previously stored } else if (_affCode != plyr_[_pID].laff) { // update last affiliate plyr_[_pID].laff = _affCode; } // verify a valid team was selected _team = verifyTeam(_team); // reload core reLoadCore(_pID, _affCode, _team, _eth, _eventData_); } function reLoadXaddr(address _affCode, uint256 _team, uint256 _eth) isActivated() isHuman() isWithinLimits(_eth) public { // set up our tx event data F3Ddatasets.EventReturns memory _eventData_; // fetch player ID uint256 _pID = pIDxAddr_[msg.sender]; // manage affiliate residuals uint256 _affID; // if no affiliate code was given or player tried to use their own, lolz if (_affCode == address(0) || _affCode == msg.sender) { // use last stored affiliate code _affID = plyr_[_pID].laff; // if affiliate code was given } else { // get affiliate ID from aff Code _affID = pIDxAddr_[_affCode]; // if affID is not the same as previously stored if (_affID != plyr_[_pID].laff) { // update last affiliate plyr_[_pID].laff = _affID; } } // verify a valid team was selected _team = verifyTeam(_team); // reload core reLoadCore(_pID, _affID, _team, _eth, _eventData_); } function reLoadXname(bytes32 _affCode, uint256 _team, uint256 _eth) isActivated() isHuman() isWithinLimits(_eth) public { // set up our tx event data F3Ddatasets.EventReturns memory _eventData_; // fetch player ID uint256 _pID = pIDxAddr_[msg.sender]; // manage affiliate residuals uint256 _affID; // if no affiliate code was given or player tried to use their own, lolz if (_affCode == '' || _affCode == plyr_[_pID].name) { // use last stored affiliate code _affID = plyr_[_pID].laff; // if affiliate code was given } else { // get affiliate ID from aff Code _affID = pIDxName_[_affCode]; // if affID is not the same as previously stored if (_affID != plyr_[_pID].laff) { // update last affiliate plyr_[_pID].laff = _affID; } } // verify a valid team was selected _team = verifyTeam(_team); // reload core reLoadCore(_pID, _affID, _team, _eth, _eventData_); } /** * @dev withdraws all of your earnings. * -functionhash- 0x3ccfd60b */ function withdraw() isActivated() isHuman() public { // setup local rID uint256 _rID = rID_; // grab time uint256 _now = now; // fetch player ID uint256 _pID = pIDxAddr_[msg.sender]; // setup temp var for player eth uint256 _eth; // check to see if round has ended and no one has run round end yet if (_now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) { // set up our tx event data F3Ddatasets.EventReturns memory _eventData_; // end the round (distributes pot) round_[_rID].ended = true; _eventData_ = endRound(_eventData_); // get their earnings _eth = withdrawEarnings(_pID); // gib moni if (_eth > 0) plyr_[_pID].addr.transfer(_eth); // build event data _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; // fire withdraw and distribute event emit F3Devents.onWithdrawAndDistribute ( msg.sender, plyr_[_pID].name, _eth, _eventData_.compressedData, _eventData_.compressedIDs, _eventData_.winnerAddr, _eventData_.winnerName, _eventData_.amountWon, _eventData_.newPot, _eventData_.P3DAmount, _eventData_.genAmount ); // in any other situation } else { // get their earnings _eth = withdrawEarnings(_pID); // gib moni if (_eth > 0) plyr_[_pID].addr.transfer(_eth); // fire withdraw event emit F3Devents.onWithdraw(_pID, msg.sender, plyr_[_pID].name, _eth, _now); } } /** * @dev use these to register names. they are just wrappers that will send the * registration requests to the PlayerBook contract. So registering here is the * same as registering there. UI will always display the last name you registered. * but you will still own all previously registered names to use as affiliate * links. * - must pay a registration fee. * - name must be unique * - names will be converted to lowercase * - name cannot start or end with a space * - cannot have more than 1 space in a row * - cannot be only numbers * - cannot start with 0x * - name must be at least 1 char * - max length of 32 characters long * - allowed characters: a-z, 0-9, and space * -functionhash- 0x921dec21 (using ID for affiliate) * -functionhash- 0x3ddd4698 (using address for affiliate) * -functionhash- 0x685ffd83 (using name for affiliate) * @param _nameString players desired name * @param _affCode affiliate ID, address, or name of who referred you * @param _all set to true if you want this to push your info to all games * (this might cost a lot of gas) */ function registerNameXID(string _nameString, uint256 _affCode, bool _all) isHuman() public payable { bytes32 _name = _nameString.nameFilter(); address _addr = msg.sender; uint256 _paid = msg.value; (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXIDFromDapp.value(_paid)(_addr, _name, _affCode, _all); uint256 _pID = pIDxAddr_[_addr]; // fire event emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); } function registerNameXaddr(string _nameString, address _affCode, bool _all) isHuman() public payable { bytes32 _name = _nameString.nameFilter(); address _addr = msg.sender; uint256 _paid = msg.value; (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXaddrFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); uint256 _pID = pIDxAddr_[_addr]; // fire event emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); } function registerNameXname(string _nameString, bytes32 _affCode, bool _all) isHuman() public payable { bytes32 _name = _nameString.nameFilter(); address _addr = msg.sender; uint256 _paid = msg.value; (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXnameFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); uint256 _pID = pIDxAddr_[_addr]; // fire event emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); } //============================================================================== // _ _ _|__|_ _ _ _ . // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) //=====_|======================================================================= /** * @dev return the price buyer will pay for next 1 individual key. * -functionhash- 0x018a25e8 * @return price for next key bought (in wei format) */ function getBuyPrice() public view returns(uint256) { // setup local rID uint256 _rID = rID_; // grab time uint256 _now = now; // are we in a round? if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) return ( (round_[_rID].keys.add(1000000000000000000)).ethRec(1000000000000000000) ); else // rounds over. need price for new round return ( 75000000000000 ); // init } /** * @dev returns time left. dont spam this, you'll ddos yourself from your node * provider * -functionhash- 0xc7e284b8 * @return time left in seconds */ function getTimeLeft() public view returns(uint256) { // setup local rID uint256 _rID = rID_; // grab time uint256 _now = now; if (_now < round_[_rID].end) if (_now > round_[_rID].strt + rndGap_) return( (round_[_rID].end).sub(_now) ); else return( (round_[_rID].strt + rndGap_).sub(_now) ); else return(0); } /** * @dev returns player earnings per vaults * -functionhash- 0x63066434 * @return winnings vault * @return general vault * @return affiliate vault */ function getPlayerVaults(uint256 _pID) public view returns(uint256 ,uint256, uint256) { // setup local rID uint256 _rID = rID_; // if round has ended. but round end has not been run (so contract has not distributed winnings) if (now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) { // if player is winner if (round_[_rID].plyr == _pID) { return ( (plyr_[_pID].win).add( ((round_[_rID].pot).mul(48)) / 100 ), (plyr_[_pID].gen).add( getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask) ), plyr_[_pID].aff ); // if player is not the winner } else { return ( plyr_[_pID].win, (plyr_[_pID].gen).add( getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask) ), plyr_[_pID].aff ); } // if round is still going on, or round has ended and round end has been ran } else { return ( plyr_[_pID].win, (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), plyr_[_pID].aff ); } } /** * solidity hates stack limits. this lets us avoid that hate */ function getPlayerVaultsHelper(uint256 _pID, uint256 _rID) private view returns(uint256) { 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) ); } /** * @dev returns all current round info needed for front end * -functionhash- 0x747dff42 * @return eth invested during ICO phase * @return round id * @return total keys for round * @return time round ends * @return time round started * @return current pot * @return current team ID & player ID in lead * @return current player in leads address * @return current player in leads name * @return whales eth in for round * @return bears eth in for round * @return sneks eth in for round * @return bulls eth in for round * @return airdrop tracker # & airdrop pot */ function getCurrentRoundInfo() public view returns(uint256, uint256, uint256, uint256, uint256, uint256, uint256, address, bytes32, uint256, uint256, uint256, uint256, uint256) { // setup local rID uint256 _rID = rID_; return ( round_[_rID].ico, //0 _rID, //1 round_[_rID].keys, //2 round_[_rID].end, //3 round_[_rID].strt, //4 round_[_rID].pot, //5 (round_[_rID].team + (round_[_rID].plyr * 10)), //6 plyr_[round_[_rID].plyr].addr, //7 plyr_[round_[_rID].plyr].name, //8 rndTmEth_[_rID][0], //9 rndTmEth_[_rID][1], //10 rndTmEth_[_rID][2], //11 rndTmEth_[_rID][3], //12 airDropTracker_ + (airDropPot_ * 1000) //13 ); } /** * @dev returns player info based on address. if no address is given, it will * use msg.sender * -functionhash- 0xee0b5d8b * @param _addr address of the player you want to lookup * @return player ID * @return player name * @return keys owned (current round) * @return winnings vault * @return general vault * @return affiliate vault * @return player round eth */ function getPlayerInfoByAddress(address _addr) public view returns(uint256, bytes32, uint256, uint256, uint256, uint256, uint256) { // setup local rID uint256 _rID = rID_; if (_addr == address(0)) { _addr == msg.sender; } uint256 _pID = pIDxAddr_[_addr]; return ( _pID, //0 plyr_[_pID].name, //1 plyrRnds_[_pID][_rID].keys, //2 plyr_[_pID].win, //3 (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), //4 plyr_[_pID].aff, //5 plyrRnds_[_pID][_rID].eth //6 ); } //============================================================================== // _ _ _ _ | _ _ . _ . // (_(_)| (/_ |(_)(_||(_ . (this + tools + calcs + modules = our softwares engine) //=====================_|======================================================= /** * @dev logic runs whenever a buy order is executed. determines how to handle * incoming eth depending on if we are in an active round or not */ function buyCore(uint256 _pID, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) private { // setup local rID uint256 _rID = rID_; // grab time uint256 _now = now; // if round is active if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) { // call core core(_rID, _pID, msg.value, _affID, _team, _eventData_); // if round is not active } else { // check to see if end round needs to be ran if (_now > round_[_rID].end && round_[_rID].ended == false) { // end the round (distributes pot) & start new round round_[_rID].ended = true; _eventData_ = endRound(_eventData_); // build event data _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; // fire buy and distribute event emit F3Devents.onBuyAndDistribute ( msg.sender, plyr_[_pID].name, msg.value, _eventData_.compressedData, _eventData_.compressedIDs, _eventData_.winnerAddr, _eventData_.winnerName, _eventData_.amountWon, _eventData_.newPot, _eventData_.P3DAmount, _eventData_.genAmount ); } // put eth in players vault plyr_[_pID].gen = plyr_[_pID].gen.add(msg.value); } } /** * @dev logic runs whenever a reload order is executed. determines how to handle * incoming eth depending on if we are in an active round or not */ function reLoadCore(uint256 _pID, uint256 _affID, uint256 _team, uint256 _eth, F3Ddatasets.EventReturns memory _eventData_) private { // setup local rID uint256 _rID = rID_; // grab time uint256 _now = now; // if round is active if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) { // get earnings from all vaults and return unused to gen vault // because we use a custom safemath library. this will throw if player // tried to spend more eth than they have. plyr_[_pID].gen = withdrawEarnings(_pID).sub(_eth); // call core core(_rID, _pID, _eth, _affID, _team, _eventData_); // if round is not active and end round needs to be ran } else if (_now > round_[_rID].end && round_[_rID].ended == false) { // end the round (distributes pot) & start new round round_[_rID].ended = true; _eventData_ = endRound(_eventData_); // build event data _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; // fire buy and distribute event emit F3Devents.onReLoadAndDistribute ( msg.sender, plyr_[_pID].name, _eventData_.compressedData, _eventData_.compressedIDs, _eventData_.winnerAddr, _eventData_.winnerName, _eventData_.amountWon, _eventData_.newPot, _eventData_.P3DAmount, _eventData_.genAmount ); } } /** * @dev this is the core logic for any buy/reload that happens while a round * is live. */ function core(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) private { // if player is new to round if (plyrRnds_[_pID][_rID].keys == 0) _eventData_ = managePlayer(_pID, _eventData_); // early round eth limiter if (round_[_rID].eth < 100000000000000000000 && plyrRnds_[_pID][_rID].eth.add(_eth) > 1000000000000000000) { uint256 _availableLimit = (1000000000000000000).sub(plyrRnds_[_pID][_rID].eth); uint256 _refund = _eth.sub(_availableLimit); plyr_[_pID].gen = plyr_[_pID].gen.add(_refund); _eth = _availableLimit; } // if eth left is greater than min eth allowed (sorry no pocket lint) if (_eth > 1000000000) { // mint the new keys uint256 _keys = (round_[_rID].eth).keysRec(_eth); // if they bought at least 1 whole key if (_keys >= 1000000000000000000) { updateTimer(_keys, _rID); // set new leaders if (round_[_rID].plyr != _pID) round_[_rID].plyr = _pID; if (round_[_rID].team != _team) round_[_rID].team = _team; // set the new leader bool to true _eventData_.compressedData = _eventData_.compressedData + 100; } // manage airdrops if (_eth >= 100000000000000000) { airDropTracker_++; if (airdrop() == true) { // gib muni uint256 _prize; if (_eth >= 10000000000000000000) { // calculate prize and give it to winner _prize = ((airDropPot_).mul(75)) / 100; plyr_[_pID].win = (plyr_[_pID].win).add(_prize); // adjust airDropPot airDropPot_ = (airDropPot_).sub(_prize); // let event know a tier 3 prize was won _eventData_.compressedData += 300000000000000000000000000000000; } else if (_eth >= 1000000000000000000 && _eth < 10000000000000000000) { // calculate prize and give it to winner _prize = ((airDropPot_).mul(50)) / 100; plyr_[_pID].win = (plyr_[_pID].win).add(_prize); // adjust airDropPot airDropPot_ = (airDropPot_).sub(_prize); // let event know a tier 2 prize was won _eventData_.compressedData += 200000000000000000000000000000000; } else if (_eth >= 100000000000000000 && _eth < 1000000000000000000) { // calculate prize and give it to winner _prize = ((airDropPot_).mul(25)) / 100; plyr_[_pID].win = (plyr_[_pID].win).add(_prize); // adjust airDropPot airDropPot_ = (airDropPot_).sub(_prize); // let event know a tier 3 prize was won _eventData_.compressedData += 300000000000000000000000000000000; } // set airdrop happened bool to true _eventData_.compressedData += 10000000000000000000000000000000; // let event know how much was won _eventData_.compressedData += _prize * 1000000000000000000000000000000000; // reset air drop tracker airDropTracker_ = 0; } } // store the air drop tracker number (number of buys since last airdrop) _eventData_.compressedData = _eventData_.compressedData + (airDropTracker_ * 1000); // update player plyrRnds_[_pID][_rID].keys = _keys.add(plyrRnds_[_pID][_rID].keys); plyrRnds_[_pID][_rID].eth = _eth.add(plyrRnds_[_pID][_rID].eth); // update round round_[_rID].keys = _keys.add(round_[_rID].keys); round_[_rID].eth = _eth.add(round_[_rID].eth); rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]); // distribute eth _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_); _eventData_ = distributeInternal(_rID, _pID, _eth, _team, _keys, _eventData_); // call end tx function to fire end tx event. endTx(_pID, _team, _eth, _keys, _eventData_); } } //============================================================================== // _ _ | _ | _ _|_ _ _ _ . // (_(_||(_|_||(_| | (_)| _\ . //============================================================================== /** * @dev calculates unmasked earnings (just calculates, does not update mask) * @return earnings in wei format */ function calcUnMaskedEarnings(uint256 _pID, uint256 _rIDlast) private view returns(uint256) { return( (((round_[_rIDlast].mask).mul(plyrRnds_[_pID][_rIDlast].keys)) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask) ); } /** * @dev returns the amount of keys you would get given an amount of eth. * -functionhash- 0xce89c80c * @param _rID round ID you want price for * @param _eth amount of eth sent in * @return keys received */ function calcKeysReceived(uint256 _rID, uint256 _eth) public view returns(uint256) { // grab time uint256 _now = now; // are we in a round? if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) return ( (round_[_rID].eth).keysRec(_eth) ); else // rounds over. need keys for new round return ( (_eth).keys() ); } /** * @dev returns current eth price for X keys. * -functionhash- 0xcf808000 * @param _keys number of keys desired (in 18 decimal format) * @return amount of eth needed to send */ function iWantXKeys(uint256 _keys) public view returns(uint256) { // setup local rID uint256 _rID = rID_; // grab time uint256 _now = now; // are we in a round? if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) return ( (round_[_rID].keys.add(_keys)).ethRec(_keys) ); else // rounds over. need price for new round return ( (_keys).eth() ); } //============================================================================== // _|_ _ _ | _ . // | (_)(_)|_\ . //============================================================================== /** * @dev receives name/player info from names contract */ function receivePlayerInfo(uint256 _pID, address _addr, bytes32 _name, uint256 _laff) external { require (msg.sender == address(PlayerBook), "your not playerNames contract... hmmm.."); if (pIDxAddr_[_addr] != _pID) pIDxAddr_[_addr] = _pID; if (pIDxName_[_name] != _pID) pIDxName_[_name] = _pID; if (plyr_[_pID].addr != _addr) plyr_[_pID].addr = _addr; if (plyr_[_pID].name != _name) plyr_[_pID].name = _name; if (plyr_[_pID].laff != _laff) plyr_[_pID].laff = _laff; if (plyrNames_[_pID][_name] == false) plyrNames_[_pID][_name] = true; } /** * @dev receives entire player name list */ function receivePlayerNameList(uint256 _pID, bytes32 _name) external { require (msg.sender == address(PlayerBook), "your not playerNames contract... hmmm.."); if(plyrNames_[_pID][_name] == false) plyrNames_[_pID][_name] = true; } /** * @dev gets existing or registers new pID. use this when a player may be new * @return pID */ function determinePID(F3Ddatasets.EventReturns memory _eventData_) private returns (F3Ddatasets.EventReturns) { uint256 _pID = pIDxAddr_[msg.sender]; // if player is new to this version of fomo3d if (_pID == 0) { // grab their player ID, name and last aff ID, from player names contract _pID = PlayerBook.getPlayerID(msg.sender); bytes32 _name = PlayerBook.getPlayerName(_pID); uint256 _laff = PlayerBook.getPlayerLAff(_pID); // set up player account pIDxAddr_[msg.sender] = _pID; plyr_[_pID].addr = msg.sender; if (_name != "") { pIDxName_[_name] = _pID; plyr_[_pID].name = _name; plyrNames_[_pID][_name] = true; } if (_laff != 0 && _laff != _pID) plyr_[_pID].laff = _laff; // set the new player bool to true _eventData_.compressedData = _eventData_.compressedData + 1; } return (_eventData_); } /** * @dev checks to make sure user picked a valid team. if not sets team * to default (sneks) */ function verifyTeam(uint256 _team) private pure returns (uint256) { if (_team < 0 || _team > 3) return(2); else return(_team); } /** * @dev decides if round end needs to be run & new round started. and if * player unmasked earnings from previously played rounds need to be moved. */ function managePlayer(uint256 _pID, F3Ddatasets.EventReturns memory _eventData_) private returns (F3Ddatasets.EventReturns) { // if player has played a previous round, move their unmasked earnings // from that round to gen vault. if (plyr_[_pID].lrnd != 0) updateGenVault(_pID, plyr_[_pID].lrnd); // update player's last round played plyr_[_pID].lrnd = rID_; // set the joined round bool to true _eventData_.compressedData = _eventData_.compressedData + 10; return(_eventData_); } /** * @dev ends the round. manages paying out winner/splitting up pot */ function endRound(F3Ddatasets.EventReturns memory _eventData_) private returns (F3Ddatasets.EventReturns) { // setup local rID uint256 _rID = rID_; // grab our winning player and team id's uint256 _winPID = round_[_rID].plyr; uint256 _winTID = round_[_rID].team; // grab our pot amount uint256 _pot = round_[_rID].pot; // calculate our winner share, community rewards, gen share, // p3d share, and amount reserved for next pot uint256 _win = (_pot.mul(48)) / 100; uint256 _com = (_pot / 50); uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100; uint256 _p3d = (_pot.mul(potSplit_[_winTID].p3d)) / 100; uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen)).sub(_p3d); // calculate ppt for round mask uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); uint256 _dust = _gen.sub((_ppt.mul(round_[_rID].keys)) / 1000000000000000000); if (_dust > 0) { _gen = _gen.sub(_dust); _res = _res.add(_dust); } // pay our winner plyr_[_winPID].win = _win.add(plyr_[_winPID].win); // community rewards if (!address(Jekyll_Island_Inc).call.value(_com)(bytes4(keccak256("deposit()")))) { // This ensures Team Just cannot influence the outcome of FoMo3D with // bank migrations by breaking outgoing transactions. // Something we would never do. But that's not the point. // We spent 2000$ in eth re-deploying just to patch this, we hold the // highest belief that everything we create should be trustless. // Team JUST, The name you shouldn't have to trust. _p3d = _p3d.add(_com); _com = 0; } // distribute gen portion to key holders round_[_rID].mask = _ppt.add(round_[_rID].mask); // send share for p3d to divies if (_p3d > 0) Divies.deposit.value(_p3d)(); // prepare event data _eventData_.compressedData = _eventData_.compressedData + (round_[_rID].end * 1000000); _eventData_.compressedIDs = _eventData_.compressedIDs + (_winPID * 100000000000000000000000000) + (_winTID * 100000000000000000); _eventData_.winnerAddr = plyr_[_winPID].addr; _eventData_.winnerName = plyr_[_winPID].name; _eventData_.amountWon = _win; _eventData_.genAmount = _gen; _eventData_.P3DAmount = _p3d; _eventData_.newPot = _res; // start next round rID_++; _rID++; round_[_rID].strt = now; round_[_rID].end = now.add(rndInit_).add(rndGap_); round_[_rID].pot = _res; return(_eventData_); } /** * @dev moves any unmasked earnings to gen vault. updates earnings mask */ function updateGenVault(uint256 _pID, uint256 _rIDlast) private { uint256 _earnings = calcUnMaskedEarnings(_pID, _rIDlast); if (_earnings > 0) { // put in gen vault plyr_[_pID].gen = _earnings.add(plyr_[_pID].gen); // zero out their earnings by updating mask plyrRnds_[_pID][_rIDlast].mask = _earnings.add(plyrRnds_[_pID][_rIDlast].mask); } } /** * @dev updates round timer based on number of whole keys bought. */ function updateTimer(uint256 _keys, uint256 _rID) private { // grab time uint256 _now = now; // calculate time based on number of keys bought uint256 _newTime; if (_now > round_[_rID].end && round_[_rID].plyr == 0) _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(_now); else _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(round_[_rID].end); // compare to max and set new end time if (_newTime < (rndMax_).add(_now)) round_[_rID].end = _newTime; else round_[_rID].end = rndMax_.add(_now); } /** * @dev generates a random number between 0-99 and checks to see if thats * resulted in an airdrop win * @return do we have a winner? */ function airdrop() private view returns(bool) { uint256 seed = uint256(keccak256(abi.encodePacked( (block.timestamp).add (block.difficulty).add ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add (block.gaslimit).add ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add (block.number) ))); if((seed - ((seed / 1000) * 1000)) < airDropTracker_) return(true); else return(false); } /** * @dev distributes eth based on fees to com, aff, and p3d */ function distributeExternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) private returns(F3Ddatasets.EventReturns) { // pay 2% out to community rewards uint256 _com = _eth / 50; uint256 _p3d; if (!address(Jekyll_Island_Inc).call.value(_com)(bytes4(keccak256("deposit()")))) { // This ensures Team Just cannot influence the outcome of FoMo3D with // bank migrations by breaking outgoing transactions. // Something we would never do. But that's not the point. // We spent 2000$ in eth re-deploying just to patch this, we hold the // highest belief that everything we create should be trustless. // Team JUST, The name you shouldn't have to trust. _p3d = _com; _com = 0; } // pay 1% out to FoMo3D short uint256 _long = _eth / 100; otherF3D_.potSwap.value(_long)(); // distribute share to affiliate uint256 _aff = _eth / 10; // decide what to do with affiliate share of fees // affiliate must not be self, and must have a name registered if (_affID != _pID && plyr_[_affID].name != '') { plyr_[_affID].aff = _aff.add(plyr_[_affID].aff); emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _aff, now); } else { _p3d = _aff; } // pay out p3d _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100)); if (_p3d > 0) { // deposit to divies contract Divies.deposit.value(_p3d)(); // set up event data _eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount); } return(_eventData_); } function potSwap() external payable { // setup local rID uint256 _rID = rID_ + 1; round_[_rID].pot = round_[_rID].pot.add(msg.value); emit F3Devents.onPotSwapDeposit(_rID, msg.value); } /** * @dev distributes eth based on fees to gen and pot */ function distributeInternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _team, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) private returns(F3Ddatasets.EventReturns) { // calculate gen share uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100; // toss 1% into airdrop pot uint256 _air = (_eth / 100); airDropPot_ = airDropPot_.add(_air); // update eth balance (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share)) _eth = _eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100)); // calculate pot uint256 _pot = _eth.sub(_gen); // distribute gen share (thats what updateMasks() does) and adjust // balances for dust. uint256 _dust = updateMasks(_rID, _pID, _gen, _keys); if (_dust > 0) _gen = _gen.sub(_dust); // add eth to pot round_[_rID].pot = _pot.add(_dust).add(round_[_rID].pot); // set up event data _eventData_.genAmount = _gen.add(_eventData_.genAmount); _eventData_.potAmount = _pot; return(_eventData_); } /** * @dev updates masks for round and player when keys are bought * @return dust left over */ function updateMasks(uint256 _rID, uint256 _pID, uint256 _gen, uint256 _keys) private returns(uint256) { /* MASKING NOTES earnings masks are a tricky thing for people to wrap their minds around. the basic thing to understand here. is were going to have a global tracker based on profit per share for each round, that increases in relevant proportion to the increase in share supply. the player will have an additional mask that basically says "based on the rounds mask, my shares, and how much i've already withdrawn, how much is still owed to me?" */ // calc profit per key & round mask based on this buy: (dust goes to pot) uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); round_[_rID].mask = _ppt.add(round_[_rID].mask); // calculate player earning from their own buy (only based on the keys // they just bought). & update player earnings mask uint256 _pearn = (_ppt.mul(_keys)) / (1000000000000000000); plyrRnds_[_pID][_rID].mask = (((round_[_rID].mask.mul(_keys)) / (1000000000000000000)).sub(_pearn)).add(plyrRnds_[_pID][_rID].mask); // calculate & return dust return(_gen.sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000))); } /** * @dev adds up unmasked earnings, & vault earnings, sets them all to 0 * @return earnings in wei format */ function withdrawEarnings(uint256 _pID) private returns(uint256) { // update gen vault updateGenVault(_pID, plyr_[_pID].lrnd); // from vaults uint256 _earnings = (plyr_[_pID].win).add(plyr_[_pID].gen).add(plyr_[_pID].aff); if (_earnings > 0) { plyr_[_pID].win = 0; plyr_[_pID].gen = 0; plyr_[_pID].aff = 0; } return(_earnings); } /** * @dev prepares compression data and fires event for buy or reload tx's */ function endTx(uint256 _pID, uint256 _team, uint256 _eth, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) private { _eventData_.compressedData = _eventData_.compressedData + (now * 1000000000000000000) + (_team * 100000000000000000000000000000); _eventData_.compressedIDs = _eventData_.compressedIDs + _pID + (rID_ * 10000000000000000000000000000000000000000000000000000); emit F3Devents.onEndTx ( _eventData_.compressedData, _eventData_.compressedIDs, plyr_[_pID].name, msg.sender, _eth, _keys, _eventData_.winnerAddr, _eventData_.winnerName, _eventData_.amountWon, _eventData_.newPot, _eventData_.P3DAmount, _eventData_.genAmount, _eventData_.potAmount, airDropPot_ ); } //============================================================================== // (~ _ _ _._|_ . // _)(/_(_|_|| | | \/ . //====================/========================================================= /** upon contract deploy, it will be deactivated. this is a one time * use function that will activate the contract. we do this so devs * have time to set things up on the web end **/ bool public activated_ = false; function activate() public { // only team just can activate require( msg.sender == 0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C || msg.sender == 0x8b4DA1827932D71759687f925D17F81Fc94e3A9D || msg.sender == 0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53 || msg.sender == 0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C || msg.sender == 0xF39e044e1AB204460e06E87c6dca2c6319fC69E3, "only team just can activate" ); // make sure that its been linked. require(address(otherF3D_) != address(0), "must link to other FoMo3D first"); // can only be ran once require(activated_ == false, "fomo3d already activated"); // activate the contract activated_ = true; // lets start first round rID_ = 1; round_[1].strt = now + rndExtra_ - rndGap_; round_[1].end = now + rndInit_ + rndExtra_; } function setOtherFomo(address _otherF3D) public { // only team just can activate require( msg.sender == 0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C || msg.sender == 0x8b4DA1827932D71759687f925D17F81Fc94e3A9D || msg.sender == 0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53 || msg.sender == 0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C || msg.sender == 0xF39e044e1AB204460e06E87c6dca2c6319fC69E3, "only team just can activate" ); // make sure that it HASNT yet been linked. require(address(otherF3D_) == address(0), "silly dev, you already did that"); // set up other fomo3d (fast or long) for pot swap otherF3D_ = otherFoMo3D(_otherF3D); } } ================================================ FILE: contracts/Hourglass.sol ================================================ pragma solidity ^0.4.24; /* * Team JUST presents.. * ====================================* * _____ _ _ _ _____ ___ ____ * *| _ |___| | | | | | |_ | \ * *| __| . | | | | | |_ | | | * *|__| |___|_____|__|__| |___|____/ * * * * ====================================* * -> What? * The original autonomous pyramid, improved: * [x] More stable than ever, having withstood severe testnet abuse and attack attempts from our community!. * [x] Audited, tested, and approved by known community security specialists such as tocsick and Arc. * [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! * [x] New functionality; you can now transfer tokens between wallets. Trading is now possible from within the contract! * [x] New Feature: PoS Masternodes! The first implementation of Ethereum Staking in the world! Vitalik is mad. * [x] Masternodes: Holding 100 PoWH3D Tokens allow you to generate a Masternode link, Masternode links are used as unique entry points to the contract! * [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! * * -> What about the last projects? * Every programming member of the old dev team has been fired and/or killed by 232. * The new dev team consists of seasoned, professional developers and has been audited by veteran solidity experts. * Additionally, two independent testnet iterations have been used by hundreds of people; not a single point of failure was found. * * -> Who worked on this project? * - PonziBot (math/memes/main site/master) * - Mantso (lead solidity dev/lead web3 dev) * - swagg (concept design/feedback/management) * - Anonymous#1 (main site/web3/test cases) * - Anonymous#2 (math formulae/whitepaper) * * -> Who has audited & approved the projected: * - Arc * - tocisck * - sumpunk */ import "./library/SafeMath.sol"; contract Hourglass { /*================================= = MODIFIERS = =================================*/ // only people with tokens modifier onlyBagholders() { require(myTokens() > 0); _; } // only people with profits modifier onlyStronghands() { require(myDividends(true) > 0); _; } // administrators can: // -> change the name of the contract // -> change the name of the token // -> change the PoS difficulty (How many tokens it costs to hold a masternode, in case it gets crazy high later) // they CANNOT: // -> take funds // -> disable withdrawals // -> kill the contract // -> change the price of tokens modifier onlyAdministrator(){ address _customerAddress = msg.sender; require(administrators[keccak256(_customerAddress)]); _; } // ensures that the first tokens in the contract will be equally distributed // meaning, no divine dump will be ever possible // result: healthy longevity. modifier antiEarlyWhale(uint256 _amountOfEthereum){ address _customerAddress = msg.sender; // are we still in the vulnerable phase? // if so, enact anti early whale protocol if( onlyAmbassadors && ((totalEthereumBalance() - _amountOfEthereum) <= ambassadorQuota_ )){ require( // is the customer in the ambassador list? ambassadors_[_customerAddress] == true && // does the customer purchase exceed the max ambassador quota? (ambassadorAccumulatedQuota_[_customerAddress] + _amountOfEthereum) <= ambassadorMaxPurchase_ ); // updated the accumulated quota ambassadorAccumulatedQuota_[_customerAddress] = SafeMath.add(ambassadorAccumulatedQuota_[_customerAddress], _amountOfEthereum); // execute _; } else { // in case the ether count drops low, the ambassador phase won't reinitiate onlyAmbassadors = false; _; } } /*============================== = EVENTS = ==============================*/ event onTokenPurchase( address indexed customerAddress, uint256 incomingEthereum, uint256 tokensMinted, address indexed referredBy ); event onTokenSell( address indexed customerAddress, uint256 tokensBurned, uint256 ethereumEarned ); event onReinvestment( address indexed customerAddress, uint256 ethereumReinvested, uint256 tokensMinted ); event onWithdraw( address indexed customerAddress, uint256 ethereumWithdrawn ); // ERC20 event Transfer( address indexed from, address indexed to, uint256 tokens ); /*===================================== = CONFIGURABLES = =====================================*/ string public name = "PowH3D"; string public symbol = "P3D"; uint8 constant public decimals = 18; uint8 constant internal dividendFee_ = 10; uint256 constant internal tokenPriceInitial_ = 0.0000001 ether; uint256 constant internal tokenPriceIncremental_ = 0.00000001 ether; uint256 constant internal magnitude = 2**64; // proof of stake (defaults at 100 tokens) uint256 public stakingRequirement = 100e18; // ambassador program mapping(address => bool) internal ambassadors_; uint256 constant internal ambassadorMaxPurchase_ = 1 ether; uint256 constant internal ambassadorQuota_ = 20 ether; /*================================ = DATASETS = ================================*/ // amount of shares for each address (scaled number) mapping(address => uint256) internal tokenBalanceLedger_; mapping(address => uint256) internal referralBalance_; mapping(address => int256) internal payoutsTo_; mapping(address => uint256) internal ambassadorAccumulatedQuota_; uint256 internal tokenSupply_ = 0; uint256 internal profitPerShare_; // administrator list (see above on what they can do) mapping(bytes32 => bool) public administrators; // when this is set to true, only ambassadors can purchase tokens (this prevents a whale premine, it ensures a fairly distributed upper pyramid) bool public onlyAmbassadors = true; /*======================================= = PUBLIC FUNCTIONS = =======================================*/ /* * -- APPLICATION ENTRY POINTS -- */ function Hourglass() public { // add administrators here administrators[0xdd8bb99b13fe33e1c32254dfb8fff3e71193f6b730a89dd33bfe5dedc6d83002] = true; // add the ambassadors here. // mantso - lead solidity dev & lead web dev. ambassadors_[0x8b4DA1827932D71759687f925D17F81Fc94e3A9D] = true; // ponzibot - mathematics & website, and undisputed meme god. ambassadors_[0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53] = true; // swagg - concept design, feedback, management. ambassadors_[0x7563A35d5610eE7c9CD330E255Da0e779a644C19] = true; // k-dawgz - shilling machine, meme maestro, bizman. ambassadors_[0x215e3C713BADb158A457e61f99325bBB5d278E57] = true; // elmojo - all those pretty .GIFs & memes you see? you can thank this man for that. ambassadors_[0xaFF8B5CDCB339eEf5e1100597740a394C7B9c6cA] = true; // capex - community moderator. ambassadors_[0x8dc6569c28521560EAF1890bC41b2F3FC2010E1b] = true; // jörmungandr - pentests & twitter trendsetter. ambassadors_[0xf14BE3662FE4c9215c27698166759Db6967De94f] = true; // inventor - the source behind the non-intrusive referral model. ambassadors_[0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C] = true; // tocsick - pentesting, contract auditing. ambassadors_[0x49Aae4D923207e80Fc91E626BCb6532502264dfC] = true; // arc - pentesting, contract auditing. ambassadors_[0x3a0cca1A832644B60730E5D4c27947C5De609d62] = true; // sumpunk - contract auditing. ambassadors_[0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C] = true; // randall - charts & sheets, data dissector, advisor. ambassadors_[0x2b219C2178f099dE4E9A3667d5cCc2cc64da0763] = true; // ambius - 3d chart visualization. ambassadors_[0x2A04C7335f90a6bd4e9c4F713DD792200e27F2E6] = true; // contributors that need to remain private out of security concerns. ambassadors_[0x35668818ba8F768D4C21787a6f45C86C69394dfD] = true; //dp ambassadors_[0xa3120da52e604aC3Fc80A63813Ef15476e0B6AbD] = true; //tc ambassadors_[0x924E71bA600372e2410285423F1Fe66799b717EC] = true; //ja ambassadors_[0x6Ed450e062C20F929CB7Ee72fCc53e9697980a18] = true; //sf ambassadors_[0x18864A6682c8EB79EEA5B899F11bC94ef9a85ADb] = true; //tb ambassadors_[0x9cC1BdC994b7a847705D19106287C0BF94EF04B5] = true; //sm ambassadors_[0x6926572813ec1438088963f208C61847df435a74] = true; //mc ambassadors_[0xE16Ab764a02Ae03681E351Ac58FE79717c0eE8C6] = true; //et ambassadors_[0x276F4a79F22D1BfC51Bd8dc5b27Bfd934C823932] = true; //sn ambassadors_[0xA2b4ed3E2f4beF09FB35101B76Ef4cB9D3eeCaCf] = true; //bt ambassadors_[0x147fc6b04c95BCE47D013c8d7a200ee434323669] = true; //al } /** * Converts all incoming ethereum to tokens for the caller, and passes down the referral addy (if any) */ function buy(address _referredBy) public payable returns(uint256) { purchaseTokens(msg.value, _referredBy); } /** * Fallback function to handle ethereum that was send straight to the contract * Unfortunately we cannot use a referral address this way. */ function() payable public { purchaseTokens(msg.value, 0x0); } /** * Converts all of caller's dividends to tokens. */ function reinvest() onlyStronghands() public { // fetch dividends uint256 _dividends = myDividends(false); // retrieve ref. bonus later in the code // pay out the dividends virtually address _customerAddress = msg.sender; payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); // retrieve ref. bonus _dividends += referralBalance_[_customerAddress]; referralBalance_[_customerAddress] = 0; // dispatch a buy order with the virtualized "withdrawn dividends" uint256 _tokens = purchaseTokens(_dividends, 0x0); // fire event onReinvestment(_customerAddress, _dividends, _tokens); } /** * Alias of sell() and withdraw(). */ function exit() public { // get token count for caller & sell them all address _customerAddress = msg.sender; uint256 _tokens = tokenBalanceLedger_[_customerAddress]; if(_tokens > 0) sell(_tokens); // lambo delivery service withdraw(); } /** * Withdraws all of the callers earnings. */ function withdraw() onlyStronghands() public { // setup data address _customerAddress = msg.sender; uint256 _dividends = myDividends(false); // get ref. bonus later in the code // update dividend tracker payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); // add ref. bonus _dividends += referralBalance_[_customerAddress]; referralBalance_[_customerAddress] = 0; // lambo delivery service _customerAddress.transfer(_dividends); // fire event onWithdraw(_customerAddress, _dividends); } /** * Liquifies tokens to ethereum. */ function sell(uint256 _amountOfTokens) onlyBagholders() public { // setup data address _customerAddress = msg.sender; // russian hackers BTFO require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); uint256 _tokens = _amountOfTokens; uint256 _ethereum = tokensToEthereum_(_tokens); uint256 _dividends = SafeMath.div(_ethereum, dividendFee_); uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); // burn the sold tokens tokenSupply_ = SafeMath.sub(tokenSupply_, _tokens); tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _tokens); // update dividends tracker int256 _updatedPayouts = (int256) (profitPerShare_ * _tokens + (_taxedEthereum * magnitude)); payoutsTo_[_customerAddress] -= _updatedPayouts; // dividing by zero is a bad idea if (tokenSupply_ > 0) { // update the amount of dividends per token profitPerShare_ = SafeMath.add(profitPerShare_, (_dividends * magnitude) / tokenSupply_); } // fire event onTokenSell(_customerAddress, _tokens, _taxedEthereum); } /** * Transfer tokens from the caller to a new holder. * Remember, there's a 10% fee here as well. */ function transfer(address _toAddress, uint256 _amountOfTokens) onlyBagholders() public returns(bool) { // setup address _customerAddress = msg.sender; // make sure we have the requested tokens // also disables transfers until ambassador phase is over // ( we dont want whale premines ) require(!onlyAmbassadors && _amountOfTokens <= tokenBalanceLedger_[_customerAddress]); // withdraw all outstanding dividends first if(myDividends(true) > 0) withdraw(); // liquify 10% of the tokens that are transfered // these are dispersed to shareholders uint256 _tokenFee = SafeMath.div(_amountOfTokens, dividendFee_); uint256 _taxedTokens = SafeMath.sub(_amountOfTokens, _tokenFee); uint256 _dividends = tokensToEthereum_(_tokenFee); // burn the fee tokens tokenSupply_ = SafeMath.sub(tokenSupply_, _tokenFee); // exchange tokens tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens); tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _taxedTokens); // update dividend trackers payoutsTo_[_customerAddress] -= (int256) (profitPerShare_ * _amountOfTokens); payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _taxedTokens); // disperse dividends among holders profitPerShare_ = SafeMath.add(profitPerShare_, (_dividends * magnitude) / tokenSupply_); // fire event Transfer(_customerAddress, _toAddress, _taxedTokens); // ERC20 return true; } /*---------- ADMINISTRATOR ONLY FUNCTIONS ----------*/ /** * In case the amassador quota is not met, the administrator can manually disable the ambassador phase. */ function disableInitialStage() onlyAdministrator() public { onlyAmbassadors = false; } /** * In case one of us dies, we need to replace ourselves. */ function setAdministrator(bytes32 _identifier, bool _status) onlyAdministrator() public { administrators[_identifier] = _status; } /** * Precautionary measures in case we need to adjust the masternode rate. */ function setStakingRequirement(uint256 _amountOfTokens) onlyAdministrator() public { stakingRequirement = _amountOfTokens; } /** * If we want to rebrand, we can. */ function setName(string _name) onlyAdministrator() public { name = _name; } /** * If we want to rebrand, we can. */ function setSymbol(string _symbol) onlyAdministrator() public { symbol = _symbol; } /*---------- HELPERS AND CALCULATORS ----------*/ /** * Method to view the current Ethereum stored in the contract * Example: totalEthereumBalance() */ function totalEthereumBalance() public view returns(uint) { return this.balance; } /** * Retrieve the total token supply. */ function totalSupply() public view returns(uint256) { return tokenSupply_; } /** * Retrieve the tokens owned by the caller. */ function myTokens() public view returns(uint256) { address _customerAddress = msg.sender; return balanceOf(_customerAddress); } /** * Retrieve the dividends owned by the caller. * If `_includeReferralBonus` is to to 1/true, the referral bonus will be included in the calculations. * The reason for this, is that in the frontend, we will want to get the total divs (global + ref) * But in the internal calculations, we want them separate. */ function myDividends(bool _includeReferralBonus) public view returns(uint256) { address _customerAddress = msg.sender; return _includeReferralBonus ? dividendsOf(_customerAddress) + referralBalance_[_customerAddress] : dividendsOf(_customerAddress) ; } /** * Retrieve the token balance of any single address. */ function balanceOf(address _customerAddress) view public returns(uint256) { return tokenBalanceLedger_[_customerAddress]; } /** * Retrieve the dividend balance of any single address. */ function dividendsOf(address _customerAddress) view public returns(uint256) { return (uint256) ((int256)(profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude; } /** * Return the buy price of 1 individual token. */ function sellPrice() public view returns(uint256) { // our calculation relies on the token supply, so we need supply. Doh. if(tokenSupply_ == 0){ return tokenPriceInitial_ - tokenPriceIncremental_; } else { uint256 _ethereum = tokensToEthereum_(1e18); uint256 _dividends = SafeMath.div(_ethereum, dividendFee_ ); uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); return _taxedEthereum; } } /** * Return the sell price of 1 individual token. */ function buyPrice() public view returns(uint256) { // our calculation relies on the token supply, so we need supply. Doh. if(tokenSupply_ == 0){ return tokenPriceInitial_ + tokenPriceIncremental_; } else { uint256 _ethereum = tokensToEthereum_(1e18); uint256 _dividends = SafeMath.div(_ethereum, dividendFee_ ); uint256 _taxedEthereum = SafeMath.add(_ethereum, _dividends); return _taxedEthereum; } } /** * Function for the frontend to dynamically retrieve the price scaling of buy orders. */ function calculateTokensReceived(uint256 _ethereumToSpend) public view returns(uint256) { uint256 _dividends = SafeMath.div(_ethereumToSpend, dividendFee_); uint256 _taxedEthereum = SafeMath.sub(_ethereumToSpend, _dividends); uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); return _amountOfTokens; } /** * Function for the frontend to dynamically retrieve the price scaling of sell orders. */ function calculateEthereumReceived(uint256 _tokensToSell) public view returns(uint256) { require(_tokensToSell <= tokenSupply_); uint256 _ethereum = tokensToEthereum_(_tokensToSell); uint256 _dividends = SafeMath.div(_ethereum, dividendFee_); uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); return _taxedEthereum; } /*========================================== = INTERNAL FUNCTIONS = ==========================================*/ function purchaseTokens(uint256 _incomingEthereum, address _referredBy) antiEarlyWhale(_incomingEthereum) internal returns(uint256) { // data setup address _customerAddress = msg.sender; uint256 _undividedDividends = SafeMath.div(_incomingEthereum, dividendFee_); // 分红 0.1 uint256 _referralBonus = SafeMath.div(_undividedDividends, 3); // 分红的三分之一给推广员 uint256 _dividends = SafeMath.sub(_undividedDividends, _referralBonus); // 真正属于分红的钱 uint256 _taxedEthereum = SafeMath.sub(_incomingEthereum, _undividedDividends); // 扣完分红后的钱,用来买币 uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); uint256 _fee = _dividends * magnitude; // no point in continuing execution if OP is a poorfag russian hacker // prevents overflow in the case that the pyramid somehow magically starts being used by everyone in the world // (or hackers) // and yes we know that the safemath function automatically rules out the "greater then" equasion. require(_amountOfTokens > 0 && (SafeMath.add(_amountOfTokens,tokenSupply_) > tokenSupply_)); // is the user referred by a masternode? if( // is this a referred purchase? _referredBy != 0x0000000000000000000000000000000000000000 && // no cheating! _referredBy != _customerAddress && // does the referrer have at least X whole tokens? // i.e is the referrer a godly chad masternode tokenBalanceLedger_[_referredBy] >= stakingRequirement ){ // wealth redistribution referralBalance_[_referredBy] = SafeMath.add(referralBalance_[_referredBy], _referralBonus); } else { // no ref purchase // add the referral bonus back to the global dividends cake _dividends = SafeMath.add(_dividends, _referralBonus); _fee = _dividends * magnitude; } // we can't give people infinite ethereum if(tokenSupply_ > 0){ // add tokens to the pool tokenSupply_ = SafeMath.add(tokenSupply_, _amountOfTokens); // take the amount of dividends gained through this transaction, and allocates them evenly to each shareholder profitPerShare_ += (_dividends * magnitude / (tokenSupply_)); // calculate the amount of tokens the customer receives over his purchase _fee = _fee - (_fee-(_amountOfTokens * (_dividends * magnitude / (tokenSupply_)))); } else { // add tokens to the pool tokenSupply_ = _amountOfTokens; } // update circulating supply & the ledger address for the customer tokenBalanceLedger_[_customerAddress] = SafeMath.add(tokenBalanceLedger_[_customerAddress], _amountOfTokens); // Tells the contract that the buyer doesn't deserve dividends for the tokens before they owned them; //really i know you think you do but you don't int256 _updatedPayouts = (int256) ((profitPerShare_ * _amountOfTokens) - _fee); payoutsTo_[_customerAddress] += _updatedPayouts; // fire event onTokenPurchase(_customerAddress, _incomingEthereum, _amountOfTokens, _referredBy); return _amountOfTokens; } /** * Calculate Token price based on an amount of incoming ethereum * It's an algorithm, hopefully we gave you the whitepaper with it in scientific notation; * Some conversions occurred to prevent decimal errors or underflows / overflows in solidity code. */ function ethereumToTokens_(uint256 _ethereum) internal view returns(uint256) { uint256 _tokenPriceInitial = tokenPriceInitial_ * 1e18; uint256 _tokensReceived = ( ( // underflow attempts BTFO SafeMath.sub( (sqrt ( (_tokenPriceInitial**2) + (2*(tokenPriceIncremental_ * 1e18)*(_ethereum * 1e18)) + (((tokenPriceIncremental_)**2)*(tokenSupply_**2)) + (2*(tokenPriceIncremental_)*_tokenPriceInitial*tokenSupply_) ) ), _tokenPriceInitial ) )/(tokenPriceIncremental_) )-(tokenSupply_) ; return _tokensReceived; } /** * Calculate token sell value. * It's an algorithm, hopefully we gave you the whitepaper with it in scientific notation; * Some conversions occurred to prevent decimal errors or underflows / overflows in solidity code. */ function tokensToEthereum_(uint256 _tokens) internal view returns(uint256) { uint256 tokens_ = (_tokens + 1e18); uint256 _tokenSupply = (tokenSupply_ + 1e18); uint256 _etherReceived = ( // underflow attempts BTFO SafeMath.sub( ( ( ( tokenPriceInitial_ +(tokenPriceIncremental_ * (_tokenSupply/1e18)) )-tokenPriceIncremental_ )*(tokens_ - 1e18) ),(tokenPriceIncremental_*((tokens_**2-tokens_)/1e18))/2 ) /1e18); return _etherReceived; } //This is where all your gas goes, sorry //Not sorry, you probably only paid 1 gwei function sqrt(uint x) internal pure returns (uint y) { uint z = (x + 1) / 2; y = x; while (z < y) { y = z; z = (x / z + z) / 2; } } } ================================================ FILE: contracts/JIincForwarder.sol ================================================ pragma solidity ^0.4.24; /* * @title -Jekyll Island- CORP BANK FORWARDER v0.4.6 * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ * _____ _____ * (, / /) /) /) (, / /) /) * ┌─┐ / _ (/_ // // / _ // _ __ _(/ * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ * ┴ ┴ / / .-/ _____ (__ / * (__ / (_/ (, / /)™ * / __ __ __ __ _ __ __ _ _/_ _ _(/ * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ *====/$$$$$===========/$$=================/$$ /$$====/$$$$$$===========/$$===========================/$$=* * |__ $$ | $$ | $$| $$ |_ $$_/ | $$ | $$ * | $$ /$$$$$$ | $$ /$$ /$$ /$$| $$| $$ | $$ /$$$$$$$| $$ /$$$$$$ /$$$$$$$ /$$$$$$$ * | $$ /$$__ $$| $$ /$$/| $$ | $$| $$| $$ | $$ /$$_____/| $$ |____ $$| $$__ $$ /$$__ $$ * /$$ | $$| $$$$$$$$| $$$$$$/ | $$ | $$| $$| $$ | $$ | $$$$$$ | $$ /$$$$$$$| $$ \ $$| $$ | $$ *| $$ | $$| $$_____/| $$_ $$ | $$ | $$| $$| $$ | $$ \____ $$| $$ /$$__ $$| $$ | $$| $$ | $$ *| $$$$$$/| $$$$$$$| $$ \ $$| $$$$$$$| $$| $$ /$$$$$$ /$$$$$$$/| $$| $$$$$$$| $$ | $$| $$$$$$$ * \______/ \_______/|__/ \__/ \____ $$|__/|__/ |______/|_______/ |__/ \_______/|__/ |__/ \_______/ *===============================/$$ | $$ Inc. ╔═╗╔═╗╦═╗╔═╗ ╔╗ ╔═╗╔╗╔╦╔═ ┌─┐┌─┐┬─┐┬ ┬┌─┐┬─┐┌┬┐┌─┐┬─┐ * | $$$$$$/=======║ ║ ║╠╦╝╠═╝ ╠╩╗╠═╣║║║╠╩╗ ├┤ │ │├┬┘│││├─┤├┬┘ ││├┤ ├┬┘ * \______/ ╚═╝╚═╝╩╚═╩ ╚═╝╩ ╩╝╚╝╩ ╩ └ └─┘┴└─└┴┘┴ ┴┴└──┴┘└─┘┴└─==* * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ *===========================================================================================* * ┌────────────────────┐ * │ Setup Instructions │ * └────────────────────┘ * (Step 1) import the Jekyll Island Inc Forwarder Interface into your contract * * import "./JIincForwarderInterface.sol"; * * (Step 2) set it to point to the forwarder * * JIincForwarderInterface private Jekyll_Island_Inc = JIincForwarderInterface(0xdd4950F977EE28D2C132f1353D1595035Db444EE); * ┌────────────────────┐ * │ Usage Instructions │ * └────────────────────┘ * whenever your contract needs to send eth to the corp bank, simply use the * the following command: * * Jekyll_Island_Inc.deposit.value(amount)() * * OPTIONAL: * if you need to be checking wither the transaction was successful, the deposit function returns * a bool indicating wither or not it was successful. so another way to call this function * would be: * * require(Jekyll_Island_Inc.deposit.value(amount)() == true, "Jekyll Island deposit failed"); * */ interface JIincInterfaceForForwarder { function deposit(address _addr) external payable returns (bool); function migrationReceiver_setup() external returns (bool); } contract JIincForwarder { string public name = "JIincForwarder"; JIincInterfaceForForwarder private currentCorpBank_; address private newCorpBank_; bool needsBank_ = true; constructor() public { //constructor does nothing. } function() public payable { // done so that if any one tries to dump eth into this contract, we can // just forward it to corp bank. currentCorpBank_.deposit.value(address(this).balance)(address(currentCorpBank_)); } function deposit() public payable returns(bool) { require(msg.value > 0, "Forwarder Deposit failed - zero deposits not allowed"); require(needsBank_ == false, "Forwarder Deposit failed - no registered bank"); if (currentCorpBank_.deposit.value(msg.value)(msg.sender) == true) return(true); else return(false); } //============================================================================== // _ _ . _ _ _ _|_. _ _ . // | | ||(_|| (_| | |(_)| | . //===========_|================================================================= function status() public view returns(address, address, bool) { return(address(currentCorpBank_), address(newCorpBank_), needsBank_); } function startMigration(address _newCorpBank) external returns(bool) { // make sure this is coming from current corp bank require(msg.sender == address(currentCorpBank_), "Forwarder startMigration failed - msg.sender must be current corp bank"); // communicate with the new corp bank and make sure it has the forwarder // registered if(JIincInterfaceForForwarder(_newCorpBank).migrationReceiver_setup() == true) { // save our new corp bank address newCorpBank_ = _newCorpBank; return (true); } else return (false); } function cancelMigration() external returns(bool) { // make sure this is coming from the current corp bank (also lets us know // that current corp bank has not been killed) require(msg.sender == address(currentCorpBank_), "Forwarder cancelMigration failed - msg.sender must be current corp bank"); // erase stored new corp bank address; newCorpBank_ = address(0x0); return (true); } function finishMigration() external returns(bool) { // make sure its coming from new corp bank require(msg.sender == newCorpBank_, "Forwarder finishMigration failed - msg.sender must be new corp bank"); // update corp bank address currentCorpBank_ = (JIincInterfaceForForwarder(newCorpBank_)); // erase new corp bank address newCorpBank_ = address(0x0); return (true); } //============================================================================== // . _ ._|_. _ | _ _ _|_ _ . // || || | |(_|| _\(/_ | |_||_) . (this only runs once ever) //==============================|=============================================== function setup(address _firstCorpBank) external { require(needsBank_ == true, "Forwarder setup failed - corp bank already registered"); currentCorpBank_ = JIincInterfaceForForwarder(_firstCorpBank); needsBank_ = false; } } ================================================ FILE: contracts/PlayerBook.sol ================================================ pragma solidity ^0.4.24; /* * -PlayerBook - v0.3.14 * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ * _____ _____ * (, / /) /) /) (, / /) /) * ┌─┐ / _ (/_ // // / _ // _ __ _(/ * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ * ┴ ┴ / / .-/ _____ (__ / * (__ / (_/ (, / /)™ * / __ __ __ __ _ __ __ _ _/_ _ _(/ * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ * ______ _ ______ _ *====(_____ \=| |===============================(____ \===============| |=============* * _____) )| | _____ _ _ _____ ____ ____) ) ___ ___ | | _ * | ____/ | | (____ || | | || ___ | / ___) | __ ( / _ \ / _ \ | |_/ ) * | | | | / ___ || |_| || ____|| | | |__) )| |_| || |_| || _ ( *====|_|=======\_)\_____|=\__ ||_____)|_|======|______/==\___/==\___/=|_|=\_)=========* * (____/ * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ */ import "./library/SafeMath.sol"; import "./library/NameFilter.sol"; import "./library/MSFun.sol"; import "./interface/TeamJustInterface.sol"; import "./interface/JIincForwarderInterface.sol"; import "./interface/PlayerBookReceiverInterface.sol"; contract PlayerBook { using NameFilter for string; using SafeMath for uint256; JIincForwarderInterface constant private Jekyll_Island_Inc = JIincForwarderInterface(0xdd4950F977EE28D2C132f1353D1595035Db444EE); TeamJustInterface constant private TeamJust = TeamJustInterface(0x464904238b5CdBdCE12722A7E6014EC1C0B66928); MSFun.Data private msData; function multiSigDev(bytes32 _whatFunction) private returns (bool) {return(MSFun.multiSig(msData, TeamJust.requiredDevSignatures(), _whatFunction));} function deleteProposal(bytes32 _whatFunction) private {MSFun.deleteProposal(msData, _whatFunction);} function deleteAnyProposal(bytes32 _whatFunction) onlyDevs() public {MSFun.deleteProposal(msData, _whatFunction);} function checkData(bytes32 _whatFunction) onlyDevs() public view returns(bytes32, uint256) {return(MSFun.checkMsgData(msData, _whatFunction), MSFun.checkCount(msData, _whatFunction));} 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));} 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)));} //============================================================================== // _| _ _|_ _ _ _ _|_ _ . // (_|(_| | (_| _\(/_ | |_||_) . //=============================|================================================ uint256 public registrationFee_ = 10 finney; // price to register a name mapping(uint256 => PlayerBookReceiverInterface) public games_; // mapping of our game interfaces for sending your account info to games mapping(address => bytes32) public gameNames_; // lookup a games name mapping(address => uint256) public gameIDs_; // lokup a games ID uint256 public gID_; // total number of games uint256 public pID_; // total number of players mapping (address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address mapping (bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name mapping (uint256 => Player) public plyr_; // (pID => data) player data 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) mapping (uint256 => mapping (uint256 => bytes32)) public plyrNameList_; // (pID => nameNum => name) list of names a player owns struct Player { address addr; bytes32 name; uint256 laff; uint256 names; } //============================================================================== // _ _ _ __|_ _ __|_ _ _ . // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) //============================================================================== constructor() public { // premine the dev names (sorry not sorry) // No keys are purchased with this method, it's simply locking our addresses, // PID's and names for referral codes. plyr_[1].addr = 0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53; plyr_[1].name = "justo"; plyr_[1].names = 1; pIDxAddr_[0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53] = 1; pIDxName_["justo"] = 1; plyrNames_[1]["justo"] = true; plyrNameList_[1][1] = "justo"; plyr_[2].addr = 0x8b4DA1827932D71759687f925D17F81Fc94e3A9D; plyr_[2].name = "mantso"; plyr_[2].names = 1; pIDxAddr_[0x8b4DA1827932D71759687f925D17F81Fc94e3A9D] = 2; pIDxName_["mantso"] = 2; plyrNames_[2]["mantso"] = true; plyrNameList_[2][1] = "mantso"; plyr_[3].addr = 0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C; plyr_[3].name = "sumpunk"; plyr_[3].names = 1; pIDxAddr_[0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C] = 3; pIDxName_["sumpunk"] = 3; plyrNames_[3]["sumpunk"] = true; plyrNameList_[3][1] = "sumpunk"; plyr_[4].addr = 0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C; plyr_[4].name = "inventor"; plyr_[4].names = 1; pIDxAddr_[0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C] = 4; pIDxName_["inventor"] = 4; plyrNames_[4]["inventor"] = true; plyrNameList_[4][1] = "inventor"; pID_ = 4; } //============================================================================== // _ _ _ _|. |`. _ _ _ . // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) //============================================================================== /** * @dev prevents contracts from interacting with fomo3d */ modifier isHuman() { address _addr = msg.sender; uint256 _codeLength; assembly {_codeLength := extcodesize(_addr)} require(_codeLength == 0, "sorry humans only"); _; } modifier onlyDevs() { require(TeamJust.isDev(msg.sender) == true, "msg sender is not a dev"); _; } modifier isRegisteredGame() { require(gameIDs_[msg.sender] != 0); _; } //============================================================================== // _ _ _ _|_ _ . // (/_\/(/_| | | _\ . //============================================================================== // fired whenever a player registers a name event onNewName ( uint256 indexed playerID, address indexed playerAddress, bytes32 indexed playerName, bool isNewPlayer, uint256 affiliateID, address affiliateAddress, bytes32 affiliateName, uint256 amountPaid, uint256 timeStamp ); //============================================================================== // _ _ _|__|_ _ _ _ . // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) //=====_|======================================================================= function checkIfNameValid(string _nameStr) public view returns(bool) { bytes32 _name = _nameStr.nameFilter(); if (pIDxName_[_name] == 0) return (true); else return (false); } //============================================================================== // _ |_ |. _ |` _ __|_. _ _ _ . // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) //====|========================================================================= /** * @dev registers a name. UI will always display the last name you registered. * but you will still own all previously registered names to use as affiliate * links. * - must pay a registration fee. * - name must be unique * - names will be converted to lowercase * - name cannot start or end with a space * - cannot have more than 1 space in a row * - cannot be only numbers * - cannot start with 0x * - name must be at least 1 char * - max length of 32 characters long * - allowed characters: a-z, 0-9, and space * -functionhash- 0x921dec21 (using ID for affiliate) * -functionhash- 0x3ddd4698 (using address for affiliate) * -functionhash- 0x685ffd83 (using name for affiliate) * @param _nameString players desired name * @param _affCode affiliate ID, address, or name of who refered you * @param _all set to true if you want this to push your info to all games * (this might cost a lot of gas) */ function registerNameXID(string _nameString, uint256 _affCode, bool _all) isHuman() public payable { // make sure name fees paid require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); // filter name + condition checks bytes32 _name = NameFilter.nameFilter(_nameString); // set up address address _addr = msg.sender; // set up our tx event data and determine if player is new or not bool _isNewPlayer = determinePID(_addr); // fetch player id uint256 _pID = pIDxAddr_[_addr]; // manage affiliate residuals // if no affiliate code was given, no new affiliate code was given, or the // player tried to use their own pID as an affiliate code, lolz if (_affCode != 0 && _affCode != plyr_[_pID].laff && _affCode != _pID) { // update last affiliate plyr_[_pID].laff = _affCode; } else if (_affCode == _pID) { _affCode = 0; } // register name registerNameCore(_pID, _addr, _affCode, _name, _isNewPlayer, _all); } function registerNameXaddr(string _nameString, address _affCode, bool _all) isHuman() public payable { // make sure name fees paid require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); // filter name + condition checks bytes32 _name = NameFilter.nameFilter(_nameString); // set up address address _addr = msg.sender; // set up our tx event data and determine if player is new or not bool _isNewPlayer = determinePID(_addr); // fetch player id uint256 _pID = pIDxAddr_[_addr]; // manage affiliate residuals // if no affiliate code was given or player tried to use their own, lolz uint256 _affID; if (_affCode != address(0) && _affCode != _addr) { // get affiliate ID from aff Code _affID = pIDxAddr_[_affCode]; // if affID is not the same as previously stored if (_affID != plyr_[_pID].laff) { // update last affiliate plyr_[_pID].laff = _affID; } } // register name registerNameCore(_pID, _addr, _affID, _name, _isNewPlayer, _all); } function registerNameXname(string _nameString, bytes32 _affCode, bool _all) isHuman() public payable { // make sure name fees paid require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); // filter name + condition checks bytes32 _name = NameFilter.nameFilter(_nameString); // set up address address _addr = msg.sender; // set up our tx event data and determine if player is new or not bool _isNewPlayer = determinePID(_addr); // fetch player id uint256 _pID = pIDxAddr_[_addr]; // manage affiliate residuals // if no affiliate code was given or player tried to use their own, lolz uint256 _affID; if (_affCode != "" && _affCode != _name) { // get affiliate ID from aff Code _affID = pIDxName_[_affCode]; // if affID is not the same as previously stored if (_affID != plyr_[_pID].laff) { // update last affiliate plyr_[_pID].laff = _affID; } } // register name registerNameCore(_pID, _addr, _affID, _name, _isNewPlayer, _all); } /** * @dev players, if you registered a profile, before a game was released, or * set the all bool to false when you registered, use this function to push * your profile to a single game. also, if you've updated your name, you * can use this to push your name to games of your choosing. * -functionhash- 0x81c5b206 * @param _gameID game id */ function addMeToGame(uint256 _gameID) isHuman() public { require(_gameID <= gID_, "silly player, that game doesn't exist yet"); address _addr = msg.sender; uint256 _pID = pIDxAddr_[_addr]; require(_pID != 0, "hey there buddy, you dont even have an account"); uint256 _totalNames = plyr_[_pID].names; // add players profile and most recent name games_[_gameID].receivePlayerInfo(_pID, _addr, plyr_[_pID].name, plyr_[_pID].laff); // add list of all names if (_totalNames > 1) for (uint256 ii = 1; ii <= _totalNames; ii++) games_[_gameID].receivePlayerNameList(_pID, plyrNameList_[_pID][ii]); } /** * @dev players, use this to push your player profile to all registered games. * -functionhash- 0x0c6940ea */ function addMeToAllGames() isHuman() public { address _addr = msg.sender; uint256 _pID = pIDxAddr_[_addr]; require(_pID != 0, "hey there buddy, you dont even have an account"); uint256 _laff = plyr_[_pID].laff; uint256 _totalNames = plyr_[_pID].names; bytes32 _name = plyr_[_pID].name; for (uint256 i = 1; i <= gID_; i++) { games_[i].receivePlayerInfo(_pID, _addr, _name, _laff); if (_totalNames > 1) for (uint256 ii = 1; ii <= _totalNames; ii++) games_[i].receivePlayerNameList(_pID, plyrNameList_[_pID][ii]); } } /** * @dev players use this to change back to one of your old names. tip, you'll * still need to push that info to existing games. * -functionhash- 0xb9291296 * @param _nameString the name you want to use */ function useMyOldName(string _nameString) isHuman() public { // filter name, and get pID bytes32 _name = _nameString.nameFilter(); uint256 _pID = pIDxAddr_[msg.sender]; // make sure they own the name require(plyrNames_[_pID][_name] == true, "umm... thats not a name you own"); // update their current name plyr_[_pID].name = _name; } //============================================================================== // _ _ _ _ | _ _ . _ . // (_(_)| (/_ |(_)(_||(_ . //=====================_|======================================================= function registerNameCore(uint256 _pID, address _addr, uint256 _affID, bytes32 _name, bool _isNewPlayer, bool _all) private { // if names already has been used, require that current msg sender owns the name if (pIDxName_[_name] != 0) require(plyrNames_[_pID][_name] == true, "sorry that names already taken"); // add name to player profile, registry, and name book plyr_[_pID].name = _name; pIDxName_[_name] = _pID; if (plyrNames_[_pID][_name] == false) { plyrNames_[_pID][_name] = true; plyr_[_pID].names++; plyrNameList_[_pID][plyr_[_pID].names] = _name; } // registration fee goes directly to community rewards Jekyll_Island_Inc.deposit.value(address(this).balance)(); // push player info to games if (_all == true) for (uint256 i = 1; i <= gID_; i++) games_[i].receivePlayerInfo(_pID, _addr, _name, _affID); // fire event emit onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, msg.value, now); } //============================================================================== // _|_ _ _ | _ . // | (_)(_)|_\ . //============================================================================== function determinePID(address _addr) private returns (bool) { if (pIDxAddr_[_addr] == 0) { pID_++; pIDxAddr_[_addr] = pID_; plyr_[pID_].addr = _addr; // set the new player bool to true return (true); } else { return (false); } } //============================================================================== // _ _|_ _ _ _ _ | _ _ || _ . // (/_>< | (/_| | |(_|| (_(_|||_\ . //============================================================================== function getPlayerID(address _addr) isRegisteredGame() external returns (uint256) { determinePID(_addr); return (pIDxAddr_[_addr]); } function getPlayerName(uint256 _pID) external view returns (bytes32) { return (plyr_[_pID].name); } function getPlayerLAff(uint256 _pID) external view returns (uint256) { return (plyr_[_pID].laff); } function getPlayerAddr(uint256 _pID) external view returns (address) { return (plyr_[_pID].addr); } function getNameFee() external view returns (uint256) { return(registrationFee_); } function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) isRegisteredGame() external payable returns(bool, uint256) { // make sure name fees paid require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); // set up our tx event data and determine if player is new or not bool _isNewPlayer = determinePID(_addr); // fetch player id uint256 _pID = pIDxAddr_[_addr]; // manage affiliate residuals // if no affiliate code was given, no new affiliate code was given, or the // player tried to use their own pID as an affiliate code, lolz uint256 _affID = _affCode; if (_affID != 0 && _affID != plyr_[_pID].laff && _affID != _pID) { // update last affiliate plyr_[_pID].laff = _affID; } else if (_affID == _pID) { _affID = 0; } // register name registerNameCore(_pID, _addr, _affID, _name, _isNewPlayer, _all); return(_isNewPlayer, _affID); } function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) isRegisteredGame() external payable returns(bool, uint256) { // make sure name fees paid require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); // set up our tx event data and determine if player is new or not bool _isNewPlayer = determinePID(_addr); // fetch player id uint256 _pID = pIDxAddr_[_addr]; // manage affiliate residuals // if no affiliate code was given or player tried to use their own, lolz uint256 _affID; if (_affCode != address(0) && _affCode != _addr) { // get affiliate ID from aff Code _affID = pIDxAddr_[_affCode]; // if affID is not the same as previously stored if (_affID != plyr_[_pID].laff) { // update last affiliate plyr_[_pID].laff = _affID; } } // register name registerNameCore(_pID, _addr, _affID, _name, _isNewPlayer, _all); return(_isNewPlayer, _affID); } function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) isRegisteredGame() external payable returns(bool, uint256) { // make sure name fees paid require (msg.value >= registrationFee_, "umm..... you have to pay the name fee"); // set up our tx event data and determine if player is new or not bool _isNewPlayer = determinePID(_addr); // fetch player id uint256 _pID = pIDxAddr_[_addr]; // manage affiliate residuals // if no affiliate code was given or player tried to use their own, lolz uint256 _affID; if (_affCode != "" && _affCode != _name) { // get affiliate ID from aff Code _affID = pIDxName_[_affCode]; // if affID is not the same as previously stored if (_affID != plyr_[_pID].laff) { // update last affiliate plyr_[_pID].laff = _affID; } } // register name registerNameCore(_pID, _addr, _affID, _name, _isNewPlayer, _all); return(_isNewPlayer, _affID); } //============================================================================== // _ _ _|_ _ . // _\(/_ | |_||_) . //=============|================================================================ function addGame(address _gameAddress, string _gameNameStr) onlyDevs() public { require(gameIDs_[_gameAddress] == 0, "derp, that games already been registered"); if (multiSigDev("addGame") == true) {deleteProposal("addGame"); gID_++; bytes32 _name = _gameNameStr.nameFilter(); gameIDs_[_gameAddress] = gID_; gameNames_[_gameAddress] = _name; games_[gID_] = PlayerBookReceiverInterface(_gameAddress); games_[gID_].receivePlayerInfo(1, plyr_[1].addr, plyr_[1].name, 0); games_[gID_].receivePlayerInfo(2, plyr_[2].addr, plyr_[2].name, 0); games_[gID_].receivePlayerInfo(3, plyr_[3].addr, plyr_[3].name, 0); games_[gID_].receivePlayerInfo(4, plyr_[4].addr, plyr_[4].name, 0); } } function setRegistrationFee(uint256 _fee) onlyDevs() public { if (multiSigDev("setRegistrationFee") == true) {deleteProposal("setRegistrationFee"); registrationFee_ = _fee; } } } ================================================ FILE: contracts/TeamJust.sol ================================================ pragma solidity ^0.4.24; /* -Team Just- v0.2.5 * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ * _____ _____ * (, / /) /) /) (, / /) /) * ┌─┐ / _ (/_ // // / _ // _ __ _(/ * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ * ┴ ┴ / / .-/ _____ (__ / * (__ / (_/ (, / /)™ * / __ __ __ __ _ __ __ _ _/_ _ _(/ * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ * JJJJJJJJJJUUUUUUUU UUUUUUUU SSSSSSSSSSSSSSSTTTTTTTTTTTTTTTTTTTTTTT *==============J:::::::::U::::::U=====U::::::USS:::::::::::::::T:::::::::::::::::::::T======* * J:::::::::U::::::U U::::::S:::::SSSSSS::::::T:::::::::::::::::::::T * JJ:::::::JUU:::::U U:::::US:::::S SSSSSST:::::TT:::::::TT:::::T * J:::::J U:::::U U:::::US:::::S TTTTTT T:::::T TTTTTT * J::_________ : ________::::US::_::S ____ ____ T:::::T * J:| _ _ |:|_ __ |:::U S/ \:SSSS |_ \ / _| T:::::T * J:|_/:| |U\_|::D| |_ \_|:::U / _ \::::SSS| \/ | T:::::T * J:::::| |U:::::D| _| _::::U/ ___ \::::::| |\ /| | T:::::T * JJJJJJJ J::::_| |_:::::_| |__/ |::_/ / \ \_SS _| |_\/_| |_ T:::::T * J:::::J J:::|_____|:::|________|:|____| |____| |_____||_____| T:::::T * J::::::J J::::::J U::::::U U::::::U S:::::S T:::::T * J:::::::JJJ:::::::J U:::::::UUU:::::::USSSSSSS S:::::S TT:::::::TT * JJ:::::::::::::JJ UU:::::::::::::UU S::::::SSSSSS:::::S T:::::::::T *=======JJ:::::::::JJ========UU:::::::::UU===S:::::::::::::::SS======T:::::::::T============* * JJJJJJJJJ UUUUUUUUU SSSSSSSSSSSSSSS TTTTTTTTTTT * * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ * * ┌──────────────────────────────────────────────────────────────────────┐ * │ Que up intensely spectacular intro music... In walks, Team Just. │ * │ Everyone goes crazy. │ * │ This is a companion to MSFun. It's a central database of Devs and │ * │ Admin's that we can import to any dapp to allow them management │ * │ permissions. │ * └──────────────────────────────────────────────────────────────────────┘ * ┌────────────────────┐ * │ Setup Instructions │ * └────────────────────┘ * (Step 1) import this contracts interface into your contract * * import "./TeamJustInterface.sol"; * * (Step 2) set up the interface to point to the TeamJust contract * * TeamJustInterface constant TeamJust = TeamJustInterface(0x464904238b5CdBdCE12722A7E6014EC1C0B66928); * * modifier onlyAdmins() {require(TeamJust.isAdmin(msg.sender) == true, "onlyAdmins failed - msg.sender is not an admin"); _;} * modifier onlyDevs() {require(TeamJust.isDev(msg.sender) == true, "onlyDevs failed - msg.sender is not a dev"); _;} * ┌────────────────────┐ * │ Usage Instructions │ * └────────────────────┘ * use onlyAdmins() and onlyDevs() modifiers as you normally would on any function * you wish to restrict to admins/devs registered with this contract. * * to get required signatures for admins or devs * uint256 x = TeamJust.requiredSignatures(); * uint256 x = TeamJust.requiredDevSignatures(); * * to get admin count or dev count * uint256 x = TeamJust.adminCount(); * uint256 x = TeamJust.devCount(); * * to get the name of an admin (in bytes32 format) * bytes32 x = TeamJust.adminName(address); */ import "./library/SafeMath.sol"; import "./library/NameFilter.sol"; import "./library/MSFun.sol"; import "./interface/TeamJustInterface.sol"; import "./interface/JIincForwarderInterface.sol"; import "./interface/PlayerBookReceiverInterface.sol"; contract TeamJust { JIincForwarderInterface private Jekyll_Island_Inc = JIincForwarderInterface(0x0); //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // SET UP MSFun (note, check signers by name is modified from MSFun sdk) //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ MSFun.Data private msData; function deleteAnyProposal(bytes32 _whatFunction) onlyDevs() public {MSFun.deleteProposal(msData, _whatFunction);} function checkData(bytes32 _whatFunction) onlyAdmins() public view returns(bytes32 message_data, uint256 signature_count) {return(MSFun.checkMsgData(msData, _whatFunction), MSFun.checkCount(msData, _whatFunction));} 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)));} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // DATA SETUP //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ struct Admin { bool isAdmin; bool isDev; bytes32 name; } mapping (address => Admin) admins_; uint256 adminCount_; uint256 devCount_; uint256 requiredSignatures_; uint256 requiredDevSignatures_; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // CONSTRUCTOR //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructor() public { address inventor = 0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C; address mantso = 0x8b4DA1827932D71759687f925D17F81Fc94e3A9D; address justo = 0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53; address sumpunk = 0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C; address deployer = 0xF39e044e1AB204460e06E87c6dca2c6319fC69E3; admins_[inventor] = Admin(true, true, "inventor"); admins_[mantso] = Admin(true, true, "mantso"); admins_[justo] = Admin(true, true, "justo"); admins_[sumpunk] = Admin(true, true, "sumpunk"); admins_[deployer] = Admin(true, true, "deployer"); adminCount_ = 5; devCount_ = 5; requiredSignatures_ = 1; requiredDevSignatures_ = 1; } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // FALLBACK, SETUP, AND FORWARD //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // there should never be a balance in this contract. but if someone // does stupidly send eth here for some reason. we can forward it // to jekyll island function () public payable { Jekyll_Island_Inc.deposit.value(address(this).balance)(); } function setup(address _addr) onlyDevs() public { require( address(Jekyll_Island_Inc) == address(0) ); Jekyll_Island_Inc = JIincForwarderInterface(_addr); } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // MODIFIERS //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifier onlyDevs() { require(admins_[msg.sender].isDev == true, "onlyDevs failed - msg.sender is not a dev"); _; } modifier onlyAdmins() { require(admins_[msg.sender].isAdmin == true, "onlyAdmins failed - msg.sender is not an admin"); _; } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // DEV ONLY FUNCTIONS //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /** * @dev DEV - use this to add admins. this is a dev only function. * @param _who - address of the admin you wish to add * @param _name - admins name * @param _isDev - is this admin also a dev? */ function addAdmin(address _who, bytes32 _name, bool _isDev) public onlyDevs() { if (MSFun.multiSig(msData, requiredDevSignatures_, "addAdmin") == true) { MSFun.deleteProposal(msData, "addAdmin"); // must check this so we dont mess up admin count by adding someone // who is already an admin if (admins_[_who].isAdmin == false) { // set admins flag to true in admin mapping admins_[_who].isAdmin = true; // adjust admin count and required signatures adminCount_ += 1; requiredSignatures_ += 1; } // are we setting them as a dev? // by putting this outside the above if statement, we can upgrade existing // admins to devs. if (_isDev == true) { // bestow the honored dev status admins_[_who].isDev = _isDev; // increase dev count and required dev signatures devCount_ += 1; requiredDevSignatures_ += 1; } } // by putting this outside the above multisig, we can allow easy name changes // without having to bother with multisig. this will still create a proposal though // so use the deleteAnyProposal to delete it if you want to admins_[_who].name = _name; } /** * @dev DEV - use this to remove admins. this is a dev only function. * -requirements: never less than 1 admin * never less than 1 dev * never less admins than required signatures * never less devs than required dev signatures * @param _who - address of the admin you wish to remove */ function removeAdmin(address _who) public onlyDevs() { // we can put our requires outside the multisig, this will prevent // creating a proposal that would never pass checks anyway. require(adminCount_ > 1, "removeAdmin failed - cannot have less than 2 admins"); require(adminCount_ >= requiredSignatures_, "removeAdmin failed - cannot have less admins than number of required signatures"); if (admins_[_who].isDev == true) { require(devCount_ > 1, "removeAdmin failed - cannot have less than 2 devs"); require(devCount_ >= requiredDevSignatures_, "removeAdmin failed - cannot have less devs than number of required dev signatures"); } // checks passed if (MSFun.multiSig(msData, requiredDevSignatures_, "removeAdmin") == true) { MSFun.deleteProposal(msData, "removeAdmin"); // must check this so we dont mess up admin count by removing someone // who wasnt an admin to start with if (admins_[_who].isAdmin == true) { //set admins flag to false in admin mapping admins_[_who].isAdmin = false; //adjust admin count and required signatures adminCount_ -= 1; if (requiredSignatures_ > 1) { requiredSignatures_ -= 1; } } // were they also a dev? if (admins_[_who].isDev == true) { //set dev flag to false admins_[_who].isDev = false; //adjust dev count and required dev signatures devCount_ -= 1; if (requiredDevSignatures_ > 1) { requiredDevSignatures_ -= 1; } } } } /** * @dev DEV - change the number of required signatures. must be between * 1 and the number of admins. this is a dev only function * @param _howMany - desired number of required signatures */ function changeRequiredSignatures(uint256 _howMany) public onlyDevs() { // make sure its between 1 and number of admins require(_howMany > 0 && _howMany <= adminCount_, "changeRequiredSignatures failed - must be between 1 and number of admins"); if (MSFun.multiSig(msData, requiredDevSignatures_, "changeRequiredSignatures") == true) { MSFun.deleteProposal(msData, "changeRequiredSignatures"); // store new setting. requiredSignatures_ = _howMany; } } /** * @dev DEV - change the number of required dev signatures. must be between * 1 and the number of devs. this is a dev only function * @param _howMany - desired number of required dev signatures */ function changeRequiredDevSignatures(uint256 _howMany) public onlyDevs() { // make sure its between 1 and number of admins require(_howMany > 0 && _howMany <= devCount_, "changeRequiredDevSignatures failed - must be between 1 and number of devs"); if (MSFun.multiSig(msData, requiredDevSignatures_, "changeRequiredDevSignatures") == true) { MSFun.deleteProposal(msData, "changeRequiredDevSignatures"); // store new setting. requiredDevSignatures_ = _howMany; } } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // EXTERNAL FUNCTIONS //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function requiredSignatures() external view returns(uint256) {return(requiredSignatures_);} function requiredDevSignatures() external view returns(uint256) {return(requiredDevSignatures_);} function adminCount() external view returns(uint256) {return(adminCount_);} function devCount() external view returns(uint256) {return(devCount_);} function adminName(address _who) external view returns(bytes32) {return(admins_[_who].name);} function isAdmin(address _who) external view returns(bool) {return(admins_[_who].isAdmin);} function isDev(address _who) external view returns(bool) {return(admins_[_who].isDev);} } ================================================ FILE: contracts/interface/DiviesInterface.sol ================================================ pragma solidity ^0.4.24; interface DiviesInterface { function deposit() external payable; } ================================================ FILE: contracts/interface/F3DexternalSettingsInterface.sol ================================================ pragma solidity ^0.4.24; interface F3DexternalSettingsInterface { function getFastGap() external returns(uint256); function getLongGap() external returns(uint256); function getFastExtra() external returns(uint256); function getLongExtra() external returns(uint256); } ================================================ FILE: contracts/interface/HourglassInterface.sol ================================================ pragma solidity ^0.4.24; interface HourglassInterface { function() payable external; function buy(address _playerAddress) payable external returns(uint256); function sell(uint256 _amountOfTokens) external; function reinvest() external; function withdraw() external; function exit() external; function dividendsOf(address _playerAddress) external view returns(uint256); function balanceOf(address _playerAddress) external view returns(uint256); function transfer(address _toAddress, uint256 _amountOfTokens) external returns(bool); function stakingRequirement() external view returns(uint256); } ================================================ FILE: contracts/interface/JIincForwarderInterface.sol ================================================ pragma solidity ^0.4.24; interface JIincForwarderInterface { function deposit() external payable returns(bool); function status() external view returns(address, address, bool); function startMigration(address _newCorpBank) external returns(bool); function cancelMigration() external returns(bool); function finishMigration() external returns(bool); function setup(address _firstCorpBank) external; } ================================================ FILE: contracts/interface/JIincInterfaceForForwarder.sol ================================================ pragma solidity ^0.4.24; interface JIincInterfaceForForwarder { function deposit(address _addr) external payable returns (bool); function migrationReceiver_setup() external returns (bool); } ================================================ FILE: contracts/interface/PlayerBookInterface.sol ================================================ pragma solidity ^0.4.24; interface PlayerBookInterface { function getPlayerID(address _addr) external returns (uint256); function getPlayerName(uint256 _pID) external view returns (bytes32); function getPlayerLAff(uint256 _pID) external view returns (uint256); function getPlayerAddr(uint256 _pID) external view returns (address); function getNameFee() external view returns (uint256); function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) external payable returns(bool, uint256); function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) external payable returns(bool, uint256); function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) external payable returns(bool, uint256); } ================================================ FILE: contracts/interface/PlayerBookReceiverInterface.sol ================================================ pragma solidity ^0.4.24; interface PlayerBookReceiverInterface { function receivePlayerInfo(uint256 _pID, address _addr, bytes32 _name, uint256 _laff) external; function receivePlayerNameList(uint256 _pID, bytes32 _name) external; } ================================================ FILE: contracts/interface/TeamJustInterface.sol ================================================ pragma solidity ^0.4.24; interface TeamJustInterface { function requiredSignatures() external view returns(uint256); function requiredDevSignatures() external view returns(uint256); function adminCount() external view returns(uint256); function devCount() external view returns(uint256); function adminName(address _who) external view returns(bytes32); function isAdmin(address _who) external view returns(bool); function isDev(address _who) external view returns(bool); } ================================================ FILE: contracts/interface/otherFoMo3D.sol ================================================ pragma solidity ^0.4.24; interface otherFoMo3D { function potSwap() external payable; } ================================================ FILE: contracts/library/F3DKeysCalcLong.sol ================================================ pragma solidity ^0.4.24; import './SafeMath.sol'; //============================================================================== // | _ _ _ | _ . // |<(/_\/ (_(_||(_ . //=======/====================================================================== library F3DKeysCalcLong { using SafeMath for *; /** * @dev calculates number of keys received given X eth * @param _curEth current amount of eth in contract * @param _newEth eth being spent * @return amount of ticket purchased */ function keysRec(uint256 _curEth, uint256 _newEth) internal pure returns (uint256) { return(keys((_curEth).add(_newEth)).sub(keys(_curEth))); } /** * @dev calculates amount of eth received if you sold X keys * @param _curKeys current amount of keys that exist * @param _sellKeys amount of keys you wish to sell * @return amount of eth received */ function ethRec(uint256 _curKeys, uint256 _sellKeys) internal pure returns (uint256) { return((eth(_curKeys)).sub(eth(_curKeys.sub(_sellKeys)))); } /** * @dev calculates how many keys would exist with given an amount of eth * @param _eth eth "in contract" * @return number of keys that would exist */ function keys(uint256 _eth) internal pure returns(uint256) { return ((((((_eth).mul(1000000000000000000)).mul(312500000000000000000000000)).add(5624988281256103515625000000000000000000000000000000000000000000)).sqrt()).sub(74999921875000000000000000000000)) / (156250000); } /** * @dev calculates how much eth would be in contract given a number of keys * @param _keys number of keys "in contract" * @return eth that would exists */ function eth(uint256 _keys) internal pure returns(uint256) { return ((78125000).mul(_keys.sq()).add(((149999843750000).mul(_keys.mul(1000000000000000000))) / (2))) / ((1000000000000000000).sq()); } } ================================================ FILE: contracts/library/F3Ddatasets.sol ================================================ pragma solidity ^0.4.24; //============================================================================== // __|_ _ __|_ _ . // _\ | | |_|(_ | _\ . //============================================================================== library F3Ddatasets { //compressedData key // [76-33][32][31][30][29][28-18][17][16-6][5-3][2][1][0] // 0 - new player (bool) // 1 - joined round (bool) // 2 - new leader (bool) // 3-5 - air drop tracker (uint 0-999) // 6-16 - round end time // 17 - winnerTeam // 18 - 28 timestamp // 29 - team // 30 - 0 = reinvest (round), 1 = buy (round), 2 = buy (ico), 3 = reinvest (ico) // 31 - airdrop happened bool // 32 - airdrop tier // 33 - airdrop amount won //compressedIDs key // [77-52][51-26][25-0] // 0-25 - pID // 26-51 - winPID // 52-77 - rID struct EventReturns { uint256 compressedData; uint256 compressedIDs; address winnerAddr; // winner address bytes32 winnerName; // winner name uint256 amountWon; // amount won uint256 newPot; // amount in new pot uint256 P3DAmount; // amount distributed to p3d uint256 genAmount; // amount distributed to gen uint256 potAmount; // amount added to pot } struct Player { address addr; // player address bytes32 name; // player name uint256 win; // winnings vault uint256 gen; // general vault uint256 aff; // affiliate vault uint256 lrnd; // last round played uint256 laff; // last affiliate id used } struct PlayerRounds { uint256 eth; // eth player has added to round (used for eth limiter) uint256 keys; // keys uint256 mask; // player mask uint256 ico; // ICO phase investment } struct Round { uint256 plyr; // pID of player in lead, lead领导吗? uint256 team; // tID of team in lead uint256 end; // time ends/ended bool ended; // has round end function been ran 这个开关值得研究下 uint256 strt; // time round started uint256 keys; // keys uint256 eth; // total eth in uint256 pot; // eth to pot (during round) / final amount paid to winner (after round ends) uint256 mask; // global mask uint256 ico; // total eth sent in during ICO phase uint256 icoGen; // total eth for gen during ICO phase uint256 icoAvg; // average key price for ICO phase } struct TeamFee { uint256 gen; // % of buy in thats paid to key holders of current round uint256 p3d; // % of buy in thats paid to p3d holders } struct PotSplit { uint256 gen; // % of pot thats paid to key holders of current round uint256 p3d; // % of pot thats paid to p3d holders } } ================================================ FILE: contracts/library/MSFun.sol ================================================ pragma solidity ^0.4.24; /** @title -MSFun- v0.2.4 * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ * _____ _____ * (, / /) /) /) (, / /) /) * ┌─┐ / _ (/_ // // / _ // _ __ _(/ * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ * ┴ ┴ / / .-/ _____ (__ / * (__ / (_/ (, / /)™ * / __ __ __ __ _ __ __ _ _/_ _ _(/ * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ * _ _ _ _ _ _ _ _ _ _ _ *=(_) _ _ (_)==========_(_)(_)(_)(_)_==========(_)(_)(_)(_)(_)================================* * (_)(_) (_)(_) (_) (_) (_) _ _ _ _ _ _ * (_) (_)_(_) (_) (_)_ _ _ _ (_) _ _ (_) (_) (_)(_)(_)(_)_ * (_) (_) (_) (_)(_)(_)(_)_ (_)(_)(_)(_) (_) (_) (_) * (_) (_) _ _ _ (_) _ _ (_) (_) (_) (_) (_) _ _ *=(_)=========(_)=(_)(_)==(_)_ _ _ _(_)=(_)(_)==(_)======(_)_ _ _(_)_ (_)========(_)=(_)(_)==* * (_) (_) (_)(_) (_)(_)(_)(_) (_)(_) (_) (_)(_)(_) (_)(_) (_) (_)(_) * * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ * * ┌──────────────────────────────────────────────────────────────────────┐ * │ MSFun, is an importable library that gives your contract the ability │ * │ add multiSig requirement to functions. │ * └──────────────────────────────────────────────────────────────────────┘ * ┌────────────────────┐ * │ Setup Instructions │ * └────────────────────┘ * (Step 1) import the library into your contract * * import "./MSFun.sol"; * * (Step 2) set up the signature data for msFun * * MSFun.Data private msData; * ┌────────────────────┐ * │ Usage Instructions │ * └────────────────────┘ * at the beginning of a function * * function functionName() * { * if (MSFun.multiSig(msData, required signatures, "functionName") == true) * { * MSFun.deleteProposal(msData, "functionName"); * * // put function body here * } * } * ┌────────────────────────────────┐ * │ Optional Wrappers For TeamJust │ * └────────────────────────────────┘ * multiSig wrapper function (cuts down on inputs, improves readability) * this wrapper is HIGHLY recommended * * function multiSig(bytes32 _whatFunction) private returns (bool) {return(MSFun.multiSig(msData, TeamJust.requiredSignatures(), _whatFunction));} * function multiSigDev(bytes32 _whatFunction) private returns (bool) {return(MSFun.multiSig(msData, TeamJust.requiredDevSignatures(), _whatFunction));} * * wrapper for delete proposal (makes code cleaner) * * function deleteProposal(bytes32 _whatFunction) private {MSFun.deleteProposal(msData, _whatFunction);} * ┌────────────────────────────┐ * │ Utility & Vanity Functions │ * └────────────────────────────┘ * delete any proposal is highly recommended. without it, if an admin calls a multiSig * function, with argument inputs that the other admins do not agree upon, the function * can never be executed until the undesirable arguments are approved. * * function deleteAnyProposal(bytes32 _whatFunction) onlyDevs() public {MSFun.deleteProposal(msData, _whatFunction);} * * for viewing who has signed a proposal & proposal data * * function checkData(bytes32 _whatFunction) onlyAdmins() public view returns(bytes32, uint256) {return(MSFun.checkMsgData(msData, _whatFunction), MSFun.checkCount(msData, _whatFunction));} * * lets you check address of up to 3 signers (address) * * 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));} * * same as above but will return names in string format. * * 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)));} * ┌──────────────────────────┐ * │ Functions In Depth Guide │ * └──────────────────────────┘ * In the following examples, the Data is the proposal set for this library. And * the bytes32 is the name of the function. * * MSFun.multiSig(Data, uint256, bytes32) - Manages creating/updating multiSig * proposal for the function being called. The uint256 is the required * number of signatures needed before the multiSig will return true. * Upon first call, multiSig will create a proposal and store the arguments * passed with the function call as msgData. Any admins trying to sign the * function call will need to send the same argument values. Once required * number of signatures is reached this will return a bool of true. * * MSFun.deleteProposal(Data, bytes32) - once multiSig unlocks the function body, * you will want to delete the proposal data. This does that. * * MSFun.checkMsgData(Data, bytes32) - checks the message data for any given proposal * * MSFun.checkCount(Data, bytes32) - checks the number of admins that have signed * the proposal * * MSFun.checkSigners(data, bytes32, uint256) - checks the address of a given signer. * the uint256, is the log number of the signer (ie 1st signer, 2nd signer) */ library MSFun { //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // DATA SETS //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // contact data setup struct Data { mapping (bytes32 => ProposalData) proposal_; } struct ProposalData { // a hash of msg.data bytes32 msgData; // number of signers uint256 count; // tracking of wither admins have signed mapping (address => bool) admin; // list of admins who have signed mapping (uint256 => address) log; } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // MULTI SIG FUNCTIONS //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function multiSig(Data storage self, uint256 _requiredSignatures, bytes32 _whatFunction) internal returns(bool) { // our proposal key will be a hash of our function name + our contracts address // by adding our contracts address to this, we prevent anyone trying to circumvent // the proposal's security via external calls. bytes32 _whatProposal = whatProposal(_whatFunction); // this is just done to make the code more readable. grabs the signature count uint256 _currentCount = self.proposal_[_whatProposal].count; // store the address of the person sending the function call. we use msg.sender // here as a layer of security. in case someone imports our contract and tries to // circumvent function arguments. still though, our contract that imports this // library and calls multisig, needs to use onlyAdmin modifiers or anyone who // calls the function will be a signer. address _whichAdmin = msg.sender; // prepare our msg data. by storing this we are able to verify that all admins // are approving the same argument input to be executed for the function. we hash // it and store in bytes32 so its size is known and comparable bytes32 _msgData = keccak256(msg.data); // check to see if this is a new execution of this proposal or not if (_currentCount == 0) { // if it is, lets record the original signers data self.proposal_[_whatProposal].msgData = _msgData; // record original senders signature self.proposal_[_whatProposal].admin[_whichAdmin] = true; // update log (used to delete records later, and easy way to view signers) // also useful if the calling function wants to give something to a // specific signer. self.proposal_[_whatProposal].log[_currentCount] = _whichAdmin; // track number of signatures self.proposal_[_whatProposal].count += 1; // if we now have enough signatures to execute the function, lets // return a bool of true. we put this here in case the required signatures // is set to 1. if (self.proposal_[_whatProposal].count == _requiredSignatures) { return(true); } // if its not the first execution, lets make sure the msgData matches } else if (self.proposal_[_whatProposal].msgData == _msgData) { // msgData is a match // make sure admin hasnt already signed if (self.proposal_[_whatProposal].admin[_whichAdmin] == false) { // record their signature self.proposal_[_whatProposal].admin[_whichAdmin] = true; // update log (used to delete records later, and easy way to view signers) self.proposal_[_whatProposal].log[_currentCount] = _whichAdmin; // track number of signatures self.proposal_[_whatProposal].count += 1; } // if we now have enough signatures to execute the function, lets // return a bool of true. // we put this here for a few reasons. (1) in normal operation, if // that last recorded signature got us to our required signatures. we // need to return bool of true. (2) if we have a situation where the // required number of signatures was adjusted to at or lower than our current // signature count, by putting this here, an admin who has already signed, // can call the function again to make it return a true bool. but only if // they submit the correct msg data if (self.proposal_[_whatProposal].count == _requiredSignatures) { return(true); } } } // deletes proposal signature data after successfully executing a multiSig function function deleteProposal(Data storage self, bytes32 _whatFunction) internal { //done for readability sake bytes32 _whatProposal = whatProposal(_whatFunction); address _whichAdmin; //delete the admins votes & log. i know for loops are terrible. but we have to do this //for our data stored in mappings. simply deleting the proposal itself wouldn't accomplish this. for (uint256 i=0; i < self.proposal_[_whatProposal].count; i++) { _whichAdmin = self.proposal_[_whatProposal].log[i]; delete self.proposal_[_whatProposal].admin[_whichAdmin]; delete self.proposal_[_whatProposal].log[i]; } //delete the rest of the data in the record delete self.proposal_[_whatProposal]; } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // HELPER FUNCTIONS //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function whatProposal(bytes32 _whatFunction) private view returns(bytes32) { return(keccak256(abi.encodePacked(_whatFunction,this))); } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // VANITY FUNCTIONS //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // returns a hashed version of msg.data sent by original signer for any given function function checkMsgData (Data storage self, bytes32 _whatFunction) internal view returns (bytes32 msg_data) { bytes32 _whatProposal = whatProposal(_whatFunction); return (self.proposal_[_whatProposal].msgData); } // returns number of signers for any given function function checkCount (Data storage self, bytes32 _whatFunction) internal view returns (uint256 signature_count) { bytes32 _whatProposal = whatProposal(_whatFunction); return (self.proposal_[_whatProposal].count); } // returns address of an admin who signed for any given function function checkSigner (Data storage self, bytes32 _whatFunction, uint256 _signer) internal view returns (address signer) { require(_signer > 0, "MSFun checkSigner failed - 0 not allowed"); bytes32 _whatProposal = whatProposal(_whatFunction); return (self.proposal_[_whatProposal].log[_signer - 1]); } } ================================================ FILE: contracts/library/NameFilter.sol ================================================ pragma solidity ^0.4.24; /** * @title -Name Filter- v0.1.9 * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ * _____ _____ * (, / /) /) /) (, / /) /) * ┌─┐ / _ (/_ // // / _ // _ __ _(/ * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ * ┴ ┴ / / .-/ _____ (__ / * (__ / (_/ (, / /)™ * / __ __ __ __ _ __ __ _ _/_ _ _(/ * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ * _ __ _ ____ ____ _ _ _____ ____ ___ *=============| |\ | / /\ | |\/| | |_ =====| |_ | | | | | | | |_ | |_)==============* *=============|_| \| /_/--\ |_| | |_|__=====|_| |_| |_|__ |_| |_|__ |_| \==============* * * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ */ library NameFilter { /** * @dev filters name strings * -converts uppercase to lower case. * -makes sure it does not start/end with a space * -makes sure it does not contain multiple spaces in a row * -cannot be only numbers * -cannot start with 0x * -restricts characters to A-Z, a-z, 0-9, and space. * @return reprocessed string in bytes32 format */ function nameFilter(string _input) internal pure returns(bytes32) { bytes memory _temp = bytes(_input); uint256 _length = _temp.length; //sorry limited to 32 characters require (_length <= 32 && _length > 0, "string must be between 1 and 32 characters"); // make sure it doesnt start with or end with space require(_temp[0] != 0x20 && _temp[_length-1] != 0x20, "string cannot start or end with space"); // make sure first two characters are not 0x if (_temp[0] == 0x30) { require(_temp[1] != 0x78, "string cannot start with 0x"); require(_temp[1] != 0x58, "string cannot start with 0X"); } // create a bool to track if we have a non number character bool _hasNonNumber; // convert & check for (uint256 i = 0; i < _length; i++) { // if its uppercase A-Z if (_temp[i] > 0x40 && _temp[i] < 0x5b) { // convert to lower case a-z _temp[i] = byte(uint(_temp[i]) + 32); // we have a non number if (_hasNonNumber == false) _hasNonNumber = true; } else { require ( // require character is a space _temp[i] == 0x20 || // OR lowercase a-z (_temp[i] > 0x60 && _temp[i] < 0x7b) || // or 0-9 (_temp[i] > 0x2f && _temp[i] < 0x3a), "string contains invalid characters" ); // make sure theres not 2x spaces in a row if (_temp[i] == 0x20) require( _temp[i+1] != 0x20, "string cannot contain consecutive spaces"); // see if we have a character other than a number if (_hasNonNumber == false && (_temp[i] < 0x30 || _temp[i] > 0x39)) _hasNonNumber = true; } } require(_hasNonNumber == true, "string cannot be only numbers"); bytes32 _ret; assembly { _ret := mload(add(_temp, 32)) } return (_ret); } } ================================================ FILE: contracts/library/SafeMath.sol ================================================ pragma solidity ^0.4.24; /** * @title SafeMath v0.1.9 * @dev Math operations with safety checks that throw on error * change notes: original SafeMath library from OpenZeppelin modified by Inventor * - added sqrt * - added sq * - added pwr * - changed asserts to requires with error log outputs * - removed div, its useless */ library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { if (a == 0) { return 0; } c = a * b; require(c / a == b, "SafeMath mul failed"); return c; } /** * @dev Integer division of two numbers, truncating the quotient. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath sub failed"); return a - b; } /** * @dev Adds two numbers, throws on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256 c) { c = a + b; require(c >= a, "SafeMath add failed"); return c; } /** * @dev gives square root of given x. */ function sqrt(uint256 x) internal pure returns (uint256 y) { uint256 z = ((add(x,1)) / 2); y = x; while (z < y) { y = z; z = ((add((x / z),z)) / 2); } } /** * @dev gives square. multiplies x by x */ function sq(uint256 x) internal pure returns (uint256) { return (mul(x,x)); } /** * @dev x to the power of y */ function pwr(uint256 x, uint256 y) internal pure returns (uint256) { if (x==0) return (0); else if (y==0) return (1); else { uint256 z = x; for (uint256 i=1; i < y; i++) z = mul(z,x); return (z); } } } ================================================ FILE: contracts/library/UintCompressor.sol ================================================ pragma solidity ^0.4.24; import "./SafeMath.sol"; /** * @title -UintCompressor- v0.1.9 * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ * _____ _____ * (, / /) /) /) (, / /) /) * ┌─┐ / _ (/_ // // / _ // _ __ _(/ * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ * ┴ ┴ / / .-/ _____ (__ / * (__ / (_/ (, / /)™ * / __ __ __ __ _ __ __ _ _/_ _ _(/ * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ * _ _ __ __ _ ____ ___ __ _ _ ____ ____ ____ ____ ____ __ ____ *===/ )( \ ( ) ( ( \(_ _)===/ __) / \ ( \/ )( _ \( _ \( __)/ ___)/ ___) / \ ( _ \===* * ) \/ ( )( / / )( ( (__ ( O )/ \/ \ ) __/ ) / ) _) \___ \\___ \( O ) ) / *===\____/ (__) \_)__) (__)====\___) \__/ \_)(_/(__) (__\_)(____)(____/(____/ \__/ (__\_)===* * * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ */ library UintCompressor { using SafeMath for *; function insert(uint256 _var, uint256 _include, uint256 _start, uint256 _end) internal pure returns(uint256) { // check conditions require(_end < 77 && _start < 77, "start/end must be less than 77"); require(_end >= _start, "end must be >= start"); // format our start/end points _end = exponent(_end).mul(10); _start = exponent(_start); // check that the include data fits into its segment require(_include < (_end / _start)); // build middle if (_include > 0) _include = _include.mul(_start); return((_var.sub((_var / _start).mul(_start))).add(_include).add((_var / _end).mul(_end))); } function extract(uint256 _input, uint256 _start, uint256 _end) internal pure returns(uint256) { // check conditions require(_end < 77 && _start < 77, "start/end must be less than 77"); require(_end >= _start, "end must be >= start"); // format our start/end points _end = exponent(_end).mul(10); _start = exponent(_start); // return requested section return((((_input / _start).mul(_start)).sub((_input / _end).mul(_end))) / _start); } function exponent(uint256 _position) private pure returns(uint256) { return((10).pwr(_position)); } } ================================================ FILE: contracts/modularLong.sol ================================================ pragma solidity ^0.4.24; import "./F3Devents.sol"; contract modularLong is F3Devents {} ================================================ FILE: flattener.sh ================================================ ######################################################################### # File Name: flattener.sh # Author: ma6174 # mail: ma6174@163.com # Created Time: 六 12/30 00:54:25 2017 ######################################################################### #!/bin/bash cd flat_contracts rm -rf * cd .. truffle-flattener contracts/PetCore.sol >flat_contracts/PetCoreFlat.sol truffle-flattener contracts/SaleClockAuction.sol >flat_contracts/SaleClockAuctionFlat.sol truffle-flattener contracts/SiringClockAuction.sol >flat_contracts/SiringClockAuctionFlat.sol truffle-flattener contracts/GenePet.sol >flat_contracts/GenePetFlat.sol ================================================ FILE: migrations/1_initial_migration.js ================================================ var Migrations = artifacts.require("./Migrations.sol"); module.exports = function(deployer) { deployer.deploy(Migrations); }; ================================================ FILE: migrations/2_deploy_petcore.js ================================================ var PetCore = artifacts.require("./PetCore.sol"); module.exports = function(deployer, network, accounts) { console.log('network is '+network); console.log(accounts); console.log(accounts[0]); console.log('deploy PetCore contract to develop network, account address is '+accounts[0]); deployer.deploy(PetCore); }; ================================================ FILE: migrations/3_deploy_gene.js ================================================ var GenePet = artifacts.require("./GenePet.sol"); module.exports = function(deployer) { deployer.deploy(GenePet); }; ================================================ FILE: package.json ================================================ { "name": "genePet", "version": "1.0.0", "description": "", "main": "truffle.js", "directories": { "test": "test" }, "scripts": { "dev": "lite-server", "test": "echo \"Error: no test specified\" && exit 1", "flat": "sh ./flattener.sh" }, "author": "", "license": "ISC", "devDependencies": { "lite-server": "^2.3.0" }, "dependencies": { "zeppelin-solidity": "^1.4.0" } } ================================================ FILE: truffle.js ================================================ module.exports = { networks: { develop: { host: "127.0.0.1", port: 7545, network_id: "*" // Match any network id }, test: { host: "127.0.0.1", port: 7545, network_id: "*" // Match any network id }, mine: { host: "127.0.0.1", port: 8545, network_id: "*", // Match any network id gas: 4712382 }, ropsten: { network_id: 3, host: "localhost", port: 8545, gas: 4700000 } } };