ETH Price: $2,147.62 (+0.08%)
Gas: 0.03 Gwei

Contract Diff Checker

Contract Name:
CUPIUSDTPOOL

Contract Source Code:

File 1 of 1 : CUPIUSDTPOOL

/**
 *Submitted for verification at Etherscan.io on 2020-11-27
 */

// File: contracts/Interfaces.sol

// SPDX-License-Identifier: --🦉--
pragma solidity =0.6.12;

interface IERC20 {
    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address recipient, uint256 amount)
        external
        returns (bool);

    function mint(address account, uint256 amount) external;

    function allowance(address owner, address spender)
        external
        view
        returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}

pragma solidity =0.6.12;

library SafeMathLT {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "addition overflow");
        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "subtraction overflow");
        uint256 c = a - b;
        return c;
    }

    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "multiplication overflow");

        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "division by zero");
        uint256 c = a / b;
        return c;
    }

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "modulo by zero");
        return a % b;
    }
}

pragma solidity =0.6.12;

library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * This test is non-exhaustive, and there may be false-negatives: during the
     * execution of a contract's constructor, its address will be reported as
     * not containing a contract.
     *
     * IMPORTANT: It is unsafe to assume that an address for which this
     * function returns false is an externally-owned account (EOA) and not a
     * contract.
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;


            bytes32 accountHash
         = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            codehash := extcodehash(account)
        }
        return (codehash != 0x0 && codehash != accountHash);
    }

    /**
     * @dev Converts an `address` into `address payable`. Note that this is
     * simply a type cast: the actual underlying value is not changed.
     *
     * _Available since v2.4.0._
     */
    function toPayable(address account)
        internal
        pure
        returns (address payable)
    {
        return address(uint160(account));
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     *
     * _Available since v2.4.0._
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(
            address(this).balance >= amount,
            "Address: insufficient balance"
        );

        // solhint-disable-next-line avoid-call-value
        (bool success, ) = recipient.call{value: amount}("");
        // (bool success, ) = recipient.call.value(amount)("");
        require(
            success,
            "Address: unable to send value, recipient may have reverted"
        );
    }
}

pragma solidity =0.6.12;

library SafeERC20 {
    using SafeMathLT for uint256;
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        callOptionalReturn(
            token,
            abi.encodeWithSelector(token.transfer.selector, to, value)
        );
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        callOptionalReturn(
            token,
            abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
        );
    }

    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        callOptionalReturn(
            token,
            abi.encodeWithSelector(token.approve.selector, spender, value)
        );
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(
            value
        );
        callOptionalReturn(
            token,
            abi.encodeWithSelector(
                token.approve.selector,
                spender,
                newAllowance
            )
        );
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(
            value,
            "SafeERC20: decreased allowance below zero"
        );
        callOptionalReturn(
            token,
            abi.encodeWithSelector(
                token.approve.selector,
                spender,
                newAllowance
            )
        );
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.

        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.
        // solhint-disable-next-line max-line-length
        require(address(token).isContract(), "SafeERC20: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");

        if (returndata.length > 0) {
            // Return data is optional
            // solhint-disable-next-line max-line-length
            require(
                abi.decode(returndata, (bool)),
                "SafeERC20: ERC20 operation did not succeed"
            );
        }
    }
}

pragma solidity =0.6.12;
// pragma solidity =0.7.0;
pragma experimental ABIEncoderV2;

contract CUPIUSDTPOOL {
    using SafeMathLT for uint256;
    using SafeERC20 for IERC20;

    IERC20 public mintedToken = IERC20(
        0xe7D2914136E63f209f0e9De3100eD60ce18A3e8E
    );

    IERC20 public poolToken = IERC20(
        0xdAC17F958D2ee523a2206206994597C13D831ec7
    );

    struct Difficulty {
        uint256 EndedAt;
        bool Exists;
    }

    struct Deposit {
        uint256 Difficulty;
        uint256 Amount;
        uint256 DepositedAt;
        bool Closed;
        uint256 ClosedAt;
    }

    struct User {
        bool Exists;
        uint256 Balances;
        Deposit[] Deposits;
        address Referrer;
        address[] Invited1st;
        address[] Invited2nd;
    }

    struct Reward {
        uint256 ClosedRewardTotal;
        uint256 ClosedRewardUsed;
        bool Stoped;
        uint256 CurrentRewardUsed;
        uint256 MintRewardTotal;
        uint256 LastRewardAt;
    }

    uint256 public CONTRACT_STARTED_AT;
    uint256 public CONTRACT_DEPOSIT_PERCENT = 20;
    uint256 public CONTRACT_WITHDRAWN_PERCENT = 0;
    uint256 public TOKEN_MINT_TOTAL = 15000000 * 1e18;
    uint256 public TOKEN_MINT_USED = 0;
    uint256 private TOTAL_BALANCE_SUPPLY = 0;
    uint256 public CONTRACT_DIFFICULTY = 1 * 1e18;

    mapping(uint256 => Difficulty) public DIFFICULTIES;
    mapping(address => User) public USERS;
    mapping(address => Reward) public REWARDS;
    mapping(address => uint256) public BONUS;

    address payable public CONTRACT_DEVELOPER;
    address payable public CONTRACT_FOUNDATION;
    address public CONTRACT_DEFAULT_REFERRER;
    bool public CONTRACT_INITED = false;

    uint256[] public REFERRAL_PERCENTS = [10, 5];
    uint256[] public ALLDIFFICULTIES = [CONTRACT_DIFFICULTY];

    event onStake(address indexed account, address referrer, uint256 amount);
    event onReward(address indexed account, uint256 reward);
    event onBouns(address indexed account, uint256 bouns);
    event onWithdraw(address indexed account, uint256 amount);

    modifier afterDeveloper() {
        require(msg.sender == CONTRACT_DEVELOPER);
        _;
    }

    modifier afterStarted() {
        require(block.timestamp > CONTRACT_STARTED_AT, "not start");
        _;
    }

    constructor() public {
        CONTRACT_DEVELOPER = msg.sender;
        CONTRACT_STARTED_AT = block.timestamp + 1 minutes;
    }

    receive() external payable {
        revert();
    }

    function _(
        address account,
        uint256 amount,
        address referrer
    ) internal {
        if (referrer == account) {
            referrer = CONTRACT_DEFAULT_REFERRER;
        }

        if (USERS[account].Exists == false) {
            USERS[account].Referrer = referrer;

            USERS[referrer].Invited1st.push(account);
            USERS[USERS[referrer].Referrer].Invited2nd.push(account);
        }

        USERS[account].Deposits.push(
            Deposit(CONTRACT_DIFFICULTY, amount, block.timestamp, false, 0)
        );
        USERS[account].Balances = USERS[account].Balances.add(amount);
        TOTAL_BALANCE_SUPPLY = TOTAL_BALANCE_SUPPLY.add(amount);
        USERS[account].Exists = true;

        if (REWARDS[msg.sender].Stoped) {
            getReward();
        }

        emit onStake(account, referrer, amount);
    }

    function stakeToken(uint256 amount, address referrer)
        external
        afterStarted
    {
        require(referrer != address(0), "referrer = address(0)");
        require(amount > 0, "amount = 0");

        poolToken.safeTransferFrom(msg.sender, address(this), amount);

        uint256 burnAmount = amount.mul(CONTRACT_DEPOSIT_PERCENT).div(100);
        poolToken.safeTransfer(CONTRACT_FOUNDATION, burnAmount);

        _(msg.sender, amount.sub(burnAmount), referrer);
    }

    function computeDifficulties(Deposit memory d)
        internal
        view
        returns (uint256)
    {
        uint256 earnedAmount;
        uint256 nextEndedAt = d.DepositedAt;

        if (ALLDIFFICULTIES.length > 1) {
            uint256 difficultyIndex = 0;
            for (uint256 i = 0; i < ALLDIFFICULTIES.length; i++) {
                if (ALLDIFFICULTIES[i] == d.Difficulty) {
                    difficultyIndex = i;
                    break;
                }
            }

            for (uint256 i = difficultyIndex; i < ALLDIFFICULTIES.length; i++) {
                if (DIFFICULTIES[ALLDIFFICULTIES[i]].Exists) {
                    earnedAmount = earnedAmount.add(
                        d.Amount.mul(
                            DIFFICULTIES[ALLDIFFICULTIES[i]]
                                .EndedAt
                                .sub(nextEndedAt)
                                .div(1 seconds)
                                .mul(ALLDIFFICULTIES[i])
                                .div(1e8)
                        )
                    );

                    nextEndedAt = DIFFICULTIES[ALLDIFFICULTIES[i]].EndedAt;
                }
            }
        }

        earnedAmount = earnedAmount.add(
            d
                .Amount
                .mul(block.timestamp.sub(nextEndedAt).div(1 seconds))
                .mul(CONTRACT_DIFFICULTY)
                .div(1e8)
        );

        return earnedAmount;
    }

    function _earned(address account) internal view returns (uint256) {
        require(account != address(0), "account = address(0)");
        require(
            TOKEN_MINT_USED < TOKEN_MINT_TOTAL,
            "TOKEN_MINT_USED >= TOKEN_MINT_TOTAL"
        );

        User memory u = USERS[account];

        uint256 earnedAmount;

        for (uint256 i = 0; i < u.Deposits.length; i++) {
            Deposit memory d = u.Deposits[i];

            if (d.Closed) {
                continue;
            }

            earnedAmount = earnedAmount.add(computeDifficulties(d));
        }

        earnedAmount = earnedAmount.div(1 days);
        earnedAmount = earnedAmount.add(
            REWARDS[account].ClosedRewardTotal.sub(
                REWARDS[account].ClosedRewardUsed
            )
        );

        earnedAmount = earnedAmount.sub(REWARDS[account].CurrentRewardUsed);

        if (TOKEN_MINT_USED.add(earnedAmount) > TOKEN_MINT_TOTAL) {
            earnedAmount = earnedAmount.sub(
                TOKEN_MINT_USED.add(earnedAmount).sub(TOKEN_MINT_TOTAL)
            );
        }

        return earnedAmount;
    }

    function getMyEarnd(address account)
        public
        view
        afterStarted
        returns (uint256)
    {
        return _earned(account);
    }

    function getMyInvitedLength(address account)
        external
        view
        returns (uint256, uint256)
    {
        User memory user = USERS[account];

        return (user.Invited1st.length, user.Invited2nd.length);
    }

    function getMyInvitedBonus(address account)
        public
        view
        afterStarted
        returns (uint256)
    {
        require(account != address(0), "account = address(0)");

        uint256 bonusBonus1st;
        uint256 bonusBonus2nd;

        User memory user = USERS[account];

        for (uint256 i = 0; i < user.Invited1st.length; i++) {
            uint256 earnedAmount;
            uint256 rewardAmount = REWARDS[user.Invited1st[i]].MintRewardTotal;

            earnedAmount = _earned(user.Invited1st[i]).add(rewardAmount);
            bonusBonus1st = bonusBonus1st.add(
                earnedAmount.mul(REFERRAL_PERCENTS[0]).div(100)
            );
        }

        for (uint256 i = 0; i < user.Invited2nd.length; i++) {
            uint256 earnedAmount;
            uint256 rewardAmount = REWARDS[user.Invited2nd[i]].MintRewardTotal;

            earnedAmount = _earned(user.Invited2nd[i]).add(rewardAmount);
            bonusBonus2nd = bonusBonus2nd.add(
                earnedAmount.mul(REFERRAL_PERCENTS[1]).div(100)
            );
        }

        return bonusBonus1st.add(bonusBonus2nd).sub(BONUS[account]);
    }

    function getBonus() public afterStarted {
        uint256 bonusAmount;

        bonusAmount = getMyInvitedBonus(msg.sender);

        if (bonusAmount > 0) {
            BONUS[msg.sender] = BONUS[msg.sender].add(bonusAmount);
            TOKEN_MINT_USED = TOKEN_MINT_USED.add(bonusAmount);

            mintedToken.safeTransfer(msg.sender, bonusAmount);
            emit onBouns(msg.sender, bonusAmount);
        }
    }

    function getReward() public afterStarted {
        uint256 earnedAmount;
        uint256 totalAmount;

        earnedAmount = _earned(msg.sender);

        if (REWARDS[msg.sender].Stoped) {
            REWARDS[msg.sender].Stoped = false;
            REWARDS[msg.sender].CurrentRewardUsed = 0;
        } else {
            REWARDS[msg.sender].CurrentRewardUsed = REWARDS[msg.sender]
                .CurrentRewardUsed
                .add(earnedAmount);
        }

        totalAmount = earnedAmount;

        if (totalAmount > 0) {
            REWARDS[msg.sender].ClosedRewardUsed = REWARDS[msg.sender]
                .ClosedRewardTotal;
            TOKEN_MINT_USED = TOKEN_MINT_USED.add(totalAmount);
            REWARDS[msg.sender].MintRewardTotal = REWARDS[msg.sender]
                .MintRewardTotal
                .add(totalAmount);

            mintedToken.safeTransfer(msg.sender, totalAmount);
            emit onReward(msg.sender, totalAmount);
        }
    }

    function withdraw() public afterStarted {
        User storage u = USERS[msg.sender];

        TOTAL_BALANCE_SUPPLY = TOTAL_BALANCE_SUPPLY.sub(u.Balances);

        REWARDS[msg.sender].ClosedRewardTotal = REWARDS[msg.sender]
            .ClosedRewardTotal
            .add(_earned(msg.sender));

        REWARDS[msg.sender].CurrentRewardUsed = 0;
        REWARDS[msg.sender].Stoped = true;

        for (uint256 i = 0; i < u.Deposits.length; i++) {
            u.Deposits[i].Closed = true;
            u.Deposits[i].ClosedAt = block.timestamp;
        }

         uint256 burnAmount = u.Balances.mul(CONTRACT_WITHDRAWN_PERCENT).div(
            100
        );
        uint256 amount = u.Balances.sub(burnAmount);

        poolToken.safeTransfer(msg.sender, amount);
        poolToken.safeTransfer(CONTRACT_FOUNDATION, burnAmount);

        emit onWithdraw(msg.sender, amount);

        u.Balances = 0;
    }

    function exit() external afterStarted {
        withdraw();
        getBonus();
        getReward();
    }

    function getDeposit(address account)
        external
        view
        afterStarted
        returns (Deposit[] memory)
    {
        require(account != address(0), "account = address(0)");

        User memory u = USERS[account];

        return u.Deposits;
    }

    function totalSupply() public view returns (uint256) {
        return TOTAL_BALANCE_SUPPLY;
    }

    function balanceOf(address account)
        public
        view
        afterStarted
        returns (uint256)
    {
        require(account != address(0), "account = address(0)");

        return USERS[account].Balances;
    }

    function setDifficulty(uint256 v)
        external
        afterDeveloper
        returns (uint256)
    {
        require(DIFFICULTIES[v].Exists == false, "difficulty = true");

        ALLDIFFICULTIES.push(v);
        DIFFICULTIES[CONTRACT_DIFFICULTY] = Difficulty(block.timestamp, true);
        CONTRACT_DIFFICULTY = v;

        return ALLDIFFICULTIES.length;
    }

    function setDepositPercent(uint256 percent) external afterDeveloper {
        CONTRACT_DEPOSIT_PERCENT = percent;

        require(
            CONTRACT_DEPOSIT_PERCENT.add(CONTRACT_WITHDRAWN_PERCENT) <= 100
        );
    }

    function setWithdrawnPercent(uint256 percent) external afterDeveloper {
        CONTRACT_WITHDRAWN_PERCENT = percent;

        require(
            CONTRACT_DEPOSIT_PERCENT.add(CONTRACT_WITHDRAWN_PERCENT) <= 100
        );
    }

    function setDefaultReferrer(address account) external afterDeveloper {
        require(account != address(0), "account = address(0)");

        CONTRACT_DEFAULT_REFERRER = account;
    }

    function setDeveloper(address payable account) external afterDeveloper {
        require(account != address(0), "account = address(0)");

        CONTRACT_DEVELOPER = account;
    }

    function setFoundation(address payable account) external afterDeveloper {
        require(account != address(0), "account = address(0)");

        CONTRACT_FOUNDATION = account;
    }

    function init() external afterDeveloper {
        require(CONTRACT_INITED == false, "CONTRACT_INITED = true");

        mintedToken.mint(address(this), TOKEN_MINT_TOTAL);

        CONTRACT_INITED = true;
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):