EtherTreasury - Smart Contract Audit Report

Summary

logo EtherTreasury is a platform that promises to provide in-kind returns to users in exchange for staking their assets; and provides additonal rewards for referring other users to make deposits. EtherTreasury achieves this through a pyramid scheme, where the profits of early investors are created by taking from the deposits of new users. There is a 10% fee charged on deposit and withdrawl; and those proceeds are used to add to the balance of present investors. As with any pyramid/Ponzi scheme, this is not sustainable, and users who invest later in the course of the project will not recover their initial investment; while the users who invest first/longest will gain other users' assets.

In this Ponzi scheme, the project pays its initial investors interest using money raised from new investors. Eventually, the project will no longer be able to find enough new investors to pay the users who have already deposited, and the scheme collapses leading to loss of funds.

We audited EtherTreasury's main contract, not yet deployed.

Audit Findings:
  • This is a Ponzi/pyramid scheme. Investing later in the lifecycle of the project likely will result in loss of funds.
  • The owner can swap token contracts and users' balances of those tokens at any time. The project team claims this is in case project teams upgrade their token contracts, but that rarely occurs and this function allows for serious malicious action. In theory, if a user deposits 100 USDT, their balance could be maliciously changed to 100 ANYTOKEN and the owner can steal their tokens.
  • Re-Entrancy is possible on the sell() function. We reccomend the implementation of ReentrancyGuard to prevent any attacks.
  • Date: December 22nd, 2020.

  • The project team has implemented ReentrancyGuard based on our reccomendations.

Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether/Token ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
OracleN/APASS
Re-EntrancyMultiple functions call to arbitray user-supplied external contracts. To prevent
unwanted code execution, ReentracyGuard or usage of a whitelist is advised.
FAIL
SuicideN/APASS
State Change External CallsN/APASS
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety ----->FAIL

Inheritence Chart

TronWin888 Smart Contract Inheritance

Function Graph

TronWin888 Smart Contract Graph

Functions Overview



 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public

  +  Ownable 
    - [Int]  #
    - [Pub] owner
    - [Pub] renounceOwnership #
       - modifiers: onlyOwner
    - [Pub] transferOwnership #
       - modifiers: onlyOwner

 +  ReentrancyGuard 
    - [Int]  #

 +  EtherTreasury (Ownable, ReentrancyGuard)
    - [Pub] buy ($)
       - modifiers: nonReentrant
    - [Pub] buy #
       - modifiers: nonReentrant
    - [Ext]  ($)
       - modifiers: nonReentrant
    - [Pub] reinvest #
       - modifiers: nonReentrant
    - [Pub] sellAndwithdraw #
       - modifiers: nonReentrant
    - [Pub] withdraw #
       - modifiers: nonReentrant
    - [Pub] sell #
       - modifiers: nonReentrant
    - [Pub] buyPrice
    - [Pub] sellPrice
    - [Int] tokentoCollateral_
    - [Int] collateralToToken_
    - [Pub] calculateCollateReceived
    - [Pub] calculateTokenReceived
    - [Int] purchaseCollate #
    - [Pub] totalTokenBalance
    - [Pub] totalSupply
    - [Pub] myTokens
    - [Pub] myDividends
    - [Pub] balanceOf
    - [Pub] dividendsOf
    - [Pub] tokenList
    - [Pub] walletList
    - [Pub] assignUpgradedTokens #
       - modifiers: onlyOwner
    - [Pub] startContract #
       - modifiers: onlyOwner
    - [Int] sqrt

 + [Int] ERC20 
    - [Ext] totalSupply
    - [Ext] allowance
    - [Ext] approve #
    - [Ext] balanceOf
    - [Ext] transfer #
    - [Ext] transferFrom #

 + [Lib] SafeMath 
    - [Int] mul
    - [Int] div
    - [Int] sub
    - [Int] add

 + [Lib] SignedSafeMath 
    - [Int] mul
    - [Int] div
    - [Int] sub
    - [Int] add
  

							

Source Code

Click here to download the source code as a .sol file.


// SPDX-License-Identifier: MIT
/**

 * 

 *  Program Name: EtherTreasury

 *  Website     : https://www.ethertreasury.com/

 *  Concept     : Ethereum & ERC-20 Tokens Dividend Paying DApp

 *  Category    : Passive Income

 *  Telegram    : https://t.me/EtherTreasury

 * 

 * */
pragma solidity >=0.6.0 <0.8.0;
abstract contract Ownable {

    address private _owner;
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);     /**

     * @dev Initializes the contract setting the deployer as the initial owner.

     */

    constructor () internal {

        _owner = msg.sender;

        emit OwnershipTransferred(address(0), _owner);

    }
    /**

     * @dev Returns the address of the current owner.

     */

    function owner() public view returns (address) {

        return _owner;

    }
    /**

     * @dev Throws if called by any account other than the owner.

     */

    modifier onlyOwner() {

        require(_owner == msg.sender, "Ownable: caller is not the owner");

        _;

    }

    

    /**

     * @dev Leaves the contract without owner. It will not be possible to call

     * `onlyOwner` functions anymore. Can only be called by the current owner.

     *

     * NOTE: Renouncing ownership will leave the contract without an owner,

     * thereby removing any functionality that is only available to the owner.

     */

    function renounceOwnership() public virtual onlyOwner {

        emit OwnershipTransferred(_owner, address(0));

        _owner = address(0);

    }
    /**

     * @dev Transfers ownership of the contract to a new account (`newOwner`).

     * Can only be called by the current owner.

     */

    function transferOwnership(address newOwner) public virtual onlyOwner {

        require(newOwner != address(0), "Ownable: new owner is the zero address");

        emit OwnershipTransferred(_owner, newOwner);

        _owner = newOwner;

    }

}
abstract contract ReentrancyGuard {

    // Booleans are more expensive than uint256 or any type that takes up a full

    // word because each write operation emits an extra SLOAD to first read the

    // slot's contents, replace the bits taken up by the boolean, and then write

    // back. This is the compiler's defense against contract upgrades and

    // pointer aliasing, and it cannot be disabled.
    // The values being non-zero value makes deployment a bit more expensive,

    // but in exchange the refund on every call to nonReentrant will be lower in

    // amount. Since refunds are capped to a percentage of the total

    // transaction's gas, it is best to keep them low in cases like this one, to

    // increase the likelihood of the full refund coming into effect.

    uint256 private constant _NOT_ENTERED = 1;

    uint256 private constant _ENTERED = 2;
    uint256 private _status;
    constructor () internal {

        _status = _NOT_ENTERED;

    }
    /**

     * @dev Prevents a contract from calling itself, directly or indirectly.

     * Calling a `nonReentrant` function from another `nonReentrant`

     * function is not supported. It is possible to prevent this from happening

     * by making the `nonReentrant` function external, and make it call a

     * `private` function that does the actual work.

     */

    modifier nonReentrant() {

        // On the first call to nonReentrant, _notEntered will be true

        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
        // Any calls to nonReentrant after this point will fail

        _status = _ENTERED;
        _;
        // By storing the original value once again, a refund is triggered (see

        // https://eips.ethereum.org/EIPS/eip-2200)

        _status = _NOT_ENTERED;

    }

}
contract EtherTreasury is Ownable, ReentrancyGuard {

    

    /**

     * @dev Structure to hold tokens supplu and dividend per share against collateral.

     */

    struct TokenMaster {

        uint supply;

        uint dividend;

    }

    

    /**

     * @dev Structure to hold collateral balalnce of wallet.

     */

    struct BalanceLedger {

        uint tokenBalance;

        uint referralBalance;

        int payOut;

    }

    

    /**

     * @dev mapping to store all active contract addresses and wallet addresses. This will be used to check if contract address and wallet address already part of system.

     */

    mapping(address => bool) contractAddressList;

    mapping(address => bool) walletAddressList;

    

    /**

     * @dev array to store active contract address and wallet addresses.

     */

    address[] contractAddressSet;

    address[] walletAddressSet;

    

    uint constant magnitude = 1e18 ;

    uint constant initialPrice = 100000000000;

    uint constant incrementPrice = 10000000000;

    uint constant dividendFee = 10;

    

    /**

     * @dev owner will start program on given time for investment.

     */

    bool startDeposit = false;

    

    /**

     * @dev structure mapping created for storing balance and token information.

     */

    mapping (address => mapping(address => BalanceLedger)) balanceDetails;

    mapping(address => TokenMaster) tokenDetails;

    

    /**

     * @dev events to register information about collateral buy, sell, reinvest and token withdraw.

     */

    event onPurchase(address walletAddress, address contractAddress, uint incomingTokenAmount, uint collateralMinted, address referredBy);

    event onSell(address walletAddress, address contractAddress, uint tokenAmountToReceiver, uint collateralBurned);

    event onReinvest(address walletAddress, address contractAddress, uint reInvestTokenAmount, uint collateralMinted);

    event onWithdraw(address walletAddress, address contractAddress, uint amountToWithdraw);

    

    /**

     * @dev function to purchase collateral by sending Ethereum.

     */

    function buy(address _referredBy) public nonReentrant payable returns(uint256)

    {

        require(startDeposit);

        require(msg.value>0);

        

        // if this is first deposit transaction for token then activate token struct storage with default initial parameters.

        if(contractAddressList[address(0)] == false){

            contractAddressList[address(0)] = true ;

            

            tokenDetails[address(0)].supply = 0;

            tokenDetails[address(0)].dividend = 0;

            

            contractAddressSet.push(address(0));

        }

        

        // if first investment from user then activate wallet address in system.

        if(walletAddressList[msg.sender] == false){

            walletAddressList[msg.sender] = true;

            walletAddressSet.push(msg.sender);

        }

        

        uint256 collateAmount = purchaseCollate(address(0), msg.value, _referredBy);

        return collateAmount;

    }

    

    /**

     * @dev function to purchase collateral by sending any ERC-20 Tokens except Ethereum.

     */

    function buy(address contractAddress, uint256 tokenAmount, address _referredBy) nonReentrant public returns(uint256)

    {

        require(startDeposit);

        

        // transfer token to system from user wallet

        require(ERC20(contractAddress).allowance(msg.sender, address(this)) >= tokenAmount);

        require(ERC20(contractAddress).transferFrom(msg.sender, address(this), tokenAmount));

        

        // if this is first deposit transaction for token then activate token struct storage with default initial parameters.

        if(contractAddressList[contractAddress]==false){

            contractAddressList[contractAddress]=true ;

            

            tokenDetails[contractAddress].supply = 0;

            tokenDetails[contractAddress].dividend = 0;

            

            contractAddressSet.push(contractAddress);

        }

        

        // if first investment from user then activate wallet address in system.

        if(walletAddressList[msg.sender] == false){

            walletAddressList[msg.sender] = true;

            walletAddressSet.push(msg.sender);

        }

        

        uint256 collateAmount = purchaseCollate(contractAddress,tokenAmount, _referredBy);

        return collateAmount;

    }

    

    /**

     * @dev function to purchase collateral by sending Ethereum directly to smart contract address.

     */

    fallback() payable external nonReentrant

    {

        require(startDeposit);

        require(msg.value > 0);

        // if this is first deposit transaction for token then activate token struct storage with default initial parameters.

        if(contractAddressList[address(0)] == false){

            contractAddressList[address(0)] = true ;

            

            tokenDetails[address(0)].supply = 0;

            tokenDetails[address(0)].dividend = 0;

            

            contractAddressSet.push(address(0));

        }

        

        // if first investment from user then activate wallet address in system.

        if(walletAddressList[msg.sender] == false){

            walletAddressList[msg.sender] = true;

            walletAddressSet.push(msg.sender);

        }

        purchaseCollate(address(0), msg.value, address(0));

    }

    

    /**

     * @dev function to convert all dividend to collateral.

     */

    function reinvest(address contractAddress) public nonReentrant

    {

        // fetch dividends

        uint256 _dividends = myDividends(contractAddress, false); // retrieve ref. bonus later in the code

        

        // pay out the dividends virtually

        address _customerAddress = msg.sender;

        balanceDetails[_customerAddress][contractAddress].payOut =  SignedSafeMath.add(balanceDetails[_customerAddress][contractAddress].payOut, (int256) (SafeMath.mul(_dividends, magnitude)));

        

        // retrieve ref. bonus

        _dividends = SafeMath.add(_dividends, balanceDetails[_customerAddress][contractAddress].referralBalance);

        

        balanceDetails[_customerAddress][contractAddress].referralBalance = 0;

        

        // dispatch a buy order with the virtualized "withdrawn dividends"

        uint256 _collate = purchaseCollate(contractAddress, _dividends, address(0));

        

        // fire event

        emit onReinvest(_customerAddress, contractAddress, _dividends, _collate);

    }

    

    /**

     * @dev function to sell collateral and withdraw tokens.

     */

    function sellAndwithdraw(address contractAddress) public nonReentrant

    {

        // get token count for caller & sell them all

        address _customerAddress = msg.sender;

        uint256 _tokens = balanceDetails[_customerAddress][contractAddress].tokenBalance;

        if(_tokens > 0) sell(contractAddress, _tokens);

    

        withdraw(contractAddress);

    }
    /**

     * @dev function to withdraw tokens, dividend and referralBalance.

     */

    function withdraw(address contractAddress) public nonReentrant

    {

        // setup data

        address _customerAddress = msg.sender;

        uint256 _dividends = myDividends(contractAddress, false); // get ref. bonus later in the code

        

        // update dividend tracker

        balanceDetails[_customerAddress][contractAddress].payOut = SignedSafeMath.add(balanceDetails[_customerAddress][contractAddress].payOut,  SignedSafeMath.mul((int256)(_dividends), (int256)(magnitude)));

        

        // add ref. bonus

        _dividends = SafeMath.add(_dividends, balanceDetails[_customerAddress][contractAddress].referralBalance) ;

        balanceDetails[_customerAddress][contractAddress].referralBalance = 0;

        

        // delivery service

        if (contractAddress == address(0)){

            payable(address(_customerAddress)).transfer(_dividends);

        }

        else{

            ERC20(contractAddress).transfer(_customerAddress,_dividends);

        }

        

        

        // fire event

        emit onWithdraw(_customerAddress, contractAddress, _dividends);

    }

    

    /**

     * @dev function to sell collatral.

     */

    function sell(address contractAddress, uint256 _amountOfCollate) public nonReentrant

    {

      

        address _customerAddress = msg.sender;

       

        require(_amountOfCollate <= balanceDetails[_customerAddress][contractAddress].tokenBalance);

        

        uint256 _collates = _amountOfCollate;

        uint256 _tokens = collateralToToken_(contractAddress, _collates);

        uint256 _dividends = SafeMath.div(_tokens, dividendFee);

        uint256 _taxedToken = SafeMath.sub(_tokens, _dividends);

        

        // burn the sold tokens

        tokenDetails[contractAddress].supply = SafeMath.sub(tokenDetails[contractAddress].supply, _collates);

        balanceDetails[_customerAddress][contractAddress].tokenBalance = SafeMath.sub(balanceDetails[_customerAddress][contractAddress].tokenBalance, _collates);

        

        // update dividends tracker

        int256 _updatedPayouts = (int256) (SafeMath.add(SafeMath.mul(tokenDetails[contractAddress].dividend, _collates), (SafeMath.mul(_taxedToken, magnitude))));

        balanceDetails[_customerAddress][contractAddress].payOut = SignedSafeMath.sub(balanceDetails[_customerAddress][contractAddress].payOut,_updatedPayouts);       

        

        // dividing by zero is a bad idea

        if (tokenDetails[contractAddress].supply > 0) {

            // update the amount of dividends per token

            tokenDetails[contractAddress].dividend = SafeMath.add(tokenDetails[contractAddress].dividend, SafeMath.div((SafeMath.mul(_dividends, magnitude)), tokenDetails[contractAddress].supply));

        }

        

        // fire event

        emit onSell(_customerAddress, contractAddress, _taxedToken, _collates);

    }

        

    /**

     * @dev function to get current purchase price of single collateral.

     */

    function buyPrice(address contractAddress) public view returns(uint currentBuyPrice) {

        if(tokenDetails[contractAddress].supply == 0){

            return SafeMath.add(initialPrice, incrementPrice);

        } else {

            uint256 _token = collateralToToken_(contractAddress, 1e18);

            uint256 _dividends = SafeMath.div(_token, dividendFee);

            uint256 _taxedToken = SafeMath.add(_token, _dividends);

            return _taxedToken;

        }

    }

    

    /**

     * @dev function to get current sell price of single collateral.

     */

    function sellPrice(address contractAddress) public view returns(uint) {

        if(tokenDetails[contractAddress].supply == 0){

            return SafeMath.sub(initialPrice, incrementPrice);

        } else {

            uint256 _token = collateralToToken_(contractAddress, 1e18);

            uint256 _dividends = SafeMath.div(_token, dividendFee);

            uint256 _taxedToken = SafeMath.sub(_token, _dividends);

            return _taxedToken;

        }

    }
    

    /**

     * @dev function to calculate collateral price based on an amount of incoming token

     * It's an scientific algorithm;

     * Some conversions occurred to prevent decimal errors or underflows / overflows in solidity code.

     */

    function tokentoCollateral_(address contractAddress, uint256 amount) internal view returns(uint256)

    {

        uint256 _tokenPriceInitial = initialPrice * 1e18;

        uint256 tokenSupply_ = tokenDetails[contractAddress].supply;

        uint256 tokenPriceIncremental_ = incrementPrice;

        

        uint256 _tokensReceived = 

         (

            (

                // underflow attempts BTFO

                SafeMath.sub(

                    (sqrt

                        (

                            (_tokenPriceInitial**2)

                            +

                            (2*(tokenPriceIncremental_ * 1e18)*(amount * 1e18))

                            +

                            (((tokenPriceIncremental_)**2)*(tokenSupply_**2))

                            +

                            (2*(tokenPriceIncremental_)*_tokenPriceInitial*tokenSupply_)

                        )

                    ), _tokenPriceInitial

                )

            )/(tokenPriceIncremental_)

        )-(tokenSupply_)

        ;

  

        return _tokensReceived;

    }

    

    /**

     * @dev function to calculate token price based on an amount of incoming collateral

     * It's an scientific algorithm;

     * Some conversions occurred to prevent decimal errors or underflows / overflows in solidity code.

     */

    function collateralToToken_(address contractAddress, uint256 _tokens) internal view returns(uint256)

    {
        uint256 tokens_ = SafeMath.add(_tokens, 1e18) ;

        uint256 _tokenSupply = SafeMath.add(tokenDetails[contractAddress].supply, 1e18);

        uint256 tokenPriceInitial_ = initialPrice;

        uint tokenPriceIncremental_ = incrementPrice;

        

        uint256 _etherReceived =

        (

            // underflow attempts BTFO

            SafeMath.sub(

                (

                    (

                        (

                            tokenPriceInitial_ +(tokenPriceIncremental_ * (_tokenSupply/1e18))

                        )-tokenPriceIncremental_

                    )*(tokens_ - 1e18)

                ),(tokenPriceIncremental_*((tokens_**2-tokens_)/1e18))/2

            )

        /1e18);

        

        return _etherReceived;

    }

    

    /**

     * @dev function to calculate amount of collateral received after sending tokens

     */

    function calculateCollateReceived(address contractAddress, uint256 _tokenAmount) public view returns(uint256)

    {

        uint256 _dividends = SafeMath.div(_tokenAmount, dividendFee);

        uint256 _taxedToken = SafeMath.sub(_tokenAmount, _dividends);

        uint256 _amountOfCollatral = tokentoCollateral_(contractAddress, _taxedToken);

        

        return _amountOfCollatral;

    }

     

    /**

     * @dev function to calculate amount of tokens received after sending collateral

     */

    function calculateTokenReceived(address contractAddress, uint256 _collateToSell) public view returns(uint256)

    {

        require(_collateToSell <= tokenDetails[contractAddress].supply);

        uint256 _token = collateralToToken_(contractAddress, _collateToSell);

        uint256 _dividends = SafeMath.div(_token, dividendFee);

        uint256 _taxedToken = SafeMath.sub(_token, _dividends);

        return _taxedToken;

    }  

    

    /**

     * @dev function to process purchase of collateral and update user balance, dividend

     */

    function purchaseCollate(address contractAddress, uint256 _incomingToken, address _referredBy) internal returns(uint256)

    {

        // data setup

        uint256 incomingToken__ = _incomingToken;

        address _customerAddress = msg.sender;

        uint256 _undividedDividends = SafeMath.div(_incomingToken, dividendFee);

        uint256 _referralBonus = SafeMath.div(_undividedDividends, 3);

        uint256 _dividends = SafeMath.sub(_undividedDividends, _referralBonus);

        uint256 _taxedToken = SafeMath.sub(_incomingToken, _undividedDividends);

        uint256 _amountOfCollate = tokentoCollateral_(contractAddress,_taxedToken);

        uint256 _fee = SafeMath.mul(_dividends, magnitude);

        uint256 totalSupply__ = tokenDetails[contractAddress].supply;

        address contractAddress__ = contractAddress;

        address referredBy__ =_referredBy;

 

      

        require(_amountOfCollate > 0 && (SafeMath.add(_amountOfCollate,totalSupply__) > totalSupply__));

        

        // is the user referred by a karmalink?

        if(

            // is this a referred purchase?

            _referredBy != address(0) &&

            

            // no cheating!

            referredBy__ != _customerAddress &&

            

            walletAddressList[_referredBy] == true

        ){

            // wealth redistribution

            balanceDetails[_referredBy][contractAddress__].referralBalance = SafeMath.add(balanceDetails[_referredBy][contractAddress__].referralBalance, _referralBonus);

        } else {

            // no ref purchase

            // add the referral bonus back to the global dividends cake

            _dividends = SafeMath.add(_dividends, _referralBonus);

            _fee = SafeMath.mul(_dividends, magnitude);

        }

        

        // we can't give people infinite ethereum

        if(tokenDetails[contractAddress__].supply > 0){

            totalSupply__ = tokenDetails[contractAddress__].supply;

            

            // add tokens to the pool

            tokenDetails[contractAddress__].supply = SafeMath.add(tokenDetails[contractAddress__].supply, _amountOfCollate);

 

            // take the amount of dividends gained through this transaction, and allocates them evenly to each shareholder

            tokenDetails[contractAddress__].dividend = SafeMath.add(tokenDetails[contractAddress__].dividend,SafeMath.div(SafeMath.mul(_dividends, magnitude), totalSupply__)) ;

            

            // calculate the amount of tokens the customer receives over his purchase 

            _fee = SafeMath.sub(_fee, (SafeMath.sub(_fee, SafeMath.mul(_amountOfCollate, SafeMath.div(SafeMath.mul(_dividends, magnitude), totalSupply__)))));

        

        } else {

            // add tokens to the pool

            tokenDetails[contractAddress__].supply = _amountOfCollate;

        }

        

        // update circulating supply & the ledger address for the customer

        balanceDetails[_customerAddress][contractAddress__].tokenBalance = SafeMath.add(balanceDetails[_customerAddress][contractAddress__].tokenBalance, _amountOfCollate);

        

        uint256 currentDividend = tokenDetails[contractAddress__].dividend;

        

        int256 _updatedPayouts = (int256) (SafeMath.sub((SafeMath.mul(currentDividend, _amountOfCollate)), _fee));

        balanceDetails[_customerAddress][contractAddress__].payOut = SignedSafeMath.add(balanceDetails[_customerAddress][contractAddress__].payOut,_updatedPayouts);

        

        // fire event

        emit onPurchase(_customerAddress, contractAddress__, incomingToken__, _amountOfCollate, referredBy__);

        

        return _amountOfCollate;

    }

    

    /**

     * @dev function to get tokens contract hold

     */

    function totalTokenBalance(address contractAddress) public view returns(uint)

    {   

        if (contractAddress== address(0)){

            return address(this).balance;

        }

        else{

            return ERC20(contractAddress).balanceOf(address(this));

        }

    }

    

    /**

     * @dev function to retrieve the total token supply.

     */

    function totalSupply(address contractAddress) public view returns(uint256)

    {

        return tokenDetails[contractAddress].supply;

    }

    

    /**

     * @dev function to retrieve the tokens owned by the caller.

     */

    function myTokens(address contractAddress) public view returns(uint256)

    {

        address _customerAddress = msg.sender;

        return balanceOf(contractAddress, _customerAddress);

    }

    

    /**

     * @dev function to retrieve the dividends owned by the caller.

      */ 

    function myDividends(address contractAddress, bool _includeReferralBonus) public view returns(uint256)

    {

        address _customerAddress = msg.sender;

        return _includeReferralBonus ? SafeMath.add(dividendsOf(contractAddress,_customerAddress), balanceDetails[_customerAddress][contractAddress].referralBalance) : dividendsOf(contractAddress, _customerAddress) ;

    }

    

    /**

     * @dev function to retrieve the token balance of any single address.

     */

    function balanceOf(address contractAddress, address _customerAddress) view public returns(uint256)

    {

        return balanceDetails[_customerAddress][contractAddress].tokenBalance;

    }

    

    /**

     * @dev function to retrieve the dividend balance of any single address.

     */

    function dividendsOf(address contractAddress, address _customerAddress) view public returns(uint256)

    {

        return SafeMath.div(((uint256) (SignedSafeMath.sub((int256)(SafeMath.mul(tokenDetails[contractAddress].dividend, balanceDetails[_customerAddress][contractAddress].tokenBalance)), balanceDetails[_customerAddress][contractAddress].payOut))), magnitude);

    }

    
    /**

     * @dev function to return active tokens list in system

     */ 

    function tokenList() public view returns (address [] memory){

        return contractAddressSet;

    }

    

    /**

     * @dev function to return active wallets list in system

     */ 

    function walletList() public view returns (address [] memory){

        return walletAddressSet;

    }

    
    /**

     * @dev function to process upgrade of user balance to new token contract address in case project decide to change ERC-20 token contract

     * This function will be used only when project team sent equivalent new contract in system token without asking for returning old tokens

     * token swap ratio must be same

     * this will protect users from price crash due to token sell for swapping or new token stuck

     * User will be having access of both old and new contract tokens

     */ 

    function assignUpgradedTokens(address contractAddress, address newContractAddress) public onlyOwner returns(bool success)

    {

        // validate old contract is already part of system

        require(contractAddressList[contractAddress]=true, "Ccontract tokens must be part of system");

        

        // activate new contractAddress in system

        if(contractAddressList[newContractAddress]==false)

        {

            contractAddressList[newContractAddress]=true ;

            tokenDetails[newContractAddress].supply = 0;

            tokenDetails[newContractAddress].dividend = 0;

            

            contractAddressSet.push(newContractAddress);

        }

        

        for(uint i = 0; i < walletAddressSet.length; i++)

        {

            if (balanceDetails[walletAddressSet[i]][contractAddress].tokenBalance > 0 || balanceDetails[walletAddressSet[i]][contractAddress].payOut > 0)

            {

                // assign new tokens. we are keeping old token as it is and user can withdraw that also

                balanceDetails[walletAddressSet[i]][newContractAddress].tokenBalance = balanceDetails[walletAddressSet[i]][contractAddress].tokenBalance;

                balanceDetails[walletAddressSet[i]][newContractAddress].referralBalance = balanceDetails[walletAddressSet[i]][contractAddress].referralBalance;

                balanceDetails[walletAddressSet[i]][newContractAddress].payOut = balanceDetails[walletAddressSet[i]][contractAddress].payOut;

                

            }

        }

        

        // assign dividend, current price and supply to new contract

        tokenDetails[newContractAddress].supply = tokenDetails[contractAddress].supply;

        tokenDetails[newContractAddress].dividend = tokenDetails[contractAddress].dividend;

        

        return true;

    }

    

    /**

     * @dev function to startDeposit

     */ 

    function startContract() public onlyOwner returns(bool status){

        startDeposit = true;

        return true;

    }

    

    function sqrt(uint x) internal pure returns (uint y) {

        uint z = SafeMath.div(SafeMath.add(x, 1), 2);

        y = x;

        while (z < y) {

            y = z;

            z = SafeMath.div((SafeMath.add(SafeMath.div(x, z), z)), 2);

        }

    }

}
/**

 * @dev interface to process transfer of ERC20 tokens

 */ 

interface ERC20 {

    function totalSupply() external view returns (uint supply);

    function allowance(address _owner, address _spender) external view returns (uint remaining);

    function approve(address _spender, uint _value) external returns (bool success);

    function balanceOf(address _owner) external view returns (uint balance);

    function transfer(address _to, uint _value) external returns (bool success);

    function transferFrom(address _from, address _to, uint _value) external returns (bool success);
    event Approval(address indexed _owner, address indexed _spender,    uint _value);

    event Transfer(address indexed _from, address indexed _to, uint    _value);

}
/**

 * @dev safemath library to avoid mathematical overflow error

 */ 

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) {

        // 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 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;

    }

}
library SignedSafeMath {

    int256 constant private _INT256_MIN = -2**255;
    function mul(int256 a, int256 b) internal pure returns (int256) {

        if (a == 0) {

            return 0;

        }
        require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");
        int256 c = a * b;

        require(c / a == b, "SignedSafeMath: multiplication overflow");
        return c;

    }
    function div(int256 a, int256 b) internal pure returns (int256) {

        require(b != 0, "SignedSafeMath: division by zero");

        require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");
        int256 c = a / b;
        return c;

    }
    function sub(int256 a, int256 b) internal pure returns (int256) {

        int256 c = a - b;

        require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");
        return c;

    }
    function add(int256 a, int256 b) internal pure returns (int256) {

        int256 c = a + b;

        require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");
        return c;

    }

}