Transaction Hash:
Block:
6116506 at Aug-09-2018 01:08:04 PM +UTC
Transaction Fee:
0.011886001 ETH
$25.59
Gas Used:
177,403 Gas / 67 Gwei
Emitted Events:
| 25 |
F4Kings.onEndTx( compressedData=201533820084000000000000009100, compressedIDs=10000000000000000000000000000000000000000000000000046, playerName=0000000000000000000000000000000000000000000000000000000000000000, playerAddress=[Sender] 0x40dae1f03d4f28fcdb51e3f8236372f0a37b35e1, ethIn=100000000000000000, keysBought=492259097415021250590, winnerAddr=0x00000000...000000000, winnerName=0000000000000000000000000000000000000000000000000000000000000000, amountWon=0, newPot=0, P3DAmount=10000000000000000, genAmount=51999999999553239, potAmount=18000000000000000, airDropPot=464771597600449832 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x112a6fc6...14329aEbd | 14.440974695784380633 Eth | 14.452724695784380633 Eth | 0.01175 | ||
| 0x40dAe1F0...0a37b35e1 |
19.519338637847439889 Eth
Nonce: 486
|
19.407452636847439889 Eth
Nonce: 487
| 0.111886001 | ||
| 0x431C4354...5C725DA5c | 4.905816601250918757 Eth | 4.909066601250918757 Eth | 0.00325 | ||
| 0xA9B9805D...79c47bA53 | 47.76941608184494113 Eth | 47.85441608184494113 Eth | 0.085 | ||
|
0xEA674fdD...16B898ec8
Miner
| (Ethermine) | 1,141.700213724371392965 Eth | 1,141.712099725371392965 Eth | 0.011886001 |
Execution Trace
ETH 0.1
F4Kings.CALL( )
- ETH 0.01
0x112a6fc6a5e593cd9b90e3b0540a74814329aebd.CALL( ) - ETH 0.00325
0x431c4354db7f2b9ac1d9b2019e925c85c725da5c.CALL( ) - ETH 0.00175
0x112a6fc6a5e593cd9b90e3b0540a74814329aebd.CALL( )
[F4Kings (ln:243)]
determinePID[F4Kings (ln:251)]getPlayerID[F4Kings (ln:1105)]getPlayerName[F4Kings (ln:1106)]getPlayerLAff[F4Kings (ln:1107)]
buyCore[F4Kings (ln:257)]core[F4Kings (ln:804)]managePlayer[F4Kings (ln:901)]updateGenVault[F4Kings (ln:1155)]calcUnMaskedEarnings[F4Kings (ln:1235)]add[F4Kings (ln:1239)]add[F4Kings (ln:1241)]
keysRec[F4Kings (ln:908)]mul[F4Kings (ln:936)]add[F4Kings (ln:937)]sub[F4Kings (ln:940)]mul[F4Kings (ln:946)]add[F4Kings (ln:947)]sub[F4Kings (ln:950)]mul[F4Kings (ln:956)]add[F4Kings (ln:957)]sub[F4Kings (ln:960)]add[F4Kings (ln:979)]add[F4Kings (ln:980)]add[F4Kings (ln:983)]add[F4Kings (ln:984)]add[F4Kings (ln:985)]distributeExternal[F4Kings (ln:988)]value[F4Kings (ln:1311)]add[F4Kings (ln:1321)]distributeAff[F4Kings (ln:1321)]add[F4Kings (ln:1359)]onAffiliatePayout[F4Kings (ln:1361)]add[F4Kings (ln:1367)]onAffiliatePayout[F4Kings (ln:1368)]add[F4Kings (ln:1374)]onAffiliatePayout[F4Kings (ln:1375)]add[F4Kings (ln:1377)]add[F4Kings (ln:1380)]add[F4Kings (ln:1383)]
sub[F4Kings (ln:1329)]transfer[F4Kings (ln:1331)]mul[F4Kings (ln:1331)]transfer[F4Kings (ln:1332)]mul[F4Kings (ln:1332)]add[F4Kings (ln:1334)]add[F4Kings (ln:1337)]
distributeInternal[F4Kings (ln:989)]endTx[F4Kings (ln:992)]onEndTx[F4Kings (ln:1509)]
endRound[F4Kings (ln:813)]mul[F4Kings (ln:1185)]mul[F4Kings (ln:1187)]sub[F4Kings (ln:1188)]sub[F4Kings (ln:1188)]sub[F4Kings (ln:1188)]mul[F4Kings (ln:1191)]sub[F4Kings (ln:1192)]mul[F4Kings (ln:1192)]sub[F4Kings (ln:1195)]add[F4Kings (ln:1196)]add[F4Kings (ln:1200)]transfer[F4Kings (ln:1203)]mul[F4Kings (ln:1203)]transfer[F4Kings (ln:1204)]mul[F4Kings (ln:1204)]add[F4Kings (ln:1207)]add[F4Kings (ln:1223)]add[F4Kings (ln:1223)]
onBuyAndDistribute[F4Kings (ln:820)]add[F4Kings (ln:837)]
pragma solidity ^0.4.24;
contract F3Devents {
// fired whenever a player registers a name
event onNewName
(
uint256 indexed playerID,
address indexed playerAddress,
bytes32 indexed playerName,
bool isNewPlayer,
uint256 affiliateID,
address affiliateAddress,
bytes32 affiliateName,
uint256 amountPaid,
uint256 timeStamp
);
// fired at end of buy or reload
event onEndTx
(
uint256 compressedData,
uint256 compressedIDs,
bytes32 playerName,
address playerAddress,
uint256 ethIn,
uint256 keysBought,
address winnerAddr,
bytes32 winnerName,
uint256 amountWon,
uint256 newPot,
uint256 P3DAmount,
uint256 genAmount,
uint256 potAmount,
uint256 airDropPot
);
// fired whenever theres a withdraw
event onWithdraw
(
uint256 indexed playerID,
address playerAddress,
bytes32 playerName,
uint256 ethOut,
uint256 timeStamp
);
// fired whenever a withdraw forces end round to be ran
event onWithdrawAndDistribute
(
address playerAddress,
bytes32 playerName,
uint256 ethOut,
uint256 compressedData,
uint256 compressedIDs,
address winnerAddr,
bytes32 winnerName,
uint256 amountWon,
uint256 newPot,
uint256 P3DAmount,
uint256 genAmount
);
// (fomo3d short 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 short 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 modularShort is F3Devents {}
contract F4Kings is modularShort {
using SafeMath for *;
using NameFilter for string;
using F3DKeysCalcShort for uint256;
PlayerBookInterface constant private PlayerBook = PlayerBookInterface(0xf626967fA13d841fd74D49dEe9bDd0D0dD6C4394);
//==============================================================================
// _ _ _ |`. _ _ _ |_ | _ _ .
// (_(_)| |~|~|(_||_|| (_||_)|(/__\ . (game settings)
//=================_|===========================================================
address private admin = msg.sender;
address private shareCom = 0x431C4354dB7f2b9aC1d9B2019e925C85C725DA5c;
string constant public name = "f4kings";
string constant public symbol = "f4kings";
uint256 private rndExtra_ = 0; // length of the very first ICO
uint256 private rndGap_ = 2 minutes; // length of ICO phase, set to 1 year for EOS.
uint256 constant private rndInit_ = 24 hours; // round timer starts at this
uint256 constant private rndInc_ = 20 seconds; // every full key purchased adds this much to the timer
uint256 constant private rndMax_ = 24 hours; // max length a round timer can be
uint256 constant private rndLimit_ = 3; // limit rnd eth purchase
//==============================================================================
// _| _ _|_ _ _ _ _|_ _ .
// (_|(_| | (_| _\(/_ | |_||_) . (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) + (Pot , Referrals, Community)
// Referrals / Community rewards are mathematically designed to come from the winner's share of the pot.
fees_[0] = F3Ddatasets.TeamFee(22,0); //48% to pot, 18% to aff, 10% to com, 1% to pot swap, 1% to air drop pot
fees_[1] = F3Ddatasets.TeamFee(32,0); //38% to pot, 18% to aff, 10% to com, 1% to pot swap, 1% to air drop pot
fees_[2] = F3Ddatasets.TeamFee(52,0); //18% to pot, 18% to aff, 10% to com, 1% to pot swap, 1% to air drop pot
fees_[3] = F3Ddatasets.TeamFee(42,0); //28% to pot, 18% to aff, 10% 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)
potSplit_[0] = F3Ddatasets.PotSplit(42,0); //48% to winner, 0% to next round, 10% to com
potSplit_[1] = F3Ddatasets.PotSplit(34,0); //48% to winner, 8% to next round, 10% to com
potSplit_[2] = F3Ddatasets.PotSplit(18,0); //48% to winner, 24% to next round, 10% to com
potSplit_[3] = F3Ddatasets.PotSplit(26,0); //48% to winner, 16% to next round, 10% 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_);
}
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;
uint256 _withdrawFee;
// 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)
{
//10% trade tax
_withdrawFee = _eth / 10;
uint256 _p1 = _withdrawFee.mul(65) / 100;
uint256 _p2 = _withdrawFee.mul(35) / 100;
shareCom.transfer(_p1);
admin.transfer(_p2);
plyr_[_pID].addr.transfer(_eth.sub(_withdrawFee));
}
// 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)
{
//10% trade tax
_withdrawFee = _eth / 10;
_p1 = _withdrawFee.mul(65) / 100;
_p2 = _withdrawFee.mul(35) / 100;
shareCom.transfer(_p1);
admin.transfer(_p2);
plyr_[_pID].addr.transfer(_eth.sub(_withdrawFee));
}
// 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);
}
//==============================================================================
// _ _ _|__|_ _ _ _ .
// (_|(/_ | | (/_| _\ . (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 ( 100000000000000 ); // 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);
}
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
);
}
//==============================================================================
// _ _ _ _ | _ _ . _ .
// (_(_)| (/_ |(_)(_||(_ . (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_);
// 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 / 10);
uint256 _gen = (_pot.mul(potSplit_[_winTID].gen)) / 100;
uint256 _res = (((_pot.sub(_win)).sub(_com)).sub(_gen));
// 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
shareCom.transfer((_com.mul(65) / 100));
admin.transfer((_com.mul(35) / 100));
// 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_.P3DAmount = 0;
_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;
uint256 _rndInc = rndInc_;
if(round_[_rID].pot > rndLimit_)
{
_rndInc = _rndInc / 2;
}
// 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 community rewards
uint256 _com = _eth / 10;
uint256 _p3d;
if (!address(admin).call.value(_com)())
{
_p3d = _com;
_com = 0;
}
// pay 1% out to FoMo3D short
// uint256 _long = _eth / 100;
// otherF3D_.potSwap.value(_long)();
_p3d = _p3d.add(distributeAff(_rID,_pID,_eth,_affID));
// pay out p3d
// _p3d = _p3d.add((_eth.mul(fees_[_team].p3d)) / (100));
if (_p3d > 0)
{
// deposit to divies contract
uint256 _potAmount = _p3d / 2;
uint256 _amount = _p3d.sub(_potAmount);
shareCom.transfer((_amount.mul(65)/100));
admin.transfer((_amount.mul(35)/100));
round_[_rID].pot = round_[_rID].pot.add(_potAmount);
// set up event data
_eventData_.P3DAmount = _p3d.add(_eventData_.P3DAmount);
}
return(_eventData_);
}
function distributeAff(uint256 _rID, uint256 _pID, uint256 _eth, uint256 _affID)
private
returns(uint256)
{
uint256 _addP3d = 0;
// distribute share to affiliate
uint256 _aff1 = _eth / 10;
uint256 _aff2 = _eth / 20;
uint256 _aff3 = _eth / 34;
// decide what to do with affiliate share of fees
// affiliate must not be self, and must have a name registered
if ((_affID != 0) && (_affID != _pID) && (plyr_[_affID].name != ''))
{
plyr_[_pID].laffID = _affID;
plyr_[_affID].aff = _aff1.add(plyr_[_affID].aff);
emit F3Devents.onAffiliatePayout(_affID, plyr_[_affID].addr, plyr_[_affID].name, _rID, _pID, _aff1, now);
//second level aff
uint256 _secLaff = plyr_[_affID].laffID;
if((_secLaff != 0) && (_secLaff != _pID))
{
plyr_[_secLaff].aff = _aff2.add(plyr_[_secLaff].aff);
emit F3Devents.onAffiliatePayout(_secLaff, plyr_[_secLaff].addr, plyr_[_secLaff].name, _rID, _pID, _aff2, now);
//third level aff
uint256 _thirdAff = plyr_[_secLaff].laffID;
if((_thirdAff != 0 ) && (_thirdAff != _pID))
{
plyr_[_thirdAff].aff = _aff3.add(plyr_[_thirdAff].aff);
emit F3Devents.onAffiliatePayout(_thirdAff, plyr_[_thirdAff].addr, plyr_[_thirdAff].name, _rID, _pID, _aff3, now);
} else {
_addP3d = _addP3d.add(_aff3);
}
} else {
_addP3d = _addP3d.add(_aff2);
}
} else {
_addP3d = _addP3d.add(_aff1);
}
return(_addP3d);
}
function getPlayerAff(uint256 _pID)
public
view
returns (uint256,uint256,uint256)
{
uint256 _affID = plyr_[_pID].laffID;
if (_affID != 0)
{
//second level aff
uint256 _secondLaff = plyr_[_affID].laffID;
if(_secondLaff != 0)
{
//third level aff
uint256 _thirdAff = plyr_[_secondLaff].laffID;
}
}
return (_affID,_secondLaff,_thirdAff);
}
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));
_eth = _eth.sub(_eth.mul(30) / 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)
{
// 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 == admin, "only admin can activate");
// can only be ran once
require(activated_ == false, "FOMO Short 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_;
}
}
//==============================================================================
// __|_ _ __|_ _ .
// _\ | | |_|(_ | _\ .
//==============================================================================
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
uint256 laffID; // last affiliate id unaffected
}
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 F3DKeysCalcShort {
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 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 NameFilter {
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);
}
}
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);
}
}
}