github.com/annchain/OG@v0.0.9/vm/vm_test/contracts/fomolong.sol (about) 1 pragma solidity ^0.4.24; 2 /** 3 * @title -FoMo-3D v0.7.1 4 * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ 5 * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ 6 * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ 7 * _____ _____ 8 * (, / /) /) /) (, / /) /) 9 * ┌─┐ / _ (/_ // // / _ // _ __ _(/ 10 * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ 11 * ┴ ┴ / / .-/ _____ (__ / 12 * (__ / (_/ (, / /)™ 13 * / __ __ __ __ _ __ __ _ _/_ _ _(/ 14 * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ 15 * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 16 * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ .--,-``-. 17 *========,---,.======================____==========================/ / '.=======,---,====* 18 * ,' .' | ,' , `. / ../ ; .' .' `\ 19 * ,---.' | ,---. ,-+-,.' _ | ,---. \ ``\ .`- ' ,---.' \ 20 * | | .' ' ,'\ ,-+-. ; , || ' ,'\ ,---,. \___\/ \ : | | .`\ | 21 * : : : / / | ,--.'|' | || / / | ,' .' | \ : | : : | ' | 22 * : | |-, . ; ,. : | | ,', | |, . ; ,. : ,---.' | / / / | ' ' ; : 23 * | : ;/| ' | |: : | | / | |--' ' | |: : | | .' \ \ \ ' | ; . | 24 * | | .' ' | .; : | : | | , ' | .; : : |.' ___ / : | | | : | ' 25 * ' : ' | : | | : | |/ | : | `---' / /\ / : ' : | / ; 26 * | | | \ \ / | | |`-' \ \ / / ,,/ ',- . | | '` ,/ 27 * | : \ `----' | ;/ `----' \ ''\ ; ; : .' 28 *====| | ,'=============='---'==========(long version)===========\ \ .'===| ,.'======* 29 * `----' `--`-,,-' '---' 30 * ╔═╗┌─┐┌─┐┬┌─┐┬┌─┐┬ ┌─────────────────────────┐ ╦ ╦┌─┐┌┐ ╔═╗┬┌┬┐┌─┐ 31 * ║ ║├┤ ├┤ ││ │├─┤│ │ https://exitscam.me │ ║║║├┤ ├┴┐╚═╗│ │ ├┤ 32 * ╚═╝└ └ ┴└─┘┴┴ ┴┴─┘ └─┬─────────────────────┬─┘ ╚╩╝└─┘└─┘╚═╝┴ ┴ └─┘ 33 * ┌────────────────────────────────┘ └──────────────────────────────┐ 34 * │╔═╗┌─┐┬ ┬┌┬┐┬┌┬┐┬ ┬ ╔╦╗┌─┐┌─┐┬┌─┐┌┐┌ ╦┌┐┌┌┬┐┌─┐┬─┐┌─┐┌─┐┌─┐┌─┐ ╔═╗┌┬┐┌─┐┌─┐┬┌─│ 35 * │╚═╗│ ││ │ │││ │ └┬┘ ═ ║║├┤ └─┐││ ┬│││ ═ ║│││ │ ├┤ ├┬┘├┤ ├─┤│ ├┤ ═ ╚═╗ │ ├─┤│ ├┴┐│ 36 * │╚═╝└─┘┴─┘┴─┴┘┴ ┴ ┴ ═╩╝└─┘└─┘┴└─┘┘└┘ ╩┘└┘ ┴ └─┘┴└─└ ┴ ┴└─┘└─┘ ╚═╝ ┴ ┴ ┴└─┘┴ ┴│ 37 * │ ┌──────────┐ ┌───────┐ ┌─────────┐ ┌────────┐ │ 38 * └────┤ Inventor ├───────────┤ Justo ├────────────┤ Sumpunk ├──────────────┤ Mantso ├──┘ 39 * └──────────┘ └───────┘ └─────────┘ └────────┘ 40 * ┌─────────────────────────────────────────────────────────┐ ╔╦╗┬ ┬┌─┐┌┐┌┬┌─┌─┐ ╔╦╗┌─┐ 41 * │ Ambius, Aritz Cracker, Cryptoknight, Crypto McPump, │ ║ ├─┤├─┤│││├┴┐└─┐ ║ │ │ 42 * │ Capex, JogFera, The Shocker, Daok, Randazzz, PumpRabbi, │ ╩ ┴ ┴┴ ┴┘└┘┴ ┴└─┘ ╩ └─┘ 43 * │ Kadaz, Incognito Jo, Lil Stronghands, Ninja Turtle, └───────────────────────────┐ 44 * │ Psaints, Satoshi, Vitalik, Nano 2nd, Bogdanoffs Isaac Newton, Nikola Tesla, │ 45 * │ Le Comte De Saint Germain, Albert Einstein, Socrates, & all the volunteer moderator │ 46 * │ & support staff, content, creators, autonomous agents, and indie devs for P3D. │ 47 * │ Without your help, we wouldn't have the time to code this. │ 48 * └─────────────────────────────────────────────────────────────────────────────────────┘ 49 * 50 * This product is protected under license. Any unauthorized copy, modification, or use without 51 * express written consent from the creators is prohibited. 52 * 53 * WARNING: THIS PRODUCT IS HIGHLY ADDICTIVE. IF YOU HAVE AN ADDICTIVE NATURE. DO NOT PLAY. 54 */ 55 56 //============================================================================== 57 // _ _ _ _|_ _ . 58 // (/_\/(/_| | | _\ . 59 //============================================================================== 60 contract F3Devents { 61 // fired whenever a player registers a name 62 event onNewName 63 ( 64 uint256 indexed playerID, 65 address indexed playerAddress, 66 bytes32 indexed playerName, 67 bool isNewPlayer, 68 uint256 affiliateID, 69 address affiliateAddress, 70 bytes32 affiliateName, 71 uint256 amountPaid, 72 uint256 timeStamp 73 ); 74 75 // fired at end of buy or reload 76 event onEndTx 77 ( 78 uint256 compressedData, 79 uint256 compressedIDs, 80 bytes32 playerName, 81 address playerAddress, 82 uint256 ethIn, 83 uint256 keysBought, 84 address winnerAddr, 85 bytes32 winnerName, 86 uint256 amountWon, 87 uint256 newPot, 88 uint256 P3DAmount, 89 uint256 genAmount, 90 uint256 potAmount, 91 uint256 airDropPot 92 ); 93 94 // fired whenever theres a withdraw 95 event onWithdraw 96 ( 97 uint256 indexed playerID, 98 address playerAddress, 99 bytes32 playerName, 100 uint256 ethOut, 101 uint256 timeStamp 102 ); 103 104 // fired whenever a withdraw forces end round to be ran 105 event onWithdrawAndDistribute 106 ( 107 address playerAddress, 108 bytes32 playerName, 109 uint256 ethOut, 110 uint256 compressedData, 111 uint256 compressedIDs, 112 address winnerAddr, 113 bytes32 winnerName, 114 uint256 amountWon, 115 uint256 newPot, 116 uint256 P3DAmount, 117 uint256 genAmount 118 ); 119 120 // (fomo3d long only) fired whenever a player tries a buy after round timer 121 // hit zero, and causes end round to be ran. 122 event onBuyAndDistribute 123 ( 124 address playerAddress, 125 bytes32 playerName, 126 uint256 ethIn, 127 uint256 compressedData, 128 uint256 compressedIDs, 129 address winnerAddr, 130 bytes32 winnerName, 131 uint256 amountWon, 132 uint256 newPot, 133 uint256 P3DAmount, 134 uint256 genAmount 135 ); 136 137 // (fomo3d long only) fired whenever a player tries a reload after round timer 138 // hit zero, and causes end round to be ran. 139 event onReLoadAndDistribute 140 ( 141 address playerAddress, 142 bytes32 playerName, 143 uint256 compressedData, 144 uint256 compressedIDs, 145 address winnerAddr, 146 bytes32 winnerName, 147 uint256 amountWon, 148 uint256 newPot, 149 uint256 P3DAmount, 150 uint256 genAmount 151 ); 152 153 // fired whenever an affiliate is paid 154 event onAffiliatePayout 155 ( 156 uint256 indexed affiliateID, 157 address affiliateAddress, 158 bytes32 affiliateName, 159 uint256 indexed roundID, 160 uint256 indexed buyerID, 161 uint256 amount, 162 uint256 timeStamp 163 ); 164 165 // received pot swap deposit 166 event onPotSwapDeposit 167 ( 168 uint256 roundID, 169 uint256 amountAddedToPot 170 ); 171 } 172 173 //============================================================================== 174 // _ _ _ _|_ _ _ __|_ _ _ _|_ _ . 175 // (_(_)| | | | (_|(_ | _\(/_ | |_||_) . 176 //====================================|========================================= 177 178 contract modularLong is F3Devents {} 179 180 contract FoMo3Dlong is modularLong { 181 using SafeMath for *; 182 using NameFilter for string; 183 using F3DKeysCalcLong for uint256; 184 185 otherFoMo3D private otherF3D_; 186 DiviesInterface constant private Divies = DiviesInterface(0xc7029Ed9EBa97A096e72607f4340c34049C7AF48); 187 JIincForwarderInterface constant private Jekyll_Island_Inc = JIincForwarderInterface(0xdd4950F977EE28D2C132f1353D1595035Db444EE); 188 PlayerBookInterface constant private PlayerBook = PlayerBookInterface(0xD60d353610D9a5Ca478769D371b53CEfAA7B6E4c); 189 F3DexternalSettingsInterface constant private extSettings = F3DexternalSettingsInterface(0x32967D6c142c2F38AB39235994e2DDF11c37d590); 190 //============================================================================== 191 // _ _ _ |`. _ _ _ |_ | _ _ . 192 // (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings) 193 //=================_|=========================================================== 194 string constant public name = "FoMo3D Long Official"; 195 string constant public symbol = "F3D"; 196 uint256 private rndExtra_ = extSettings.getLongExtra(); // length of the very first ICO 197 uint256 private rndGap_ = extSettings.getLongGap(); // length of ICO phase, set to 1 year for EOS. 198 uint256 constant private rndInit_ = 1 hours; // round timer starts at this 199 uint256 constant private rndInc_ = 30 seconds; // every full key purchased adds this much to the timer 200 uint256 constant private rndMax_ = 24 hours; // max length a round timer can be 201 //============================================================================== 202 // _| _ _|_ _ _ _ _|_ _ . 203 // (_|(_| | (_| _\(/_ | |_||_) . (data used to store game info that changes) 204 //=============================|================================================ 205 uint256 public airDropPot_; // person who gets the airdrop wins part of this pot 206 uint256 public airDropTracker_ = 0; // incremented each time a "qualified" tx occurs. used to determine winning air drop 207 uint256 public rID_; // round id number / total rounds that have happened 208 //**************** 209 // PLAYER DATA 210 //**************** 211 mapping (address => uint256) public pIDxAddr_; // (addr => pID) returns player id by address 212 mapping (bytes32 => uint256) public pIDxName_; // (name => pID) returns player id by name 213 mapping (uint256 => F3Ddatasets.Player) public plyr_; // (pID => data) player data 214 mapping (uint256 => mapping (uint256 => F3Ddatasets.PlayerRounds)) public plyrRnds_; // (pID => rID => data) player round data by player id & round id 215 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) 216 //**************** 217 // ROUND DATA 218 //**************** 219 mapping (uint256 => F3Ddatasets.Round) public round_; // (rID => data) round data 220 mapping (uint256 => mapping(uint256 => uint256)) public rndTmEth_; // (rID => tID => data) eth in per team, by round id and team id 221 //**************** 222 // TEAM FEE DATA 223 //**************** 224 mapping (uint256 => F3Ddatasets.TeamFee) public fees_; // (team => fees) fee distribution by team 225 mapping (uint256 => F3Ddatasets.PotSplit) public potSplit_; // (team => fees) pot split distribution by team 226 //============================================================================== 227 // _ _ _ __|_ _ __|_ _ _ . 228 // (_(_)| |_\ | | |_|(_ | (_)| . (initial data setup upon contract deploy) 229 //============================================================================== 230 constructor() 231 public 232 { 233 // Team allocation structures 234 // 0 = whales 235 // 1 = bears 236 // 2 = sneks 237 // 3 = bulls 238 239 // Team allocation percentages 240 // (F3D, P3D) + (Pot , Referrals, Community) 241 // Referrals / Community rewards are mathematically designed to come from the winner's share of the pot. 242 fees_[0] = F3Ddatasets.TeamFee(30,6); //50% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot 243 fees_[1] = F3Ddatasets.TeamFee(43,0); //43% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot 244 fees_[2] = F3Ddatasets.TeamFee(56,10); //20% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot 245 fees_[3] = F3Ddatasets.TeamFee(43,8); //35% to pot, 10% to aff, 2% to com, 1% to pot swap, 1% to air drop pot 246 247 // how to split up the final pot based on which team was picked 248 // (F3D, P3D) 249 potSplit_[0] = F3Ddatasets.PotSplit(15,10); //48% to winner, 25% to next round, 2% to com 250 potSplit_[1] = F3Ddatasets.PotSplit(25,0); //48% to winner, 25% to next round, 2% to com 251 potSplit_[2] = F3Ddatasets.PotSplit(20,20); //48% to winner, 10% to next round, 2% to com 252 potSplit_[3] = F3Ddatasets.PotSplit(30,10); //48% to winner, 10% to next round, 2% to com 253 } 254 //============================================================================== 255 // _ _ _ _|. |`. _ _ _ . 256 // | | |(_)(_||~|~|(/_| _\ . (these are safety checks) 257 //============================================================================== 258 /** 259 * @dev used to make sure no one can interact with contract until it has 260 * been activated. 261 */ 262 modifier isActivated() { 263 require(activated_ == true, "its not ready yet. check ?eta in discord"); 264 _; 265 } 266 267 /** 268 * @dev prevents contracts from interacting with fomo3d 269 */ 270 modifier isHuman() { 271 address _addr = msg.sender; 272 uint256 _codeLength; 273 274 assembly {_codeLength := extcodesize(_addr)} 275 require(_codeLength == 0, "sorry humans only"); 276 _; 277 } 278 279 /** 280 * @dev sets boundaries for incoming tx 281 */ 282 modifier isWithinLimits(uint256 _eth) { 283 require(_eth >= 1000000000, "pocket lint: not a valid currency"); 284 require(_eth <= 100000000000000000000000, "no vitalik, no"); 285 _; 286 } 287 288 //============================================================================== 289 // _ |_ |. _ |` _ __|_. _ _ _ . 290 // |_)|_||_)||(_ ~|~|_|| |(_ | |(_)| |_\ . (use these to interact with contract) 291 //====|========================================================================= 292 /** 293 * @dev emergency buy uses last stored affiliate ID and team snek 294 */ 295 function() 296 isActivated() 297 isHuman() 298 isWithinLimits(msg.value) 299 public 300 payable 301 { 302 // set up our tx event data and determine if player is new or not 303 F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); 304 305 // fetch player id 306 uint256 _pID = pIDxAddr_[msg.sender]; 307 308 // buy core 309 buyCore(_pID, plyr_[_pID].laff, 2, _eventData_); 310 } 311 312 /** 313 * @dev converts all incoming ethereum to keys. 314 * -functionhash- 0x8f38f309 (using ID for affiliate) 315 * -functionhash- 0x98a0871d (using address for affiliate) 316 * -functionhash- 0xa65b37a1 (using name for affiliate) 317 * @param _affCode the ID/address/name of the player who gets the affiliate fee 318 * @param _team what team is the player playing for? 319 */ 320 function buyXid(uint256 _affCode, uint256 _team) 321 isActivated() 322 isHuman() 323 isWithinLimits(msg.value) 324 public 325 payable 326 { 327 // set up our tx event data and determine if player is new or not 328 F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); 329 330 // fetch player id 331 uint256 _pID = pIDxAddr_[msg.sender]; 332 333 // manage affiliate residuals 334 // if no affiliate code was given or player tried to use their own, lolz 335 if (_affCode == 0 || _affCode == _pID) 336 { 337 // use last stored affiliate code 338 _affCode = plyr_[_pID].laff; 339 340 // if affiliate code was given & its not the same as previously stored 341 } else if (_affCode != plyr_[_pID].laff) { 342 // update last affiliate 343 plyr_[_pID].laff = _affCode; 344 } 345 346 // verify a valid team was selected 347 _team = verifyTeam(_team); 348 349 // buy core 350 buyCore(_pID, _affCode, _team, _eventData_); 351 } 352 353 function buyXaddr(address _affCode, uint256 _team) 354 isActivated() 355 isHuman() 356 isWithinLimits(msg.value) 357 public 358 payable 359 { 360 // set up our tx event data and determine if player is new or not 361 F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); 362 363 // fetch player id 364 uint256 _pID = pIDxAddr_[msg.sender]; 365 366 // manage affiliate residuals 367 uint256 _affID; 368 // if no affiliate code was given or player tried to use their own, lolz 369 if (_affCode == address(0) || _affCode == msg.sender) 370 { 371 // use last stored affiliate code 372 _affID = plyr_[_pID].laff; 373 374 // if affiliate code was given 375 } else { 376 // get affiliate ID from aff Code 377 _affID = pIDxAddr_[_affCode]; 378 379 // if affID is not the same as previously stored 380 if (_affID != plyr_[_pID].laff) 381 { 382 // update last affiliate 383 plyr_[_pID].laff = _affID; 384 } 385 } 386 387 // verify a valid team was selected 388 _team = verifyTeam(_team); 389 390 // buy core 391 buyCore(_pID, _affID, _team, _eventData_); 392 } 393 394 function buyXname(bytes32 _affCode, uint256 _team) 395 isActivated() 396 isHuman() 397 isWithinLimits(msg.value) 398 public 399 payable 400 { 401 // set up our tx event data and determine if player is new or not 402 F3Ddatasets.EventReturns memory _eventData_ = determinePID(_eventData_); 403 404 // fetch player id 405 uint256 _pID = pIDxAddr_[msg.sender]; 406 407 // manage affiliate residuals 408 uint256 _affID; 409 // if no affiliate code was given or player tried to use their own, lolz 410 if (_affCode == '' || _affCode == plyr_[_pID].name) 411 { 412 // use last stored affiliate code 413 _affID = plyr_[_pID].laff; 414 415 // if affiliate code was given 416 } else { 417 // get affiliate ID from aff Code 418 _affID = pIDxName_[_affCode]; 419 420 // if affID is not the same as previously stored 421 if (_affID != plyr_[_pID].laff) 422 { 423 // update last affiliate 424 plyr_[_pID].laff = _affID; 425 } 426 } 427 428 // verify a valid team was selected 429 _team = verifyTeam(_team); 430 431 // buy core 432 buyCore(_pID, _affID, _team, _eventData_); 433 } 434 435 /** 436 * @dev essentially the same as buy, but instead of you sending ether 437 * from your wallet, it uses your unwithdrawn earnings. 438 * -functionhash- 0x349cdcac (using ID for affiliate) 439 * -functionhash- 0x82bfc739 (using address for affiliate) 440 * -functionhash- 0x079ce327 (using name for affiliate) 441 * @param _affCode the ID/address/name of the player who gets the affiliate fee 442 * @param _team what team is the player playing for? 443 * @param _eth amount of earnings to use (remainder returned to gen vault) 444 */ 445 function reLoadXid(uint256 _affCode, uint256 _team, uint256 _eth) 446 isActivated() 447 isHuman() 448 isWithinLimits(_eth) 449 public 450 { 451 // set up our tx event data 452 F3Ddatasets.EventReturns memory _eventData_; 453 454 // fetch player ID 455 uint256 _pID = pIDxAddr_[msg.sender]; 456 457 // manage affiliate residuals 458 // if no affiliate code was given or player tried to use their own, lolz 459 if (_affCode == 0 || _affCode == _pID) 460 { 461 // use last stored affiliate code 462 _affCode = plyr_[_pID].laff; 463 464 // if affiliate code was given & its not the same as previously stored 465 } else if (_affCode != plyr_[_pID].laff) { 466 // update last affiliate 467 plyr_[_pID].laff = _affCode; 468 } 469 470 // verify a valid team was selected 471 _team = verifyTeam(_team); 472 473 // reload core 474 reLoadCore(_pID, _affCode, _team, _eth, _eventData_); 475 } 476 477 function reLoadXaddr(address _affCode, uint256 _team, uint256 _eth) 478 isActivated() 479 isHuman() 480 isWithinLimits(_eth) 481 public 482 { 483 // set up our tx event data 484 F3Ddatasets.EventReturns memory _eventData_; 485 486 // fetch player ID 487 uint256 _pID = pIDxAddr_[msg.sender]; 488 489 // manage affiliate residuals 490 uint256 _affID; 491 // if no affiliate code was given or player tried to use their own, lolz 492 if (_affCode == address(0) || _affCode == msg.sender) 493 { 494 // use last stored affiliate code 495 _affID = plyr_[_pID].laff; 496 497 // if affiliate code was given 498 } else { 499 // get affiliate ID from aff Code 500 _affID = pIDxAddr_[_affCode]; 501 502 // if affID is not the same as previously stored 503 if (_affID != plyr_[_pID].laff) 504 { 505 // update last affiliate 506 plyr_[_pID].laff = _affID; 507 } 508 } 509 510 // verify a valid team was selected 511 _team = verifyTeam(_team); 512 513 // reload core 514 reLoadCore(_pID, _affID, _team, _eth, _eventData_); 515 } 516 517 function reLoadXname(bytes32 _affCode, uint256 _team, uint256 _eth) 518 isActivated() 519 isHuman() 520 isWithinLimits(_eth) 521 public 522 { 523 // set up our tx event data 524 F3Ddatasets.EventReturns memory _eventData_; 525 526 // fetch player ID 527 uint256 _pID = pIDxAddr_[msg.sender]; 528 529 // manage affiliate residuals 530 uint256 _affID; 531 // if no affiliate code was given or player tried to use their own, lolz 532 if (_affCode == '' || _affCode == plyr_[_pID].name) 533 { 534 // use last stored affiliate code 535 _affID = plyr_[_pID].laff; 536 537 // if affiliate code was given 538 } else { 539 // get affiliate ID from aff Code 540 _affID = pIDxName_[_affCode]; 541 542 // if affID is not the same as previously stored 543 if (_affID != plyr_[_pID].laff) 544 { 545 // update last affiliate 546 plyr_[_pID].laff = _affID; 547 } 548 } 549 550 // verify a valid team was selected 551 _team = verifyTeam(_team); 552 553 // reload core 554 reLoadCore(_pID, _affID, _team, _eth, _eventData_); 555 } 556 557 /** 558 * @dev withdraws all of your earnings. 559 * -functionhash- 0x3ccfd60b 560 */ 561 function withdraw() 562 isActivated() 563 isHuman() 564 public 565 { 566 // setup local rID 567 uint256 _rID = rID_; 568 569 // grab time 570 uint256 _now = now; 571 572 // fetch player ID 573 uint256 _pID = pIDxAddr_[msg.sender]; 574 575 // setup temp var for player eth 576 uint256 _eth; 577 578 // check to see if round has ended and no one has run round end yet 579 if (_now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) 580 { 581 // set up our tx event data 582 F3Ddatasets.EventReturns memory _eventData_; 583 584 // end the round (distributes pot) 585 round_[_rID].ended = true; 586 _eventData_ = endRound(_eventData_); 587 588 // get their earnings 589 _eth = withdrawEarnings(_pID); 590 591 // gib moni 592 if (_eth > 0) 593 plyr_[_pID].addr.transfer(_eth); 594 595 // build event data 596 _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); 597 _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; 598 599 // fire withdraw and distribute event 600 emit F3Devents.onWithdrawAndDistribute 601 ( 602 msg.sender, 603 plyr_[_pID].name, 604 _eth, 605 _eventData_.compressedData, 606 _eventData_.compressedIDs, 607 _eventData_.winnerAddr, 608 _eventData_.winnerName, 609 _eventData_.amountWon, 610 _eventData_.newPot, 611 _eventData_.P3DAmount, 612 _eventData_.genAmount 613 ); 614 615 // in any other situation 616 } else { 617 // get their earnings 618 _eth = withdrawEarnings(_pID); 619 620 // gib moni 621 if (_eth > 0) 622 plyr_[_pID].addr.transfer(_eth); 623 624 // fire withdraw event 625 emit F3Devents.onWithdraw(_pID, msg.sender, plyr_[_pID].name, _eth, _now); 626 } 627 } 628 629 /** 630 * @dev use these to register names. they are just wrappers that will send the 631 * registration requests to the PlayerBook contract. So registering here is the 632 * same as registering there. UI will always display the last name you registered. 633 * but you will still own all previously registered names to use as affiliate 634 * links. 635 * - must pay a registration fee. 636 * - name must be unique 637 * - names will be converted to lowercase 638 * - name cannot start or end with a space 639 * - cannot have more than 1 space in a row 640 * - cannot be only numbers 641 * - cannot start with 0x 642 * - name must be at least 1 char 643 * - max length of 32 characters long 644 * - allowed characters: a-z, 0-9, and space 645 * -functionhash- 0x921dec21 (using ID for affiliate) 646 * -functionhash- 0x3ddd4698 (using address for affiliate) 647 * -functionhash- 0x685ffd83 (using name for affiliate) 648 * @param _nameString players desired name 649 * @param _affCode affiliate ID, address, or name of who referred you 650 * @param _all set to true if you want this to push your info to all games 651 * (this might cost a lot of gas) 652 */ 653 function registerNameXID(string _nameString, uint256 _affCode, bool _all) 654 isHuman() 655 public 656 payable 657 { 658 bytes32 _name = _nameString.nameFilter(); 659 address _addr = msg.sender; 660 uint256 _paid = msg.value; 661 (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXIDFromDapp.value(_paid)(_addr, _name, _affCode, _all); 662 663 uint256 _pID = pIDxAddr_[_addr]; 664 665 // fire event 666 emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); 667 } 668 669 function registerNameXaddr(string _nameString, address _affCode, bool _all) 670 isHuman() 671 public 672 payable 673 { 674 bytes32 _name = _nameString.nameFilter(); 675 address _addr = msg.sender; 676 uint256 _paid = msg.value; 677 (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXaddrFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); 678 679 uint256 _pID = pIDxAddr_[_addr]; 680 681 // fire event 682 emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); 683 } 684 685 function registerNameXname(string _nameString, bytes32 _affCode, bool _all) 686 isHuman() 687 public 688 payable 689 { 690 bytes32 _name = _nameString.nameFilter(); 691 address _addr = msg.sender; 692 uint256 _paid = msg.value; 693 (bool _isNewPlayer, uint256 _affID) = PlayerBook.registerNameXnameFromDapp.value(msg.value)(msg.sender, _name, _affCode, _all); 694 695 uint256 _pID = pIDxAddr_[_addr]; 696 697 // fire event 698 emit F3Devents.onNewName(_pID, _addr, _name, _isNewPlayer, _affID, plyr_[_affID].addr, plyr_[_affID].name, _paid, now); 699 } 700 //============================================================================== 701 // _ _ _|__|_ _ _ _ . 702 // (_|(/_ | | (/_| _\ . (for UI & viewing things on etherscan) 703 //=====_|======================================================================= 704 /** 705 * @dev return the price buyer will pay for next 1 individual key. 706 * -functionhash- 0x018a25e8 707 * @return price for next key bought (in wei format) 708 */ 709 function getBuyPrice() 710 public 711 view 712 returns(uint256) 713 { 714 // setup local rID 715 uint256 _rID = rID_; 716 717 // grab time 718 uint256 _now = now; 719 720 // are we in a round? 721 if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) 722 return ( (round_[_rID].keys.add(1000000000000000000)).ethRec(1000000000000000000) ); 723 else // rounds over. need price for new round 724 return ( 75000000000000 ); // init 725 } 726 727 /** 728 * @dev returns time left. dont spam this, you'll ddos yourself from your node 729 * provider 730 * -functionhash- 0xc7e284b8 731 * @return time left in seconds 732 */ 733 function getTimeLeft() 734 public 735 view 736 returns(uint256) 737 { 738 // setup local rID 739 uint256 _rID = rID_; 740 741 // grab time 742 uint256 _now = now; 743 744 if (_now < round_[_rID].end) 745 if (_now > round_[_rID].strt + rndGap_) 746 return( (round_[_rID].end).sub(_now) ); 747 else 748 return( (round_[_rID].strt + rndGap_).sub(_now) ); 749 else 750 return(0); 751 } 752 753 /** 754 * @dev returns player earnings per vaults 755 * -functionhash- 0x63066434 756 * @return winnings vault 757 * @return general vault 758 * @return affiliate vault 759 */ 760 function getPlayerVaults(uint256 _pID) 761 public 762 view 763 returns(uint256 ,uint256, uint256) 764 { 765 // setup local rID 766 uint256 _rID = rID_; 767 768 // if round has ended. but round end has not been run (so contract has not distributed winnings) 769 if (now > round_[_rID].end && round_[_rID].ended == false && round_[_rID].plyr != 0) 770 { 771 // if player is winner 772 if (round_[_rID].plyr == _pID) 773 { 774 return 775 ( 776 (plyr_[_pID].win).add( ((round_[_rID].pot).mul(48)) / 100 ), 777 (plyr_[_pID].gen).add( getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask) ), 778 plyr_[_pID].aff 779 ); 780 // if player is not the winner 781 } else { 782 return 783 ( 784 plyr_[_pID].win, 785 (plyr_[_pID].gen).add( getPlayerVaultsHelper(_pID, _rID).sub(plyrRnds_[_pID][_rID].mask) ), 786 plyr_[_pID].aff 787 ); 788 } 789 790 // if round is still going on, or round has ended and round end has been ran 791 } else { 792 return 793 ( 794 plyr_[_pID].win, 795 (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), 796 plyr_[_pID].aff 797 ); 798 } 799 } 800 801 /** 802 * solidity hates stack limits. this lets us avoid that hate 803 */ 804 function getPlayerVaultsHelper(uint256 _pID, uint256 _rID) 805 private 806 view 807 returns(uint256) 808 { 809 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) ); 810 } 811 812 /** 813 * @dev returns all current round info needed for front end 814 * -functionhash- 0x747dff42 815 * @return eth invested during ICO phase 816 * @return round id 817 * @return total keys for round 818 * @return time round ends 819 * @return time round started 820 * @return current pot 821 * @return current team ID & player ID in lead 822 * @return current player in leads address 823 * @return current player in leads name 824 * @return whales eth in for round 825 * @return bears eth in for round 826 * @return sneks eth in for round 827 * @return bulls eth in for round 828 * @return airdrop tracker # & airdrop pot 829 */ 830 function getCurrentRoundInfo() 831 public 832 view 833 returns(uint256, uint256, uint256, uint256, uint256, uint256, uint256, address, bytes32, uint256, uint256, uint256, uint256, uint256) 834 { 835 // setup local rID 836 uint256 _rID = rID_; 837 838 return 839 ( 840 round_[_rID].ico, //0 841 _rID, //1 842 round_[_rID].keys, //2 843 round_[_rID].end, //3 844 round_[_rID].strt, //4 845 round_[_rID].pot, //5 846 (round_[_rID].team + (round_[_rID].plyr * 10)), //6 847 plyr_[round_[_rID].plyr].addr, //7 848 plyr_[round_[_rID].plyr].name, //8 849 rndTmEth_[_rID][0], //9 850 rndTmEth_[_rID][1], //10 851 rndTmEth_[_rID][2], //11 852 rndTmEth_[_rID][3], //12 853 airDropTracker_ + (airDropPot_ * 1000) //13 854 ); 855 } 856 857 /** 858 * @dev returns player info based on address. if no address is given, it will 859 * use msg.sender 860 * -functionhash- 0xee0b5d8b 861 * @param _addr address of the player you want to lookup 862 * @return player ID 863 * @return player name 864 * @return keys owned (current round) 865 * @return winnings vault 866 * @return general vault 867 * @return affiliate vault 868 * @return player round eth 869 */ 870 function getPlayerInfoByAddress(address _addr) 871 public 872 view 873 returns(uint256, bytes32, uint256, uint256, uint256, uint256, uint256) 874 { 875 // setup local rID 876 uint256 _rID = rID_; 877 878 if (_addr == address(0)) 879 { 880 _addr == msg.sender; 881 } 882 uint256 _pID = pIDxAddr_[_addr]; 883 884 return 885 ( 886 _pID, //0 887 plyr_[_pID].name, //1 888 plyrRnds_[_pID][_rID].keys, //2 889 plyr_[_pID].win, //3 890 (plyr_[_pID].gen).add(calcUnMaskedEarnings(_pID, plyr_[_pID].lrnd)), //4 891 plyr_[_pID].aff, //5 892 plyrRnds_[_pID][_rID].eth //6 893 ); 894 } 895 896 //============================================================================== 897 // _ _ _ _ | _ _ . _ . 898 // (_(_)| (/_ |(_)(_||(_ . (this + tools + calcs + modules = our softwares engine) 899 //=====================_|======================================================= 900 /** 901 * @dev logic runs whenever a buy order is executed. determines how to handle 902 * incoming eth depending on if we are in an active round or not 903 */ 904 function buyCore(uint256 _pID, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) 905 private 906 { 907 // setup local rID 908 uint256 _rID = rID_; 909 910 // grab time 911 uint256 _now = now; 912 913 // if round is active 914 if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) 915 { 916 // call core 917 core(_rID, _pID, msg.value, _affID, _team, _eventData_); 918 919 // if round is not active 920 } else { 921 // check to see if end round needs to be ran 922 if (_now > round_[_rID].end && round_[_rID].ended == false) 923 { 924 // end the round (distributes pot) & start new round 925 round_[_rID].ended = true; 926 _eventData_ = endRound(_eventData_); 927 928 // build event data 929 _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); 930 _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; 931 932 // fire buy and distribute event 933 emit F3Devents.onBuyAndDistribute 934 ( 935 msg.sender, 936 plyr_[_pID].name, 937 msg.value, 938 _eventData_.compressedData, 939 _eventData_.compressedIDs, 940 _eventData_.winnerAddr, 941 _eventData_.winnerName, 942 _eventData_.amountWon, 943 _eventData_.newPot, 944 _eventData_.P3DAmount, 945 _eventData_.genAmount 946 ); 947 } 948 949 // put eth in players vault 950 plyr_[_pID].gen = plyr_[_pID].gen.add(msg.value); 951 } 952 } 953 954 /** 955 * @dev logic runs whenever a reload order is executed. determines how to handle 956 * incoming eth depending on if we are in an active round or not 957 */ 958 function reLoadCore(uint256 _pID, uint256 _affID, uint256 _team, uint256 _eth, F3Ddatasets.EventReturns memory _eventData_) 959 private 960 { 961 // setup local rID 962 uint256 _rID = rID_; 963 964 // grab time 965 uint256 _now = now; 966 967 // if round is active 968 if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) 969 { 970 // get earnings from all vaults and return unused to gen vault 971 // because we use a custom safemath library. this will throw if player 972 // tried to spend more eth than they have. 973 plyr_[_pID].gen = withdrawEarnings(_pID).sub(_eth); 974 975 // call core 976 core(_rID, _pID, _eth, _affID, _team, _eventData_); 977 978 // if round is not active and end round needs to be ran 979 } else if (_now > round_[_rID].end && round_[_rID].ended == false) { 980 // end the round (distributes pot) & start new round 981 round_[_rID].ended = true; 982 _eventData_ = endRound(_eventData_); 983 984 // build event data 985 _eventData_.compressedData = _eventData_.compressedData + (_now * 1000000000000000000); 986 _eventData_.compressedIDs = _eventData_.compressedIDs + _pID; 987 988 // fire buy and distribute event 989 emit F3Devents.onReLoadAndDistribute 990 ( 991 msg.sender, 992 plyr_[_pID].name, 993 _eventData_.compressedData, 994 _eventData_.compressedIDs, 995 _eventData_.winnerAddr, 996 _eventData_.winnerName, 997 _eventData_.amountWon, 998 _eventData_.newPot, 999 _eventData_.P3DAmount, 1000 _eventData_.genAmount 1001 ); 1002 } 1003 } 1004 1005 /** 1006 * @dev this is the core logic for any buy/reload that happens while a round 1007 * is live. 1008 */ 1009 function core(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) 1010 private 1011 { 1012 // if player is new to round 1013 if (plyrRnds_[_pID][_rID].keys == 0) 1014 _eventData_ = managePlayer(_pID, _eventData_); 1015 1016 // early round eth limiter 1017 if (round_[_rID].eth < 100000000000000000000 && plyrRnds_[_pID][_rID].eth.add(_eth) > 1000000000000000000) 1018 { 1019 uint256 _availableLimit = (1000000000000000000).sub(plyrRnds_[_pID][_rID].eth); 1020 uint256 _refund = _eth.sub(_availableLimit); 1021 plyr_[_pID].gen = plyr_[_pID].gen.add(_refund); 1022 _eth = _availableLimit; 1023 } 1024 1025 // if eth left is greater than min eth allowed (sorry no pocket lint) 1026 if (_eth > 1000000000) 1027 { 1028 1029 // mint the new keys 1030 uint256 _keys = (round_[_rID].eth).keysRec(_eth); 1031 1032 // if they bought at least 1 whole key 1033 if (_keys >= 1000000000000000000) 1034 { 1035 updateTimer(_keys, _rID); 1036 1037 // set new leaders 1038 if (round_[_rID].plyr != _pID) 1039 round_[_rID].plyr = _pID; 1040 if (round_[_rID].team != _team) 1041 round_[_rID].team = _team; 1042 1043 // set the new leader bool to true 1044 _eventData_.compressedData = _eventData_.compressedData + 100; 1045 } 1046 1047 // manage airdrops 1048 if (_eth >= 100000000000000000) 1049 { 1050 airDropTracker_++; 1051 if (airdrop() == true) 1052 { 1053 // gib muni 1054 uint256 _prize; 1055 if (_eth >= 10000000000000000000) 1056 { 1057 // calculate prize and give it to winner 1058 _prize = ((airDropPot_).mul(75)) / 100; 1059 plyr_[_pID].win = (plyr_[_pID].win).add(_prize); 1060 1061 // adjust airDropPot 1062 airDropPot_ = (airDropPot_).sub(_prize); 1063 1064 // let event know a tier 3 prize was won 1065 _eventData_.compressedData += 300000000000000000000000000000000; 1066 } else if (_eth >= 1000000000000000000 && _eth < 10000000000000000000) { 1067 // calculate prize and give it to winner 1068 _prize = ((airDropPot_).mul(50)) / 100; 1069 plyr_[_pID].win = (plyr_[_pID].win).add(_prize); 1070 1071 // adjust airDropPot 1072 airDropPot_ = (airDropPot_).sub(_prize); 1073 1074 // let event know a tier 2 prize was won 1075 _eventData_.compressedData += 200000000000000000000000000000000; 1076 } else if (_eth >= 100000000000000000 && _eth < 1000000000000000000) { 1077 // calculate prize and give it to winner 1078 _prize = ((airDropPot_).mul(25)) / 100; 1079 plyr_[_pID].win = (plyr_[_pID].win).add(_prize); 1080 1081 // adjust airDropPot 1082 airDropPot_ = (airDropPot_).sub(_prize); 1083 1084 // let event know a tier 3 prize was won 1085 _eventData_.compressedData += 300000000000000000000000000000000; 1086 } 1087 // set airdrop happened bool to true 1088 _eventData_.compressedData += 10000000000000000000000000000000; 1089 // let event know how much was won 1090 _eventData_.compressedData += _prize * 1000000000000000000000000000000000; 1091 1092 // reset air drop tracker 1093 airDropTracker_ = 0; 1094 } 1095 } 1096 1097 // store the air drop tracker number (number of buys since last airdrop) 1098 _eventData_.compressedData = _eventData_.compressedData + (airDropTracker_ * 1000); 1099 1100 // update player 1101 plyrRnds_[_pID][_rID].keys = _keys.add(plyrRnds_[_pID][_rID].keys); 1102 plyrRnds_[_pID][_rID].eth = _eth.add(plyrRnds_[_pID][_rID].eth); 1103 1104 // update round 1105 round_[_rID].keys = _keys.add(round_[_rID].keys); 1106 round_[_rID].eth = _eth.add(round_[_rID].eth); 1107 rndTmEth_[_rID][_team] = _eth.add(rndTmEth_[_rID][_team]); 1108 1109 // distribute eth 1110 _eventData_ = distributeExternal(_rID, _pID, _eth, _affID, _team, _eventData_); 1111 _eventData_ = distributeInternal(_rID, _pID, _eth, _team, _keys, _eventData_); 1112 1113 // call end tx function to fire end tx event. 1114 endTx(_pID, _team, _eth, _keys, _eventData_); 1115 } 1116 } 1117 //============================================================================== 1118 // _ _ | _ | _ _|_ _ _ _ . 1119 // (_(_||(_|_||(_| | (_)| _\ . 1120 //============================================================================== 1121 /** 1122 * @dev calculates unmasked earnings (just calculates, does not update mask) 1123 * @return earnings in wei format 1124 */ 1125 function calcUnMaskedEarnings(uint256 _pID, uint256 _rIDlast) 1126 private 1127 view 1128 returns(uint256) 1129 { 1130 return( (((round_[_rIDlast].mask).mul(plyrRnds_[_pID][_rIDlast].keys)) / (1000000000000000000)).sub(plyrRnds_[_pID][_rIDlast].mask) ); 1131 } 1132 1133 /** 1134 * @dev returns the amount of keys you would get given an amount of eth. 1135 * -functionhash- 0xce89c80c 1136 * @param _rID round ID you want price for 1137 * @param _eth amount of eth sent in 1138 * @return keys received 1139 */ 1140 function calcKeysReceived(uint256 _rID, uint256 _eth) 1141 public 1142 view 1143 returns(uint256) 1144 { 1145 // grab time 1146 uint256 _now = now; 1147 1148 // are we in a round? 1149 if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) 1150 return ( (round_[_rID].eth).keysRec(_eth) ); 1151 else // rounds over. need keys for new round 1152 return ( (_eth).keys() ); 1153 } 1154 1155 /** 1156 * @dev returns current eth price for X keys. 1157 * -functionhash- 0xcf808000 1158 * @param _keys number of keys desired (in 18 decimal format) 1159 * @return amount of eth needed to send 1160 */ 1161 function iWantXKeys(uint256 _keys) 1162 public 1163 view 1164 returns(uint256) 1165 { 1166 // setup local rID 1167 uint256 _rID = rID_; 1168 1169 // grab time 1170 uint256 _now = now; 1171 1172 // are we in a round? 1173 if (_now > round_[_rID].strt + rndGap_ && (_now <= round_[_rID].end || (_now > round_[_rID].end && round_[_rID].plyr == 0))) 1174 return ( (round_[_rID].keys.add(_keys)).ethRec(_keys) ); 1175 else // rounds over. need price for new round 1176 return ( (_keys).eth() ); 1177 } 1178 //============================================================================== 1179 // _|_ _ _ | _ . 1180 // | (_)(_)|_\ . 1181 //============================================================================== 1182 /** 1183 * @dev receives name/player info from names contract 1184 */ 1185 function receivePlayerInfo(uint256 _pID, address _addr, bytes32 _name, uint256 _laff) 1186 external 1187 { 1188 require (msg.sender == address(PlayerBook), "your not playerNames contract... hmmm.."); 1189 if (pIDxAddr_[_addr] != _pID) 1190 pIDxAddr_[_addr] = _pID; 1191 if (pIDxName_[_name] != _pID) 1192 pIDxName_[_name] = _pID; 1193 if (plyr_[_pID].addr != _addr) 1194 plyr_[_pID].addr = _addr; 1195 if (plyr_[_pID].name != _name) 1196 plyr_[_pID].name = _name; 1197 if (plyr_[_pID].laff != _laff) 1198 plyr_[_pID].laff = _laff; 1199 if (plyrNames_[_pID][_name] == false) 1200 plyrNames_[_pID][_name] = true; 1201 } 1202 1203 /** 1204 * @dev receives entire player name list 1205 */ 1206 function receivePlayerNameList(uint256 _pID, bytes32 _name) 1207 external 1208 { 1209 require (msg.sender == address(PlayerBook), "your not playerNames contract... hmmm.."); 1210 if(plyrNames_[_pID][_name] == false) 1211 plyrNames_[_pID][_name] = true; 1212 } 1213 1214 /** 1215 * @dev gets existing or registers new pID. use this when a player may be new 1216 * @return pID 1217 */ 1218 function determinePID(F3Ddatasets.EventReturns memory _eventData_) 1219 private 1220 returns (F3Ddatasets.EventReturns) 1221 { 1222 uint256 _pID = pIDxAddr_[msg.sender]; 1223 // if player is new to this version of fomo3d 1224 if (_pID == 0) 1225 { 1226 // grab their player ID, name and last aff ID, from player names contract 1227 _pID = PlayerBook.getPlayerID(msg.sender); 1228 bytes32 _name = PlayerBook.getPlayerName(_pID); 1229 uint256 _laff = PlayerBook.getPlayerLAff(_pID); 1230 1231 // set up player account 1232 pIDxAddr_[msg.sender] = _pID; 1233 plyr_[_pID].addr = msg.sender; 1234 1235 if (_name != "") 1236 { 1237 pIDxName_[_name] = _pID; 1238 plyr_[_pID].name = _name; 1239 plyrNames_[_pID][_name] = true; 1240 } 1241 1242 if (_laff != 0 && _laff != _pID) 1243 plyr_[_pID].laff = _laff; 1244 1245 // set the new player bool to true 1246 _eventData_.compressedData = _eventData_.compressedData + 1; 1247 } 1248 return (_eventData_); 1249 } 1250 1251 /** 1252 * @dev checks to make sure user picked a valid team. if not sets team 1253 * to default (sneks) 1254 */ 1255 function verifyTeam(uint256 _team) 1256 private 1257 pure 1258 returns (uint256) 1259 { 1260 if (_team < 0 || _team > 3) 1261 return(2); 1262 else 1263 return(_team); 1264 } 1265 1266 /** 1267 * @dev decides if round end needs to be run & new round started. and if 1268 * player unmasked earnings from previously played rounds need to be moved. 1269 */ 1270 function managePlayer(uint256 _pID, F3Ddatasets.EventReturns memory _eventData_) 1271 private 1272 returns (F3Ddatasets.EventReturns) 1273 { 1274 // if player has played a previous round, move their unmasked earnings 1275 // from that round to gen vault. 1276 if (plyr_[_pID].lrnd != 0) 1277 updateGenVault(_pID, plyr_[_pID].lrnd); 1278 1279 // update player's last round played 1280 plyr_[_pID].lrnd = rID_; 1281 1282 // set the joined round bool to true 1283 _eventData_.compressedData = _eventData_.compressedData + 10; 1284 1285 return(_eventData_); 1286 } 1287 1288 /** 1289 * @dev ends the round. manages paying out winner/splitting up pot 1290 */ 1291 function endRound(F3Ddatasets.EventReturns memory _eventData_) 1292 private 1293 returns (F3Ddatasets.EventReturns) 1294 { 1295 // setup local rID 1296 uint256 _rID = rID_; 1297 1298 // grab our winning player and team id's 1299 uint256 _winPID = round_[_rID].plyr; 1300 uint256 _winTID = round_[_rID].team; 1301 1302 // grab our pot amount 1303 uint256 _pot = round_[_rID].pot; 1304 1305 // calculate our winner share, community rewards, gen share, 1306 // p3d share, and amount reserved for next pot 1307 uint256 _win = (_pot.mul(48)) / 100; 1308 uint256 _com = (_pot / 50); 1309 uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100; 1310 uint256 _p3d = (_pot.mul(potSplit_[_winTID].p3d)) / 100; 1311 uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen)).sub(_p3d); 1312 1313 // calculate ppt for round mask 1314 uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); 1315 uint256 _dust = _gen.sub((_ppt.mul(round_[_rID].keys)) / 1000000000000000000); 1316 if (_dust > 0) 1317 { 1318 _gen = _gen.sub(_dust); 1319 _res = _res.add(_dust); 1320 } 1321 1322 // pay our winner 1323 plyr_[_winPID].win = _win.add(plyr_[_winPID].win); 1324 1325 // community rewards 1326 if (!address(Jekyll_Island_Inc).call.value(_com)(bytes4(keccak256("deposit()")))) 1327 { 1328 // This ensures Team Just cannot influence the outcome of FoMo3D with 1329 // bank migrations by breaking outgoing transactions. 1330 // Something we would never do. But that's not the point. 1331 // We spent 2000$ in eth re-deploying just to patch this, we hold the 1332 // highest belief that everything we create should be trustless. 1333 // Team JUST, The name you shouldn't have to trust. 1334 _p3d = _p3d.add(_com); 1335 _com = 0; 1336 } 1337 1338 // distribute gen portion to key holders 1339 round_[_rID].mask = _ppt.add(round_[_rID].mask); 1340 1341 // send share for p3d to divies 1342 if (_p3d > 0) 1343 Divies.deposit.value(_p3d)(); 1344 1345 // prepare event data 1346 _eventData_.compressedData = _eventData_.compressedData + (round_[_rID].end * 1000000); 1347 _eventData_.compressedIDs = _eventData_.compressedIDs + (_winPID * 100000000000000000000000000) + (_winTID * 100000000000000000); 1348 _eventData_.winnerAddr = plyr_[_winPID].addr; 1349 _eventData_.winnerName = plyr_[_winPID].name; 1350 _eventData_.amountWon = _win; 1351 _eventData_.genAmount = _gen; 1352 _eventData_.P3DAmount = _p3d; 1353 _eventData_.newPot = _res; 1354 1355 // start next round 1356 rID_++; 1357 _rID++; 1358 round_[_rID].strt = now; 1359 round_[_rID].end = now.add(rndInit_).add(rndGap_); 1360 round_[_rID].pot = _res; 1361 1362 return(_eventData_); 1363 } 1364 1365 /** 1366 * @dev moves any unmasked earnings to gen vault. updates earnings mask 1367 */ 1368 function updateGenVault(uint256 _pID, uint256 _rIDlast) 1369 private 1370 { 1371 uint256 _earnings = calcUnMaskedEarnings(_pID, _rIDlast); 1372 if (_earnings > 0) 1373 { 1374 // put in gen vault 1375 plyr_[_pID].gen = _earnings.add(plyr_[_pID].gen); 1376 // zero out their earnings by updating mask 1377 plyrRnds_[_pID][_rIDlast].mask = _earnings.add(plyrRnds_[_pID][_rIDlast].mask); 1378 } 1379 } 1380 1381 /** 1382 * @dev updates round timer based on number of whole keys bought. 1383 */ 1384 function updateTimer(uint256 _keys, uint256 _rID) 1385 private 1386 { 1387 // grab time 1388 uint256 _now = now; 1389 1390 // calculate time based on number of keys bought 1391 uint256 _newTime; 1392 if (_now > round_[_rID].end && round_[_rID].plyr == 0) 1393 _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(_now); 1394 else 1395 _newTime = (((_keys) / (1000000000000000000)).mul(rndInc_)).add(round_[_rID].end); 1396 1397 // compare to max and set new end time 1398 if (_newTime < (rndMax_).add(_now)) 1399 round_[_rID].end = _newTime; 1400 else 1401 round_[_rID].end = rndMax_.add(_now); 1402 } 1403 1404 /** 1405 * @dev generates a random number between 0-99 and checks to see if thats 1406 * resulted in an airdrop win 1407 * @return do we have a winner? 1408 */ 1409 function airdrop() 1410 private 1411 view 1412 returns(bool) 1413 { 1414 uint256 seed = uint256(keccak256(abi.encodePacked( 1415 1416 (block.timestamp).add 1417 (block.difficulty).add 1418 ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add 1419 (block.gaslimit).add 1420 ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add 1421 (block.number) 1422 1423 ))); 1424 if((seed - ((seed / 1000) * 1000)) < airDropTracker_) 1425 return(true); 1426 else 1427 return(false); 1428 } 1429 1430 /** 1431 * @dev distributes eth based on fees to com, aff, and p3d 1432 */ 1433 function distributeExternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID, uint256 _team, F3Ddatasets.EventReturns memory _eventData_) 1434 private 1435 returns(F3Ddatasets.EventReturns) 1436 { 1437 // pay 2% out to community rewards 1438 uint256 _com = _eth / 50; 1439 uint256 _p3d; 1440 if (!address(Jekyll_Island_Inc).call.value(_com)(bytes4(keccak256("deposit()")))) 1441 { 1442 // This ensures Team Just cannot influence the outcome of FoMo3D with 1443 // bank migrations by breaking outgoing transactions. 1444 // Something we would never do. But that's not the point. 1445 // We spent 2000$ in eth re-deploying just to patch this, we hold the 1446 // highest belief that everything we create should be trustless. 1447 // Team JUST, The name you shouldn't have to trust. 1448 _p3d = _com; 1449 _com = 0; 1450 } 1451 1452 // pay 1% out to FoMo3D short 1453 uint256 _long = _eth / 100; 1454 otherF3D_.potSwap.value(_long)(); 1455 1456 // distribute share to affiliate 1457 uint256 _aff = _eth / 10; 1458 1459 // decide what to do with affiliate share of fees 1460 // affiliate must not be self, and must have a name registered 1461 if (_affID != _pID && plyr_[_affID].name != '') { 1462 plyr_[_affID].aff = _aff.add(plyr_[_affID].aff); 1463 emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _aff, now); 1464 } else { 1465 _p3d = _aff; 1466 } 1467 1468 // pay out p3d 1469 _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100)); 1470 if (_p3d > 0) 1471 { 1472 // deposit to divies contract 1473 Divies.deposit.value(_p3d)(); 1474 1475 // set up event data 1476 _eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount); 1477 } 1478 1479 return(_eventData_); 1480 } 1481 1482 function potSwap() 1483 external 1484 payable 1485 { 1486 // setup local rID 1487 uint256 _rID = rID_ + 1; 1488 1489 round_[_rID].pot = round_[_rID].pot.add(msg.value); 1490 emit F3Devents.onPotSwapDeposit(_rID, msg.value); 1491 } 1492 1493 /** 1494 * @dev distributes eth based on fees to gen and pot 1495 */ 1496 function distributeInternal(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _team, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) 1497 private 1498 returns(F3Ddatasets.EventReturns) 1499 { 1500 // calculate gen share 1501 uint256 _gen = (_eth.mul(fees_[_team].gen)) / 100; 1502 1503 // toss 1% into airdrop pot 1504 uint256 _air = (_eth / 100); 1505 airDropPot_ = airDropPot_.add(_air); 1506 1507 // update eth balance (eth = eth - (com share + pot swap share + aff share + p3d share + airdrop pot share)) 1508 _eth = _eth.sub(((_eth.mul(14)) / 100).add((_eth.mul(fees_[_team].p3d)) / 100)); 1509 1510 // calculate pot 1511 uint256 _pot = _eth.sub(_gen); 1512 1513 // distribute gen share (thats what updateMasks() does) and adjust 1514 // balances for dust. 1515 uint256 _dust = updateMasks(_rID, _pID, _gen, _keys); 1516 if (_dust > 0) 1517 _gen = _gen.sub(_dust); 1518 1519 // add eth to pot 1520 round_[_rID].pot = _pot.add(_dust).add(round_[_rID].pot); 1521 1522 // set up event data 1523 _eventData_.genAmount = _gen.add(_eventData_.genAmount); 1524 _eventData_.potAmount = _pot; 1525 1526 return(_eventData_); 1527 } 1528 1529 /** 1530 * @dev updates masks for round and player when keys are bought 1531 * @return dust left over 1532 */ 1533 function updateMasks(uint256 _rID, uint256 _pID, uint256 _gen, uint256 _keys) 1534 private 1535 returns(uint256) 1536 { 1537 /* MASKING NOTES 1538 earnings masks are a tricky thing for people to wrap their minds around. 1539 the basic thing to understand here. is were going to have a global 1540 tracker based on profit per share for each round, that increases in 1541 relevant proportion to the increase in share supply. 1542 1543 the player will have an additional mask that basically says "based 1544 on the rounds mask, my shares, and how much i've already withdrawn, 1545 how much is still owed to me?" 1546 */ 1547 1548 // calc profit per key & round mask based on this buy: (dust goes to pot) 1549 uint256 _ppt = (_gen.mul(1000000000000000000)) / (round_[_rID].keys); 1550 round_[_rID].mask = _ppt.add(round_[_rID].mask); 1551 1552 // calculate player earning from their own buy (only based on the keys 1553 // they just bought). & update player earnings mask 1554 uint256 _pearn = (_ppt.mul(_keys)) / (1000000000000000000); 1555 plyrRnds_[_pID][_rID].mask = (((round_[_rID].mask.mul(_keys)) / (1000000000000000000)).sub(_pearn)).add(plyrRnds_[_pID][_rID].mask); 1556 1557 // calculate & return dust 1558 return(_gen.sub((_ppt.mul(round_[_rID].keys)) / (1000000000000000000))); 1559 } 1560 1561 /** 1562 * @dev adds up unmasked earnings, & vault earnings, sets them all to 0 1563 * @return earnings in wei format 1564 */ 1565 function withdrawEarnings(uint256 _pID) 1566 private 1567 returns(uint256) 1568 { 1569 // update gen vault 1570 updateGenVault(_pID, plyr_[_pID].lrnd); 1571 1572 // from vaults 1573 uint256 _earnings = (plyr_[_pID].win).add(plyr_[_pID].gen).add(plyr_[_pID].aff); 1574 if (_earnings > 0) 1575 { 1576 plyr_[_pID].win = 0; 1577 plyr_[_pID].gen = 0; 1578 plyr_[_pID].aff = 0; 1579 } 1580 1581 return(_earnings); 1582 } 1583 1584 /** 1585 * @dev prepares compression data and fires event for buy or reload tx's 1586 */ 1587 function endTx(uint256 _pID, uint256 _team, uint256 _eth, uint256 _keys, F3Ddatasets.EventReturns memory _eventData_) 1588 private 1589 { 1590 _eventData_.compressedData = _eventData_.compressedData + (now * 1000000000000000000) + (_team * 100000000000000000000000000000); 1591 _eventData_.compressedIDs = _eventData_.compressedIDs + _pID + (rID_ * 10000000000000000000000000000000000000000000000000000); 1592 1593 emit F3Devents.onEndTx 1594 ( 1595 _eventData_.compressedData, 1596 _eventData_.compressedIDs, 1597 plyr_[_pID].name, 1598 msg.sender, 1599 _eth, 1600 _keys, 1601 _eventData_.winnerAddr, 1602 _eventData_.winnerName, 1603 _eventData_.amountWon, 1604 _eventData_.newPot, 1605 _eventData_.P3DAmount, 1606 _eventData_.genAmount, 1607 _eventData_.potAmount, 1608 airDropPot_ 1609 ); 1610 } 1611 //============================================================================== 1612 // (~ _ _ _._|_ . 1613 // _)(/_(_|_|| | | \/ . 1614 //====================/========================================================= 1615 /** upon contract deploy, it will be deactivated. this is a one time 1616 * use function that will activate the contract. we do this so devs 1617 * have time to set things up on the web end **/ 1618 bool public activated_ = false; 1619 function activate() 1620 public 1621 { 1622 // only team just can activate 1623 require( 1624 msg.sender == 0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C || 1625 msg.sender == 0x8b4DA1827932D71759687f925D17F81Fc94e3A9D || 1626 msg.sender == 0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53 || 1627 msg.sender == 0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C || 1628 msg.sender == 0xF39e044e1AB204460e06E87c6dca2c6319fC69E3, 1629 "only team just can activate" 1630 ); 1631 1632 // make sure that its been linked. 1633 require(address(otherF3D_) != address(0), "must link to other FoMo3D first"); 1634 1635 // can only be ran once 1636 require(activated_ == false, "fomo3d already activated"); 1637 1638 // activate the contract 1639 activated_ = true; 1640 1641 // lets start first round 1642 rID_ = 1; 1643 round_[1].strt = now + rndExtra_ - rndGap_; 1644 round_[1].end = now + rndInit_ + rndExtra_; 1645 } 1646 function setOtherFomo(address _otherF3D) 1647 public 1648 { 1649 // only team just can activate 1650 require( 1651 msg.sender == 0x18E90Fc6F70344f53EBd4f6070bf6Aa23e2D748C || 1652 msg.sender == 0x8b4DA1827932D71759687f925D17F81Fc94e3A9D || 1653 msg.sender == 0x8e0d985f3Ec1857BEc39B76aAabDEa6B31B67d53 || 1654 msg.sender == 0x7ac74Fcc1a71b106F12c55ee8F802C9F672Ce40C || 1655 msg.sender == 0xF39e044e1AB204460e06E87c6dca2c6319fC69E3, 1656 "only team just can activate" 1657 ); 1658 1659 // make sure that it HASNT yet been linked. 1660 require(address(otherF3D_) == address(0), "silly dev, you already did that"); 1661 1662 // set up other fomo3d (fast or long) for pot swap 1663 otherF3D_ = otherFoMo3D(_otherF3D); 1664 } 1665 } 1666 1667 //============================================================================== 1668 // __|_ _ __|_ _ . 1669 // _\ | | |_|(_ | _\ . 1670 //============================================================================== 1671 library F3Ddatasets { 1672 //compressedData key 1673 // [76-33][32][31][30][29][28-18][17][16-6][5-3][2][1][0] 1674 // 0 - new player (bool) 1675 // 1 - joined round (bool) 1676 // 2 - new leader (bool) 1677 // 3-5 - air drop tracker (uint 0-999) 1678 // 6-16 - round end time 1679 // 17 - winnerTeam 1680 // 18 - 28 timestamp 1681 // 29 - team 1682 // 30 - 0 = reinvest (round), 1 = buy (round), 2 = buy (ico), 3 = reinvest (ico) 1683 // 31 - airdrop happened bool 1684 // 32 - airdrop tier 1685 // 33 - airdrop amount won 1686 //compressedIDs key 1687 // [77-52][51-26][25-0] 1688 // 0-25 - pID 1689 // 26-51 - winPID 1690 // 52-77 - rID 1691 struct EventReturns { 1692 uint256 compressedData; 1693 uint256 compressedIDs; 1694 address winnerAddr; // winner address 1695 bytes32 winnerName; // winner name 1696 uint256 amountWon; // amount won 1697 uint256 newPot; // amount in new pot 1698 uint256 P3DAmount; // amount distributed to p3d 1699 uint256 genAmount; // amount distributed to gen 1700 uint256 potAmount; // amount added to pot 1701 } 1702 struct Player { 1703 address addr; // player address 1704 bytes32 name; // player name 1705 uint256 win; // winnings vault 1706 uint256 gen; // general vault 1707 uint256 aff; // affiliate vault 1708 uint256 lrnd; // last round played 1709 uint256 laff; // last affiliate id used 1710 } 1711 struct PlayerRounds { 1712 uint256 eth; // eth player has added to round (used for eth limiter) 1713 uint256 keys; // keys 1714 uint256 mask; // player mask 1715 uint256 ico; // ICO phase investment 1716 } 1717 struct Round { 1718 uint256 plyr; // pID of player in lead 1719 uint256 team; // tID of team in lead 1720 uint256 end; // time ends/ended 1721 bool ended; // has round end function been ran 1722 uint256 strt; // time round started 1723 uint256 keys; // keys 1724 uint256 eth; // total eth in 1725 uint256 pot; // eth to pot (during round) / final amount paid to winner (after round ends) 1726 uint256 mask; // global mask 1727 uint256 ico; // total eth sent in during ICO phase 1728 uint256 icoGen; // total eth for gen during ICO phase 1729 uint256 icoAvg; // average key price for ICO phase 1730 } 1731 struct TeamFee { 1732 uint256 gen; // % of buy in thats paid to key holders of current round 1733 uint256 p3d; // % of buy in thats paid to p3d holders 1734 } 1735 struct PotSplit { 1736 uint256 gen; // % of pot thats paid to key holders of current round 1737 uint256 p3d; // % of pot thats paid to p3d holders 1738 } 1739 } 1740 1741 //============================================================================== 1742 // | _ _ _ | _ . 1743 // |<(/_\/ (_(_||(_ . 1744 //=======/====================================================================== 1745 library F3DKeysCalcLong { 1746 using SafeMath for *; 1747 /** 1748 * @dev calculates number of keys received given X eth 1749 * @param _curEth current amount of eth in contract 1750 * @param _newEth eth being spent 1751 * @return amount of ticket purchased 1752 */ 1753 function keysRec(uint256 _curEth, uint256 _newEth) 1754 internal 1755 pure 1756 returns (uint256) 1757 { 1758 return(keys((_curEth).add(_newEth)).sub(keys(_curEth))); 1759 } 1760 1761 /** 1762 * @dev calculates amount of eth received if you sold X keys 1763 * @param _curKeys current amount of keys that exist 1764 * @param _sellKeys amount of keys you wish to sell 1765 * @return amount of eth received 1766 */ 1767 function ethRec(uint256 _curKeys, uint256 _sellKeys) 1768 internal 1769 pure 1770 returns (uint256) 1771 { 1772 return((eth(_curKeys)).sub(eth(_curKeys.sub(_sellKeys)))); 1773 } 1774 1775 /** 1776 * @dev calculates how many keys would exist with given an amount of eth 1777 * @param _eth eth "in contract" 1778 * @return number of keys that would exist 1779 */ 1780 function keys(uint256 _eth) 1781 internal 1782 pure 1783 returns(uint256) 1784 { 1785 return ((((((_eth).mul(1000000000000000000)).mul(312500000000000000000000000)).add(5624988281256103515625000000000000000000000000000000000000000000)).sqrt()).sub(74999921875000000000000000000000)) / (156250000); 1786 } 1787 1788 /** 1789 * @dev calculates how much eth would be in contract given a number of keys 1790 * @param _keys number of keys "in contract" 1791 * @return eth that would exists 1792 */ 1793 function eth(uint256 _keys) 1794 internal 1795 pure 1796 returns(uint256) 1797 { 1798 return ((78125000).mul(_keys.sq()).add(((149999843750000).mul(_keys.mul(1000000000000000000))) / (2))) / ((1000000000000000000).sq()); 1799 } 1800 } 1801 1802 //============================================================================== 1803 // . _ _|_ _ _ |` _ _ _ _ . 1804 // || | | (/_| ~|~(_|(_(/__\ . 1805 //============================================================================== 1806 interface otherFoMo3D { 1807 function potSwap() external payable; 1808 } 1809 1810 interface F3DexternalSettingsInterface { 1811 function getFastGap() external returns(uint256); 1812 function getLongGap() external returns(uint256); 1813 function getFastExtra() external returns(uint256); 1814 function getLongExtra() external returns(uint256); 1815 } 1816 1817 interface DiviesInterface { 1818 function deposit() external payable; 1819 } 1820 1821 interface JIincForwarderInterface { 1822 function deposit() external payable returns(bool); 1823 function status() external view returns(address, address, bool); 1824 function startMigration(address _newCorpBank) external returns(bool); 1825 function cancelMigration() external returns(bool); 1826 function finishMigration() external returns(bool); 1827 function setup(address _firstCorpBank) external; 1828 } 1829 1830 interface PlayerBookInterface { 1831 function getPlayerID(address _addr) external returns (uint256); 1832 function getPlayerName(uint256 _pID) external view returns (bytes32); 1833 function getPlayerLAff(uint256 _pID) external view returns (uint256); 1834 function getPlayerAddr(uint256 _pID) external view returns (address); 1835 function getNameFee() external view returns (uint256); 1836 function registerNameXIDFromDapp(address _addr, bytes32 _name, uint256 _affCode, bool _all) external payable returns(bool, uint256); 1837 function registerNameXaddrFromDapp(address _addr, bytes32 _name, address _affCode, bool _all) external payable returns(bool, uint256); 1838 function registerNameXnameFromDapp(address _addr, bytes32 _name, bytes32 _affCode, bool _all) external payable returns(bool, uint256); 1839 } 1840 1841 /** 1842 * @title -Name Filter- v0.1.9 1843 * ┌┬┐┌─┐┌─┐┌┬┐ ╦╦ ╦╔═╗╔╦╗ ┌─┐┬─┐┌─┐┌─┐┌─┐┌┐┌┌┬┐┌─┐ 1844 * │ ├┤ ├─┤│││ ║║ ║╚═╗ ║ ├─┘├┬┘├┤ └─┐├┤ │││ │ └─┐ 1845 * ┴ └─┘┴ ┴┴ ┴ ╚╝╚═╝╚═╝ ╩ ┴ ┴└─└─┘└─┘└─┘┘└┘ ┴ └─┘ 1846 * _____ _____ 1847 * (, / /) /) /) (, / /) /) 1848 * ┌─┐ / _ (/_ // // / _ // _ __ _(/ 1849 * ├─┤ ___/___(/_/(__(_/_(/_(/_ ___/__/_)_(/_(_(_/ (_(_(_ 1850 * ┴ ┴ / / .-/ _____ (__ / 1851 * (__ / (_/ (, / /)™ 1852 * / __ __ __ __ _ __ __ _ _/_ _ _(/ 1853 * ┌─┐┬─┐┌─┐┌┬┐┬ ┬┌─┐┌┬┐ /__/ (_(__(_)/ (_/_)_(_)/ (_(_(_(__(/_(_(_ 1854 * ├─┘├┬┘│ │ │││ ││ │ (__ / .-/ © Jekyll Island Inc. 2018 1855 * ┴ ┴└─└─┘─┴┘└─┘└─┘ ┴ (_/ 1856 * _ __ _ ____ ____ _ _ _____ ____ ___ 1857 *=============| |\ | / /\ | |\/| | |_ =====| |_ | | | | | | | |_ | |_)==============* 1858 *=============|_| \| /_/--\ |_| | |_|__=====|_| |_| |_|__ |_| |_|__ |_| \==============* 1859 * 1860 * ╔═╗┌─┐┌┐┌┌┬┐┬─┐┌─┐┌─┐┌┬┐ ╔═╗┌─┐┌┬┐┌─┐ ┌──────────┐ 1861 * ║ │ ││││ │ ├┬┘├─┤│ │ ║ │ │ ││├┤ │ Inventor │ 1862 * ╚═╝└─┘┘└┘ ┴ ┴└─┴ ┴└─┘ ┴ ╚═╝└─┘─┴┘└─┘ └──────────┘ 1863 */ 1864 1865 library NameFilter { 1866 /** 1867 * @dev filters name strings 1868 * -converts uppercase to lower case. 1869 * -makes sure it does not start/end with a space 1870 * -makes sure it does not contain multiple spaces in a row 1871 * -cannot be only numbers 1872 * -cannot start with 0x 1873 * -restricts characters to A-Z, a-z, 0-9, and space. 1874 * @return reprocessed string in bytes32 format 1875 */ 1876 function nameFilter(string _input) 1877 internal 1878 pure 1879 returns(bytes32) 1880 { 1881 bytes memory _temp = bytes(_input); 1882 uint256 _length = _temp.length; 1883 1884 //sorry limited to 32 characters 1885 require (_length <= 32 && _length > 0, "string must be between 1 and 32 characters"); 1886 // make sure it doesnt start with or end with space 1887 require(_temp[0] != 0x20 && _temp[_length-1] != 0x20, "string cannot start or end with space"); 1888 // make sure first two characters are not 0x 1889 if (_temp[0] == 0x30) 1890 { 1891 require(_temp[1] != 0x78, "string cannot start with 0x"); 1892 require(_temp[1] != 0x58, "string cannot start with 0X"); 1893 } 1894 1895 // create a bool to track if we have a non number character 1896 bool _hasNonNumber; 1897 1898 // convert & check 1899 for (uint256 i = 0; i < _length; i++) 1900 { 1901 // if its uppercase A-Z 1902 if (_temp[i] > 0x40 && _temp[i] < 0x5b) 1903 { 1904 // convert to lower case a-z 1905 _temp[i] = byte(uint(_temp[i]) + 32); 1906 1907 // we have a non number 1908 if (_hasNonNumber == false) 1909 _hasNonNumber = true; 1910 } else { 1911 require 1912 ( 1913 // require character is a space 1914 _temp[i] == 0x20 || 1915 // OR lowercase a-z 1916 (_temp[i] > 0x60 && _temp[i] < 0x7b) || 1917 // or 0-9 1918 (_temp[i] > 0x2f && _temp[i] < 0x3a), 1919 "string contains invalid characters" 1920 ); 1921 // make sure theres not 2x spaces in a row 1922 if (_temp[i] == 0x20) 1923 require( _temp[i+1] != 0x20, "string cannot contain consecutive spaces"); 1924 1925 // see if we have a character other than a number 1926 if (_hasNonNumber == false && (_temp[i] < 0x30 || _temp[i] > 0x39)) 1927 _hasNonNumber = true; 1928 } 1929 } 1930 1931 require(_hasNonNumber == true, "string cannot be only numbers"); 1932 1933 bytes32 _ret; 1934 assembly { 1935 _ret := mload(add(_temp, 32)) 1936 } 1937 return (_ret); 1938 } 1939 } 1940 1941 /** 1942 * @title SafeMath v0.1.9 1943 * @dev Math operations with safety checks that throw on error 1944 * change notes: original SafeMath library from OpenZeppelin modified by Inventor 1945 * - added sqrt 1946 * - added sq 1947 * - added pwr 1948 * - changed asserts to requires with error log outputs 1949 * - removed div, its useless 1950 */ 1951 library SafeMath { 1952 1953 /** 1954 * @dev Multiplies two numbers, throws on overflow. 1955 */ 1956 function mul(uint256 a, uint256 b) 1957 internal 1958 pure 1959 returns (uint256 c) 1960 { 1961 if (a == 0) { 1962 return 0; 1963 } 1964 c = a * b; 1965 require(c / a == b, "SafeMath mul failed"); 1966 return c; 1967 } 1968 1969 /** 1970 * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). 1971 */ 1972 function sub(uint256 a, uint256 b) 1973 internal 1974 pure 1975 returns (uint256) 1976 { 1977 require(b <= a, "SafeMath sub failed"); 1978 return a - b; 1979 } 1980 1981 /** 1982 * @dev Adds two numbers, throws on overflow. 1983 */ 1984 function add(uint256 a, uint256 b) 1985 internal 1986 pure 1987 returns (uint256 c) 1988 { 1989 c = a + b; 1990 require(c >= a, "SafeMath add failed"); 1991 return c; 1992 } 1993 1994 /** 1995 * @dev gives square root of given x. 1996 */ 1997 function sqrt(uint256 x) 1998 internal 1999 pure 2000 returns (uint256 y) 2001 { 2002 uint256 z = ((add(x,1)) / 2); 2003 y = x; 2004 while (z < y) 2005 { 2006 y = z; 2007 z = ((add((x / z),z)) / 2); 2008 } 2009 } 2010 2011 /** 2012 * @dev gives square. multiplies x by x 2013 */ 2014 function sq(uint256 x) 2015 internal 2016 pure 2017 returns (uint256) 2018 { 2019 return (mul(x,x)); 2020 } 2021 2022 /** 2023 * @dev x to the power of y 2024 */ 2025 function pwr(uint256 x, uint256 y) 2026 internal 2027 pure 2028 returns (uint256) 2029 { 2030 if (x==0) 2031 return (0); 2032 else if (y==0) 2033 return (1); 2034 else 2035 { 2036 uint256 z = x; 2037 for (uint256 i=1; i < y; i++) 2038 z = mul(z,x); 2039 return (z); 2040 } 2041 } 2042 }