Skip to content

Instantly share code, notes, and snippets.

@bankrollnetwork
Created October 23, 2021 03:04
Show Gist options
  • Save bankrollnetwork/a5911a2891da4b063a69f4aa5b3621c2 to your computer and use it in GitHub Desktop.
Save bankrollnetwork/a5911a2891da4b063a69f4aa5b3621c2 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.6.12+commit.27d51765.js&optimize=true&runs=200&gist=
/*
SPDX-License-Identifier: MIT
A Bankteller Production
Bankroll Network
Copyright 2021
*/
pragma solidity ^0.6.8;
// File: openzeppelin-solidity/contracts/ownership/Ownable.sol
/**
* @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 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 transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
// pragma solidity >=0.5.0;
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}
// pragma solidity >=0.5.0;
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
// pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
// pragma solidity >=0.6.2;
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
interface Token {
function transferFrom(address from, address to, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function balanceOf(address who) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
}
/*
* @dev Stack is a perpetual rewards contract the collects 8% fee on buys/sells for a dividend pool that drips 2% daily.
* A 2% fee is paid instantly to ELEPHANT token holders on buys/sells as buybacks that are burned
*/
contract BankrollNetworkStack is Ownable {
using SafeMath for uint;
/*=================================
= MODIFIERS =
=================================*/
/// @dev Only people with tokens
modifier onlyBagholders {
require(myTokens() > 0);
_;
}
/// @dev Only people with profits
modifier onlyStronghands {
require(myDividends() > 0);
_;
}
/*==============================
= EVENTS =
==============================*/
event onLeaderBoard(
address indexed customerAddress,
uint256 invested,
uint256 tokens,
uint256 soldTokens,
uint timestamp
);
event onTokenPurchase(
address indexed customerAddress,
uint256 incomingeth,
uint256 tokensMinted,
uint timestamp
);
event onTokenSell(
address indexed customerAddress,
uint256 tokensBurned,
uint256 ethEarned,
uint timestamp
);
event onReinvestment(
address indexed customerAddress,
uint256 ethReinvested,
uint256 tokensMinted,
uint timestamp
);
event onWithdraw(
address indexed customerAddress,
uint256 ethWithdrawn,
uint timestamp
);
event onTransfer(
address indexed from,
address indexed to,
uint256 tokens,
uint timestamp
);
event onBalance(
uint256 balance,
uint256 timestamp
);
event onBuyBack(
uint256 amount,
uint256 timestamp
);
event onDonation(
address indexed from,
uint256 amount,
uint timestamp
);
// Onchain Stats!!!
struct Stats {
uint invested;
uint reinvested;
uint withdrawn;
uint rewarded;
uint contributed;
uint transferredTokens;
uint receivedTokens;
uint xInvested;
uint xReinvested;
uint xRewarded;
uint xContributed;
uint xWithdrawn;
uint xTransferredTokens;
uint xReceivedTokens;
}
/*=====================================
= CONFIGURABLES =
=====================================*/
/// @dev dividends for token purchase
uint8 internal entryFee_ = 10;
/// @dev dividends for token selling
uint8 internal exitFee_ = 10;
uint8 internal payoutRate_ = 2;
uint256 constant internal magnitude = 2 ** 64;
/*=================================
= DATASETS =
================================*/
// amount of shares for each address (scaled number)
mapping(address => uint256) private tokenBalanceLedger_;
mapping(address => int256) private payoutsTo_;
mapping(address => Stats) private stats;
//on chain referral tracking
uint256 private tokenSupply_;
uint256 private profitPerShare_;
uint256 public totalDeposits;
uint256 internal lastBalance_;
uint public players;
uint public totalTxs;
uint public dividendBalance_;
uint public elephantReserve_;
uint public lastPayout;
uint public totalClaims;
uint public totalBuyBack;
uint public firstBlock;
uint public firstTimestamp;
uint256 public balanceInterval = 6 hours;
uint256 public distributionInterval = 2 seconds;
address public tokenAddress;
address public elephantAddress = address(0xE283D0e3B8c102BAdF5E8166B73E02D96d92F688);
address public graveyardAddress = address(0xF7cC784BD260eafC1193D337fFcEA4D6ddA0dd71);
address public router = address(0x10ED43C718714eb63d5aA57B78B54704E256024E);
/*
Pancake v2 Mainnet - 0x10ed43c718714eb63d5aa57b78b54704e256024e
Uniswap v2 Rinkeby Testnet - 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a
*/
IUniswapV2Router02 public uniswapV2Router;
IUniswapV2Router02 public tokenUniswapV2Router;
Token private token;
Token private elephantToken;
Token private wethToken;
bool public buybackEnabled = true;
/*=======================================
= PUBLIC FUNCTIONS =
=======================================*/
constructor(address _tokenAddress, address _tokenRouter, uint8 _fee, uint8 _payout) Ownable() public {
require(_tokenAddress != address(0) && _tokenRouter != address(0), "Token and liquidity router must be set");
require(_fee <= 90 && _payout <= 100, "fee and payout must be properly set, fee <= 90 and payout <= 10");
entryFee_ = _fee;
exitFee_ = _fee;
payoutRate_ = _payout;
tokenAddress = _tokenAddress;
token = Token(_tokenAddress);
elephantToken = Token(elephantAddress);
uniswapV2Router = IUniswapV2Router02(router);
tokenUniswapV2Router = IUniswapV2Router02(_tokenRouter);
//Sanity check router
require(tokenUniswapV2Router.WETH() == uniswapV2Router.WETH(), "Router is not compatible");
wethToken = Token(uniswapV2Router.WETH());
lastPayout = block.timestamp;
firstBlock = block.number;
firstTimestamp = block.timestamp;
}
//Public function
function sweep() public {
if (elephantReserve_ > 0){
totalBuyBack = totalBuyBack.add(buyback(elephantReserve_));
elephantReserve_ = 0;
}
}
//If enabled the elephantReserve is funded
function enableBuyback(bool enable) onlyOwner public {
buybackEnabled = enable;
}
function updateTokenRouter(address _tokenRouter) onlyOwner public {
require(_tokenRouter != address(0), "Router must be set");
tokenUniswapV2Router = IUniswapV2Router02(_tokenRouter);
//Sanity check router
require(tokenUniswapV2Router.WETH() == uniswapV2Router.WETH(), "Router is not compatible");
}
//Execute the buyback against the router using WETH as a bridge
function buyback(uint tokenAmount) private returns (uint) {
address[] memory path;
bool isWETH = tokenAddress == uniswapV2Router.WETH();
if (!isWETH){
path = new address[](2);
path[0] = tokenAddress;
path[1] = uniswapV2Router.WETH();
//Need to be able to approve the collateral token for transfer against where its liquidity may reside in the future
//Pancake and others will maintain interfaces for legacy applications
require(token.approve(address(tokenUniswapV2Router), tokenAmount));
uint initial = wethToken.balanceOf(address(this));
tokenUniswapV2Router.swapExactTokensForTokens(
tokenAmount,
0, // accept any amount of Elephant
path,
address(this), //send it here first so we can find out how much ELEPHANT we receieved
block.timestamp.add(1 minutes)
);
//update the tokenAmount with the difference in WETH
tokenAmount = wethToken.balanceOf(address(this)).sub(initial);
}
//We always have WETH sourced from the best liquidity pool for the core asset if necessary
path = new address[](2);
path[0] = uniswapV2Router.WETH();
path[1] = elephantAddress;
//Need to be able to approve the collateral token for transfer
require(wethToken.approve(address(uniswapV2Router), tokenAmount));
uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
tokenAmount,
0, // accept any amount of Elephant
path,
address(this), //send it here first so we can find out how much ELEPHANT we receieved
block.timestamp.add(1 minutes)
);
//transfer elephant tokens (buyback)
uint _balance = elephantToken.balanceOf(address(this));
elephantToken.transfer(graveyardAddress, _balance);
emit onBuyBack(_balance, block.timestamp);
return _balance;
}
/// @dev This is how you pump pure "drip" dividends into the system
function donatePool(uint amount) public returns (uint256) {
require(token.transferFrom(msg.sender, address(this),amount));
require(tokenSupply_ > 0, "Must have supply to donate");
//If we just have instant divs, no drip
if (entryFee_ == 0){
//Apply divs
profitPerShare_ = SafeMath.add(profitPerShare_, (amount * magnitude) / tokenSupply_);
} else {
dividendBalance_ += amount;
}
emit onDonation(msg.sender, amount,now);
}
/// @dev Converts all incoming eth to tokens for the caller, and passes down the referral addy (if any)
function buy(uint buy_amount) public returns (uint256) {
return buyFor(msg.sender, buy_amount);
}
/// @dev Converts all incoming eth to tokens for the caller, and passes down the referral addy (if any)
function buyFor(address _customerAddress, uint buy_amount) public returns (uint256) {
require(token.transferFrom(msg.sender, address(this), buy_amount));
totalDeposits += buy_amount;
uint amount = purchaseTokens(_customerAddress, buy_amount);
emit onLeaderBoard(_customerAddress,
stats[_customerAddress].invested,
tokenBalanceLedger_[_customerAddress],
stats[_customerAddress].withdrawn,
now
);
//distribute
distribute();
return amount;
}
/**
* @dev Fallback function to return any TRX/ETH accidentally sent to the contract
*/
//to recieve ETH from uniswapV2Router when swaping
receive() external payable {}
/// @dev Converts all of caller's dividends to tokens.
function reinvest() onlyStronghands public {
// fetch dividends
uint256 _dividends = myDividends();
// retrieve ref. bonus later in the code
// pay out the dividends virtually
address _customerAddress = msg.sender;
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude);
// dispatch a buy order with the virtualized "withdrawn dividends"
uint256 _tokens = purchaseTokens(msg.sender, _dividends);
// fire event
emit onReinvestment(_customerAddress, _dividends, _tokens, now);
//Stats
stats[_customerAddress].reinvested = SafeMath.add(stats[_customerAddress].reinvested, _dividends);
stats[_customerAddress].xReinvested += 1;
emit onLeaderBoard(_customerAddress,
stats[_customerAddress].invested,
tokenBalanceLedger_[_customerAddress],
stats[_customerAddress].withdrawn,
now
);
//distribute
distribute();
}
/// @dev Withdraws all of the callers earnings.
function withdraw() onlyStronghands public {
// setup data
address _customerAddress = msg.sender;
uint256 _dividends = myDividends();
// update dividend tracker
payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude);
// lambo delivery service
token.transfer(_customerAddress,_dividends);
//stats
stats[_customerAddress].withdrawn = SafeMath.add(stats[_customerAddress].withdrawn, _dividends);
stats[_customerAddress].xWithdrawn += 1;
totalTxs += 1;
totalClaims += _dividends;
// fire event
emit onWithdraw(_customerAddress, _dividends, now);
emit onLeaderBoard(_customerAddress,
stats[_customerAddress].invested,
tokenBalanceLedger_[_customerAddress],
stats[_customerAddress].withdrawn,
now
);
//distribute
distribute();
}
/// @dev Liquifies tokens to eth.
function sell(uint256 _amountOfTokens) onlyBagholders public {
// setup data
address _customerAddress = msg.sender;
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]);
// data setup
uint256 _undividedDividends = SafeMath.mul(_amountOfTokens, exitFee_) / 100;
uint256 _taxedeth = SafeMath.sub(_amountOfTokens, _undividedDividends);
// burn the sold tokens
tokenSupply_ = SafeMath.sub(tokenSupply_, _amountOfTokens);
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens);
// update dividends tracker
int256 _updatedPayouts = (int256) (profitPerShare_ * _amountOfTokens + (_taxedeth * magnitude));
payoutsTo_[_customerAddress] -= _updatedPayouts;
//drip and buybacks
allocateFees(_undividedDividends);
// fire event
emit onTokenSell(_customerAddress, _amountOfTokens, _taxedeth, now);
//distribute
distribute();
}
/**
* @dev Transfer tokens from the caller to a new holder.
* Zero fees
*/
function transfer(address _toAddress, uint256 _amountOfTokens) onlyBagholders external returns (bool) {
// setup
address _customerAddress = msg.sender;
// make sure we have the requested tokens
require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]);
// withdraw all outstanding dividends first
if (myDividends() > 0) {
withdraw();
}
// exchange tokens
tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _amountOfTokens);
tokenBalanceLedger_[_toAddress] = SafeMath.add(tokenBalanceLedger_[_toAddress], _amountOfTokens);
// update dividend trackers
payoutsTo_[_customerAddress] -= (int256) (profitPerShare_ * _amountOfTokens);
payoutsTo_[_toAddress] += (int256) (profitPerShare_ * _amountOfTokens);
/* Members
A player can be initialized by buying or receiving and we want to add the user ASAP
*/
if (stats[_toAddress].invested == 0 && stats[_toAddress].receivedTokens == 0) {
players += 1;
}
//Stats
stats[_customerAddress].xTransferredTokens += 1;
stats[_customerAddress].transferredTokens += _amountOfTokens;
stats[_toAddress].receivedTokens += _amountOfTokens;
stats[_toAddress].xReceivedTokens += 1;
totalTxs += 1;
// fire event
emit onTransfer(_customerAddress, _toAddress, _amountOfTokens,now);
emit onLeaderBoard(_customerAddress,
stats[_customerAddress].invested,
tokenBalanceLedger_[_customerAddress],
stats[_customerAddress].withdrawn,
now
);
emit onLeaderBoard(_toAddress,
stats[_toAddress].invested,
tokenBalanceLedger_[_toAddress],
stats[_toAddress].withdrawn,
now
);
// ERC20
return true;
}
/*=====================================
= HELPERS AND CALCULATORS =
=====================================*/
/**
* @dev Method to view the current eth stored in the contract
*/
function totalTokenBalance() public view returns (uint256) {
return token.balanceOf(address(this));
}
/// @dev Retrieve the total token supply.
function totalSupply() public view returns (uint256) {
return tokenSupply_;
}
/// @dev Retrieve the tokens owned by the caller.
function myTokens() public view returns (uint256) {
address _customerAddress = msg.sender;
return balanceOf(_customerAddress);
}
/**
* @dev Retrieve the dividends owned by the caller.
*/
function myDividends() public view returns (uint256) {
address _customerAddress = msg.sender;
return dividendsOf(_customerAddress);
}
/// @dev Retrieve the token balance of any single address.
function balanceOf(address _customerAddress) public view returns (uint256) {
return tokenBalanceLedger_[_customerAddress];
}
/// @dev Retrieve the token balance of any single address.
function tokenBalance(address _customerAddress) public view returns (uint256) {
return _customerAddress.balance;
}
/// @dev Retrieve the dividend balance of any single address.
function dividendsOf(address _customerAddress) public view returns (uint256) {
return (uint256) ((int256) (profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude;
}
/// @dev Return the sell price of 1 individual token.
function sellPrice() public view returns (uint256) {
uint256 _eth = 1e18;
uint256 _dividends = SafeMath.div(SafeMath.mul(_eth, exitFee_), 100);
uint256 _taxedeth = SafeMath.sub(_eth, _dividends);
return _taxedeth;
}
/// @dev Return the buy price of 1 individual token.
function buyPrice() public view returns (uint256) {
uint256 _eth = 1e18;
uint256 _dividends = SafeMath.div(SafeMath.mul(_eth, entryFee_), 100);
uint256 _taxedeth = SafeMath.add(_eth, _dividends);
return _taxedeth;
}
/// @dev Function for the frontend to dynamically retrieve the price scaling of buy orders.
function calculateTokensReceived(uint256 _ethToSpend) public view returns (uint256) {
uint256 _dividends = SafeMath.div(SafeMath.mul(_ethToSpend, entryFee_), 100);
uint256 _taxedeth = SafeMath.sub(_ethToSpend, _dividends);
uint256 _amountOfTokens = _taxedeth;
return _amountOfTokens;
}
/// @dev Function for the frontend to dynamically retrieve the price scaling of sell orders.
function calculateethReceived(uint256 _tokensToSell) public view returns (uint256) {
require(_tokensToSell <= tokenSupply_);
uint256 _eth = _tokensToSell;
uint256 _dividends = SafeMath.div(SafeMath.mul(_eth, exitFee_), 100);
uint256 _taxedeth = SafeMath.sub(_eth, _dividends);
return _taxedeth;
}
/// @dev Stats of any single address
function statsOf(address _customerAddress) public view returns (uint256[14] memory){
Stats memory s = stats[_customerAddress];
uint256[14] memory statArray = [s.invested, s.withdrawn, s.rewarded, s.contributed, s.transferredTokens, s.receivedTokens, s.xInvested, s.xRewarded, s.xContributed, s.xWithdrawn, s.xTransferredTokens, s.xReceivedTokens, s.reinvested, s.xReinvested];
return statArray;
}
function dailyEstimate(address _customerAddress) public view returns (uint256){
uint256 share = dividendBalance_.mul(payoutRate_).div(100);
return (tokenSupply_ > 0) ? share.mul(tokenBalanceLedger_[_customerAddress]).div(tokenSupply_) : 0;
}
function allocateFees(uint fee) private {
//If no fees lets save time
if (fee == 0){
return;
}
// 1/5 paid out instantly to Elephant holders
uint256 instant = fee.div(5);
//If buy backs are enabled split the fee
if (buybackEnabled) {
//add the instant fee to the reserve
elephantReserve_ = elephantReserve_.add(instant);
dividendBalance_ = dividendBalance_.add(fee).sub(instant);
} else {
//add the entire fee to the dividend balance
//this only happens when there is an issue with the buy back process.
//If Pancake upgrades liquidity pools
dividendBalance_ = dividendBalance_.add(fee);
}
}
function distribute() private {
if (now.safeSub(lastBalance_) > balanceInterval) {
emit onBalance(totalTokenBalance(), now);
lastBalance_ = now;
}
if (dividendBalance_ > 0 && SafeMath.safeSub(now, lastPayout) > distributionInterval && tokenSupply_ > 0) {
//A portion of the dividend is paid out according to the rate
uint256 share = dividendBalance_.mul(payoutRate_).div(100).div(24 hours);
//divide the profit by seconds in the day
uint256 profit = share * now.safeSub(lastPayout);
//share times the amount of time elapsed
dividendBalance_ = dividendBalance_.safeSub(profit);
//Apply divs
profitPerShare_ = SafeMath.add(profitPerShare_, (profit * magnitude) / tokenSupply_);
lastPayout = now;
}
}
/*==========================================
= INTERNAL FUNCTIONS =
==========================================*/
/// @dev Internal function to actually purchase the tokens.
function purchaseTokens(address _customerAddress, uint256 _incomingeth) internal returns (uint256) {
/* Members */
if (stats[_customerAddress].invested == 0 && stats[_customerAddress].receivedTokens == 0) {
players += 1;
}
totalTxs += 1;
// data setup
uint256 _undividedDividends = SafeMath.mul(_incomingeth, entryFee_) / 100;
uint256 _amountOfTokens = SafeMath.sub(_incomingeth, _undividedDividends);
// fire event
emit onTokenPurchase(_customerAddress, _incomingeth, _amountOfTokens, now);
// yes we know that the safemath function automatically rules out the "greater then" equation.
require(_amountOfTokens > 0 && SafeMath.add(_amountOfTokens, tokenSupply_) > tokenSupply_);
// we can't give people infinite eth
if (tokenSupply_ > 0) {
// add tokens to the pool
tokenSupply_ += _amountOfTokens;
} else {
// add tokens to the pool
tokenSupply_ = _amountOfTokens;
}
//drip and buybacks
allocateFees(_undividedDividends);
// update circulating supply & the ledger address for the customer
tokenBalanceLedger_[_customerAddress] = SafeMath.add(tokenBalanceLedger_[_customerAddress], _amountOfTokens);
// Tells the contract that the buyer doesn't deserve dividends for the tokens before they owned them;
// really i know you think you do but you don't
int256 _updatedPayouts = (int256) (profitPerShare_ * _amountOfTokens);
payoutsTo_[_customerAddress] += _updatedPayouts;
//Stats
stats[_customerAddress].invested += _incomingeth;
stats[_customerAddress].xInvested += 1;
return _amountOfTokens;
}
}
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
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;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
// uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return a / b;
}
/**
* @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) {
assert(b <= a);
return a - b;
}
/* @dev Subtracts two numbers, else returns zero */
function safeSub(uint a, uint b) internal pure returns (uint) {
if (b > a) {
return 0;
} else {
return a - b;
}
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment