Created
October 23, 2021 03:04
-
-
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=
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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