pragma solidity ^0.4.25; /* * https://smartwager.(something) * * Smart Wager Token concept * * [✓] 8% Withdraw fee * [✓] 15% Deposit fee * [✓] 0% Token transfer * [✓] Multi-level Refferal System - 10% from total purchase * * [✓] 1st level 50% Refferal (5% from total purchase) * * [✓] 2nd level 30% Refferal (3% from total purchase) * * [✓] 3rd level 20% Refferal (2% from total purchase) */ contract SmartWagerToken { /*================================= = MODIFIERS = =================================*/ modifier onlyBagholders { require(myTokens() > 0); _; } modifier onlyStronghands { require(myDividends(true) > 0); _; } /*============================== = EVENTS = ==============================*/ event onTokenPurchase( address indexed customerAddress, uint256 incomingEthereum, uint256 tokensMinted, address indexed referredBy, uint timestamp, uint256 price ); event onTokenSell( address indexed customerAddress, uint256 tokensBurned, uint256 ethereumEarned, uint timestamp, uint256 price ); event onReinvestment( address indexed customerAddress, uint256 ethereumReinvested, uint256 tokensMinted ); event onWithdraw( address indexed customerAddress, uint256 ethereumWithdrawn ); event Transfer( address indexed from, address indexed to, uint256 tokens ); event onRefferalUse( address indexed refferer, uint8 indexed level, uint256 ethereumCollected, address indexed customerAddress ); string public name = "Smart Wager Token"; string public symbol = "CMT"; uint8 constant public decimals = 18; uint8 constant internal entryFee_ = 15; uint8 constant internal exitFee_ = 8; uint8 constant internal maxRefferalFee_ = 10; // 10% from total sum (lev1 - 5%, lev2 - 3%, lev3 - 2%) uint256 constant internal tokenPriceInitial_ = 0.0000001 ether; uint256 constant internal tokenPriceIncremental_ = 0.00000001 ether; uint256 constant internal magnitude = 2 ** 64; uint256 public stakingRequirement = 50e18; mapping(address => uint256) internal tokenBalanceLedger_; mapping(address => uint256) internal referralBalance_; mapping(address => int256) internal payoutsTo_; uint256 internal tokenSupply_; uint256 internal profitPerShare_; mapping(address => address) public stickyRef; function buy(address _referredBy) public payable { purchaseInternal(msg.value, _referredBy); } function() payable public { purchaseInternal(msg.value, 0x0); } function reinvest() onlyStronghands public { uint256 _dividends = myDividends(false); address _customerAddress = msg.sender; payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); _dividends += referralBalance_[_customerAddress]; referralBalance_[_customerAddress] = 0; uint256 _tokens = purchaseTokens(_dividends, 0x0); emit onReinvestment(_customerAddress, _dividends, _tokens); } function exit() public { address _customerAddress = msg.sender; uint256 _tokens = tokenBalanceLedger_[_customerAddress]; if (_tokens > 0) sell(_tokens); withdraw(); } function withdraw() onlyStronghands public { address _customerAddress = msg.sender; uint256 _dividends = myDividends(false); payoutsTo_[_customerAddress] += (int256) (_dividends * magnitude); _dividends += referralBalance_[_customerAddress]; referralBalance_[_customerAddress] = 0; _customerAddress.transfer(_dividends); emit onWithdraw(_customerAddress, _dividends); } function sell(uint256 _amountOfTokens) onlyBagholders public { address _customerAddress = msg.sender; require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); uint256 _tokens = _amountOfTokens; uint256 _ethereum = tokensToEthereum_(_tokens); uint256 _dividends = SafeMath.div(SafeMath.mul(_ethereum, exitFee_), 100); uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); tokenSupply_ = SafeMath.sub(tokenSupply_, _tokens); tokenBalanceLedger_[_customerAddress] = SafeMath.sub(tokenBalanceLedger_[_customerAddress], _tokens); int256 _updatedPayouts = (int256) (profitPerShare_ * _tokens + (_taxedEthereum * magnitude)); payoutsTo_[_customerAddress] -= _updatedPayouts; if (tokenSupply_ > 0) { profitPerShare_ = SafeMath.add(profitPerShare_, (_dividends * magnitude) / tokenSupply_); } emit onTokenSell(_customerAddress, _tokens, _taxedEthereum, now, buyPrice()); } function transfer(address _toAddress, uint256 _amountOfTokens) onlyBagholders public returns (bool) { // setup address _customerAddress = msg.sender; // make sure we have the requested tokens // also disables transfers until ambassador phase is over // ( we dont want whale premines ) require(_amountOfTokens <= tokenBalanceLedger_[_customerAddress]); // withdraw all outstanding dividends first if(myDividends(true) > 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); // fire event emit Transfer(_customerAddress, _toAddress, _amountOfTokens); return true; } function totalEthereumBalance() public view returns (uint256) { return address(this).balance; } function totalSupply() public view returns (uint256) { return tokenSupply_; } function myTokens() public view returns (uint256) { address _customerAddress = msg.sender; return balanceOf(_customerAddress); } function myDividends(bool _includeReferralBonus) public view returns (uint256) { address _customerAddress = msg.sender; return _includeReferralBonus ? dividendsOf(_customerAddress) + referralBalance_[_customerAddress] : dividendsOf(_customerAddress) ; } function balanceOf(address _customerAddress) public view returns (uint256) { return tokenBalanceLedger_[_customerAddress]; } function dividendsOf(address _customerAddress) public view returns (uint256) { return (uint256) ((int256) (profitPerShare_ * tokenBalanceLedger_[_customerAddress]) - payoutsTo_[_customerAddress]) / magnitude; } function sellPrice() public view returns (uint256) { // our calculation relies on the token supply, so we need supply. Doh. if (tokenSupply_ == 0) { return tokenPriceInitial_ - tokenPriceIncremental_; } else { uint256 _ethereum = tokensToEthereum_(1e18); uint256 _dividends = SafeMath.div(SafeMath.mul(_ethereum, exitFee_), 100); uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); return _taxedEthereum; } } function buyPrice() public view returns (uint256) { if (tokenSupply_ == 0) { return tokenPriceInitial_ + tokenPriceIncremental_; } else { uint256 _ethereum = tokensToEthereum_(1e18); uint256 _dividends = SafeMath.div(SafeMath.mul(_ethereum, entryFee_), 100); uint256 _taxedEthereum = SafeMath.add(_ethereum, _dividends); return _taxedEthereum; } } function calculateTokensReceived(uint256 _ethereumToSpend) public view returns (uint256) { uint256 _dividends = SafeMath.div(SafeMath.mul(_ethereumToSpend, entryFee_), 100); uint256 _taxedEthereum = SafeMath.sub(_ethereumToSpend, _dividends); uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); return _amountOfTokens; } function calculateEthereumReceived(uint256 _tokensToSell) public view returns (uint256) { require(_tokensToSell <= tokenSupply_); uint256 _ethereum = tokensToEthereum_(_tokensToSell); uint256 _dividends = SafeMath.div(SafeMath.mul(_ethereum, exitFee_), 100); uint256 _taxedEthereum = SafeMath.sub(_ethereum, _dividends); return _taxedEthereum; } /*========================================== = INTERNAL FUNCTIONS = ==========================================*/ // Make sure we will send back excess if user sends more then 2.5 ether before 100 ETH in contract function purchaseInternal(uint256 _incomingEthereum, address _referredBy) internal returns(uint256) { uint256 purchaseEthereum = _incomingEthereum; uint256 excess; if(purchaseEthereum > 2.5 ether) { // check if the transaction is over 2.5 ether if (SafeMath.sub(address(this).balance, purchaseEthereum) <= 100 ether) { // if so check the contract is less then 100 ether purchaseEthereum = 2.5 ether; excess = SafeMath.sub(_incomingEthereum, purchaseEthereum); } } purchaseTokens(purchaseEthereum, _referredBy); if (excess > 0) { msg.sender.transfer(excess); } } function handleRefferals(address _referredBy, uint _referralBonus, uint _undividedDividends) internal returns (uint){ uint _dividends = _undividedDividends; address _level1Referrer = stickyRef[msg.sender]; if (_level1Referrer == address(0x0)){ _level1Referrer = _referredBy; } // is the user referred by a masternode? if( // is this a referred purchase? _level1Referrer != 0x0000000000000000000000000000000000000000 && // no cheating! _level1Referrer != msg.sender && // does the referrer have at least X whole tokens? // i.e is the referrer a godly chad masternode tokenBalanceLedger_[_level1Referrer] >= stakingRequirement ){ // wealth redistribution if (stickyRef[msg.sender] == address(0x0)){ stickyRef[msg.sender] = _level1Referrer; } // level 1 refs - 50% uint256 ethereumCollected = _referralBonus/2; referralBalance_[_level1Referrer] = SafeMath.add(referralBalance_[_level1Referrer], ethereumCollected); _dividends = SafeMath.sub(_dividends, ethereumCollected); emit onRefferalUse(_level1Referrer, 1, ethereumCollected, msg.sender); address _level2Referrer = stickyRef[_level1Referrer]; if (_level2Referrer != address(0x0) && tokenBalanceLedger_[_level2Referrer] >= stakingRequirement){ // level 2 refs - 30% ethereumCollected = (_referralBonus*3)/10; referralBalance_[_level2Referrer] = SafeMath.add(referralBalance_[_level2Referrer], ethereumCollected); _dividends = SafeMath.sub(_dividends, ethereumCollected); emit onRefferalUse(_level2Referrer, 2, ethereumCollected, _level1Referrer); address _level3Referrer = stickyRef[_level2Referrer]; if (_level3Referrer != address(0x0) && tokenBalanceLedger_[_level3Referrer] >= stakingRequirement){ //level 3 refs - 20% ethereumCollected = (_referralBonus*2)/10; referralBalance_[_level3Referrer] = SafeMath.add(referralBalance_[_level3Referrer], ethereumCollected); _dividends = SafeMath.sub(_dividends, ethereumCollected); emit onRefferalUse(_level3Referrer, 2, ethereumCollected, _level2Referrer); } } } return _dividends; } function purchaseTokens(uint256 _incomingEthereum, address _referredBy) internal returns (uint256) { address _customerAddress = msg.sender; uint256 _undividedDividends = SafeMath.div(SafeMath.mul(_incomingEthereum, entryFee_), 100); uint256 _referralBonus = SafeMath.div(SafeMath.mul(_incomingEthereum, maxRefferalFee_), 100); uint256 _dividends = handleRefferals(_referredBy, _referralBonus, _undividedDividends); uint256 _taxedEthereum = SafeMath.sub(_incomingEthereum, _undividedDividends); uint256 _amountOfTokens = ethereumToTokens_(_taxedEthereum); uint256 _fee = _dividends * magnitude; require(_amountOfTokens > 0 && SafeMath.add(_amountOfTokens, tokenSupply_) > tokenSupply_); if (tokenSupply_ > 0) { tokenSupply_ = SafeMath.add(tokenSupply_, _amountOfTokens); profitPerShare_ += (_dividends * magnitude / tokenSupply_); _fee = _fee - (_fee - (_amountOfTokens * (_dividends * magnitude / tokenSupply_))); } else { tokenSupply_ = _amountOfTokens; } tokenBalanceLedger_[_customerAddress] = SafeMath.add(tokenBalanceLedger_[_customerAddress], _amountOfTokens); int256 _updatedPayouts = (int256) (profitPerShare_ * _amountOfTokens - _fee); payoutsTo_[_customerAddress] += _updatedPayouts; emit onTokenPurchase(_customerAddress, _incomingEthereum, _amountOfTokens, _referredBy, now, buyPrice()); return _amountOfTokens; } function ethereumToTokens_(uint256 _ethereum) internal view returns (uint256) { uint256 _tokenPriceInitial = tokenPriceInitial_ * 1e18; uint256 _tokensReceived = ( ( SafeMath.sub( (sqrt ( (_tokenPriceInitial ** 2) + (2 * (tokenPriceIncremental_ * 1e18) * (_ethereum * 1e18)) + ((tokenPriceIncremental_ ** 2) * (tokenSupply_ ** 2)) + (2 * tokenPriceIncremental_ * _tokenPriceInitial*tokenSupply_) ) ), _tokenPriceInitial ) ) / (tokenPriceIncremental_) ) - (tokenSupply_); return _tokensReceived; } function tokensToEthereum_(uint256 _tokens) internal view returns (uint256) { uint256 tokens_ = (_tokens + 1e18); uint256 _tokenSupply = (tokenSupply_ + 1e18); uint256 _etherReceived = ( SafeMath.sub( ( ( ( tokenPriceInitial_ + (tokenPriceIncremental_ * (_tokenSupply / 1e18)) ) - tokenPriceIncremental_ ) * (tokens_ - 1e18) ), (tokenPriceIncremental_ * ((tokens_ ** 2 - tokens_) / 1e18)) / 2 ) / 1e18); return _etherReceived; } function sqrt(uint256 x) internal pure returns (uint256 y) { uint256 z = (x + 1) / 2; y = x; while (z < y) { y = z; z = (x / z + z) / 2; } } } library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; assert(c / a == b); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a / b; return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } }
0.4.25