ETH Price: $1,885.64 (+1.37%)

Transaction Decoder

Block:
21709680 at Jan-26-2025 03:47:11 PM +UTC
Transaction Fee:
0.000710230427928192 ETH $1.34
Gas Used:
85,416 Gas / 8.314957712 Gwei

Emitted Events:

176 StandardToken.Transfer( from=[Receiver] Presale, to=[Sender] 0xb6b6b39d53cb4c275aaebd524b4fb4bb77568281, value=15008278450000000000000 )
177 Presale.ClaimToken( _user=[Sender] 0xb6b6b39d53cb4c275aaebd524b4fb4bb77568281, _amount=15008278450000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x0165E89F...C3F44D93E
(Titan Builder)
5.625978666236551771 Eth5.626059034150951771 Eth0.0000803679144
0xB6B6B39D...b77568281
0.007419152349461696 Eth
Nonce: 1
0.006708921921533504 Eth
Nonce: 2
0.000710230427928192
0xe091E9Dc...cd5608EE0

Execution Trace

Presale.CALL( )
  • StandardToken.transfer( recipient=0xB6B6B39D53CB4c275AAebd524B4fB4Bb77568281, amount=15008278450000000000000 ) => ( True )
    File 1 of 2: Presale
    /**
     *Submitted for verification at Etherscan.io on 2024-02-24
    */
    
    //SPDX-License-Identifier: MIT Licensed
    pragma solidity ^0.8.17;
    
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
    
        function _msgData() internal view virtual returns (bytes calldata) {
            return msg.data;
        }
    }
    
    contract Ownable is Context {
        address private _owner;
    
        event OwnershipTransferred(
            address indexed previousOwner,
            address indexed newOwner
        );
    
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        constructor(address _newOwner) {
            _transferOwnership(_newOwner);
        }
    
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view virtual returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            require(owner() == _msgSender(), "Ownable: caller is not the owner");
            _;
        }
    
        function renounceOwnership() public virtual onlyOwner {
            _transferOwnership(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"
            );
            _transferOwnership(newOwner);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Internal function without access restriction.
         */
        function _transferOwnership(address newOwner) internal virtual {
            address oldOwner = _owner;
            _owner = newOwner;
            emit OwnershipTransferred(oldOwner, newOwner);
        }
    }
    
    interface IERC20 {
        function name() external view returns (string memory);
    
        function symbol() external view returns (string memory);
    
        function decimals() external view returns (uint8);
    
        function totalSupply() external view returns (uint256);
    
        function balanceOf(address owner) external view returns (uint256);
    
        function allowance(
            address owner,
            address spender
        ) external view returns (uint256);
    
        function approve(address spender, uint256 value) external;
    
        function transfer(address to, uint256 value) external;
    
        function transferFrom(address from, address to, uint256 value) external;
    
        event Approval(
            address indexed owner,
            address indexed spender,
            uint256 value
        );
        event Transfer(address indexed from, address indexed to, uint256 value);
    }
    
    interface AggregatorV3Interface {
        function decimals() external view returns (uint8);
    
        function description() external view returns (string memory);
    
        function version() external view returns (uint256);
    
        function getRoundData(
            uint80 _roundId
        )
            external
            view
            returns (
                uint80 roundId,
                int256 answer,
                uint256 startedAt,
                uint256 updatedAt,
                uint80 answeredInRound
            );
    
        function latestRoundData()
            external
            view
            returns (
                uint80 roundId,
                int256 answer,
                uint256 startedAt,
                uint256 updatedAt,
                uint80 answeredInRound
            );
    }
    
    contract Presale is Ownable {
        IERC20 public mainToken;
        IERC20 public USDT = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);
    
        AggregatorV3Interface public priceFeed;
    
        struct Phase {
            uint256 tokensToSell;
            uint256 totalSoldTokens;
            uint256 tokenPerUsdPrice;
        }
        mapping(uint256 => Phase) public phases;
    
        uint256 public totalStages;
        uint256 public currentStage;
        uint256 public totalUsers;
        uint256 public soldToken;
        uint256 public amountRaised;
        uint256 public amountRaisedUSDT;
        address payable public fundReceiver;
        uint256 tokenDecimals;
        uint256[] tokensToSell;
        uint256[] tokenPerUsdPrice;
    
        bool public presaleStatus;
        bool public isPresaleEnded;
    
        address[] public UsersAddresses;
    
        mapping(address => bool) public oldBuyer;
        struct User {
            uint256 native_balance;
            uint256 usdt_balance;
            uint256 token_balance;
            uint256 claimed_tokens;
        }
    
        mapping(address => User) public users;
    
        struct Transaction {
            uint256 trxAt;
            uint256 presaleId;
            uint256 buyAmount;
            uint256 tokenAmount;
            bool isEther;
        }
    
        struct TopBuyer {
            address userAddress;
            uint256 tokenAmount;
        }
        TopBuyer[3] public topBuyersData;
        Transaction[] public transactionsHistory;
    
        event BuyToken(address indexed _user, uint256 indexed _amount);
        event ClaimToken(address indexed _user, uint256 indexed _amount);
        event UpdatePrice(uint256 _oldPrice, uint256 _newPrice);
    
        constructor(IERC20 _token, address _fundReceiver) Ownable(msg.sender) {
            mainToken = _token;
            fundReceiver = payable(_fundReceiver);
            priceFeed = AggregatorV3Interface(
                0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
            );
            tokenDecimals = mainToken.decimals();
            tokensToSell = [
                250_000_000 * 10 ** tokenDecimals,
                250_000_000 * 10 ** tokenDecimals,
                250_000_000 * 10 ** tokenDecimals,
                250_000_000 * 10 ** tokenDecimals,
                250_000_000 * 10 ** tokenDecimals,
                250_000_000 * 10 ** tokenDecimals
            ];
            tokenPerUsdPrice = [
                2500 * (10 ** tokenDecimals),
                2000 * (10 ** tokenDecimals),
                1666 * (10 ** tokenDecimals),
                1428 * (10 ** tokenDecimals),
                1250 * (10 ** tokenDecimals),
                1111 * (10 ** tokenDecimals)
            ];
            for (uint256 i = 0; i < tokensToSell.length; i++) {
                phases[i].tokensToSell = tokensToSell[i];
                phases[i].tokenPerUsdPrice = tokenPerUsdPrice[i];
            }
            totalStages = tokensToSell.length;
        }
    
        // to get real time price of BNB
        function getLatestPrice() public view returns (uint256) {
            (, int256 price, , , ) = priceFeed.latestRoundData();
            return uint256(price);
        }
    
        // to buy token during preSale time with BNB => for web3 use
    
        function buyToken() public payable {
            require(!isPresaleEnded, "Presale ended!");
            require(presaleStatus, " Presale is Paused, check back later");
            if (!oldBuyer[msg.sender]) {
                totalUsers += 1;
                UsersAddresses.push(msg.sender);
            }
            fundReceiver.transfer(msg.value);
    
            uint256 numberOfTokens;
            numberOfTokens = nativeToToken(msg.value, currentStage);
            require(
                phases[currentStage].totalSoldTokens + numberOfTokens <=
                    phases[currentStage].tokensToSell,
                "Phase Limit Reached"
            );
            soldToken = soldToken + (numberOfTokens);
            amountRaised = amountRaised + BnbToUsd(msg.value);
    
            users[msg.sender].native_balance =
                users[msg.sender].native_balance +
                (msg.value);
            users[msg.sender].token_balance =
                users[msg.sender].token_balance +
                (numberOfTokens);
            phases[currentStage].totalSoldTokens += numberOfTokens;
            oldBuyer[msg.sender] = true;
    
            updateTopBuyerData(msg.sender, users[msg.sender].token_balance);
            updateTransactionHistory(currentStage, msg.value, numberOfTokens, true);
        }
    
        // to buy token during preSale time with USDT => for web3 use
        function buyTokenUSDT(uint256 amount) public {
            require(!isPresaleEnded, "Presale ended!");
            require(presaleStatus, " Presale is Paused, check back later");
            if (!oldBuyer[msg.sender]) {
                totalUsers += 1;
                UsersAddresses.push(msg.sender);
            }
            USDT.transferFrom(msg.sender, fundReceiver, amount);
    
            uint256 numberOfTokens;
            numberOfTokens = usdtToToken(amount, currentStage);
            require(
                phases[currentStage].totalSoldTokens + numberOfTokens <=
                    phases[currentStage].tokensToSell,
                "Phase Limit Reached"
            );
            soldToken = soldToken + numberOfTokens;
            amountRaisedUSDT = amountRaisedUSDT + amount;
    
            users[msg.sender].usdt_balance += amount;
    
            users[msg.sender].token_balance =
                users[msg.sender].token_balance +
                numberOfTokens;
            phases[currentStage].totalSoldTokens += numberOfTokens;
            oldBuyer[msg.sender] = true;
    
            updateTopBuyerData(msg.sender, users[msg.sender].token_balance);
            updateTransactionHistory(currentStage, amount, numberOfTokens, false);
        }
    
        function updateTopBuyerData(address _user, uint256 _tokenAmount) internal {
            // Check if the user is already in the top buyers
            for (uint256 i = 0; i < topBuyersData.length; i++) {
                if (_user == topBuyersData[i].userAddress) {
                    topBuyersData[i].tokenAmount = _tokenAmount;
                    return;
                }
            }
    
            for (uint256 i = 0; i < topBuyersData.length; i++) {
                if (_tokenAmount > topBuyersData[i].tokenAmount) {
                    for (uint256 j = topBuyersData.length - 1; j > i; j--) {
                        topBuyersData[j] = topBuyersData[j - 1];
                    }
    
                    topBuyersData[i] = TopBuyer(_user, _tokenAmount);
                    break;
                }
            }
        }
    
        function updateTransactionHistory(
            uint256 _presaleId,
            uint256 _buyAmount,
            uint256 _noOfTokens,
            bool _isEthTrx
        ) internal {
            Transaction memory newTransaction = Transaction(
                block.timestamp,
                _presaleId,
                _buyAmount,
                _noOfTokens,
                _isEthTrx
            );
            transactionsHistory.push(newTransaction);
            if (transactionsHistory.length > 20) {
                for (uint256 i = 0; i < transactionsHistory.length - 1; i++) {
                    transactionsHistory[i] = transactionsHistory[i + 1];
                }
                transactionsHistory.pop();
            }
        }
    
        function claimTokens() external {
            require(isPresaleEnded, "Presale has not ended yet");
            User storage user = users[msg.sender];
            require(user.token_balance > 0, "No tokens purchased");
            uint256 claimableTokens = user.token_balance - user.claimed_tokens;
            require(claimableTokens > 0, "No tokens to claim");
            user.claimed_tokens += claimableTokens;
            mainToken.transfer(msg.sender, claimableTokens);
            emit ClaimToken(msg.sender, claimableTokens);
        }
    
        function getPhaseDetail(
            uint256 phaseInd
        )
            external
            view
            returns (uint256 tokenToSell, uint256 soldTokens, uint256 priceUsd)
        {
            Phase memory phase = phases[phaseInd];
            return (
                phase.tokensToSell,
                phase.totalSoldTokens,
                phase.tokenPerUsdPrice
            );
        }
    
        function setPresaleStatus(bool _status) external onlyOwner {
            presaleStatus = _status;
        }
    
        function endPresale() external onlyOwner {
            isPresaleEnded = true;
        }
    
        // to check number of token for given BNB
        function nativeToToken(
            uint256 _amount,
            uint256 phaseId
        ) public view returns (uint256) {
            uint256 bnbToUsd = (_amount * (getLatestPrice())) / (1 ether);
            uint256 numberOfTokens = (bnbToUsd * phases[phaseId].tokenPerUsdPrice) /
                (1e8);
            return numberOfTokens;
        }
    
        // BNB to USD
        function BnbToUsd(uint256 _amount) public view returns (uint256) {
            uint256 bnbToUsd = (_amount * (getLatestPrice())) / (1e8);
            return bnbToUsd;
        }
    
        // to check number of token for given usdt
        function usdtToToken(
            uint256 _amount,
            uint256 phaseId
        ) public view returns (uint256) {
            uint256 numberOfTokens = (_amount * phases[phaseId].tokenPerUsdPrice) /
                (10 ** USDT.decimals());
            return numberOfTokens;
        }
    
        function updateInfos(
            uint256 _sold,
            uint256 _raised,
            uint256 _raisedInUsdt
        ) external onlyOwner {
            soldToken = _sold;
            amountRaised = _raised;
            amountRaisedUSDT = _raisedInUsdt;
        }
    
        // change tokens
        function updateToken(address _token) external onlyOwner {
            mainToken = IERC20(_token);
        }
    
        function whitelistEthAddresses(
            address[] memory _addresses,
            uint256[] memory _tokenAmount
        ) external onlyOwner {
            require(
                _addresses.length == _tokenAmount.length,
                "Addresses and amounts must be equal"
            );
    
            for (uint256 i = 0; i < _addresses.length; i++) {
                users[_addresses[i]].token_balance += _tokenAmount[i];
            }
        }
    
        //change tokens for buy
        function updateStableTokens(IERC20 _USDT) external onlyOwner {
            USDT = IERC20(_USDT);
        }
    
        // to withdraw funds for liquidity
        function initiateTransfer(uint256 _value) external onlyOwner {
            fundReceiver.transfer(_value);
        }
    
        function totalUsersCount() external view returns (uint256) {
            return UsersAddresses.length;
        }
    
        // to withdraw funds for liquidity
        function changeFundReciever(address _addr) external onlyOwner {
            fundReceiver = payable(_addr);
        }
    
        // to withdraw funds for liquidity
        function updatePriceFeed(
            AggregatorV3Interface _priceFeed
        ) external onlyOwner {
            priceFeed = _priceFeed;
        }
    
        // funtion is used to change the stage of presale
        function setCurrentPhase(uint256 _stageNum) public onlyOwner {
            currentStage = _stageNum;
        }
    
        // to withdraw out tokens
        function transferStuckTokens(
            IERC20 token,
            uint256 _value
        ) external onlyOwner {
            token.transfer(msg.sender, _value);
        }
    }

    File 2 of 2: StandardToken
    // Dependency file: @openzeppelin/contracts/token/ERC20/IERC20.sol
    
    // SPDX-License-Identifier: MIT
    
    // pragma solidity ^0.8.0;
    
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP.
     */
    interface IERC20 {
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
    
        /**
         * @dev Returns the amount of tokens owned by `account`.
         */
        function balanceOf(address account) external view returns (uint256);
    
        /**
         * @dev Moves `amount` tokens from the caller's account to `recipient`.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transfer(address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Returns the remaining number of tokens that `spender` will be
         * allowed to spend on behalf of `owner` through {transferFrom}. This is
         * zero by default.
         *
         * This value changes when {approve} or {transferFrom} are called.
         */
        function allowance(address owner, address spender) external view returns (uint256);
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * IMPORTANT: Beware that changing an allowance with this method brings the risk
         * that someone may use both the old and the new allowance by unfortunate
         * transaction ordering. One possible solution to mitigate this race
         * condition is to first reduce the spender's allowance to 0 and set the
         * desired value afterwards:
         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
         *
         * Emits an {Approval} event.
         */
        function approve(address spender, uint256 amount) external returns (bool);
    
        /**
         * @dev Moves `amount` tokens from `sender` to `recipient` using the
         * allowance mechanism. `amount` is then deducted from the caller's
         * allowance.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transferFrom(
            address sender,
            address recipient,
            uint256 amount
        ) external returns (bool);
    
        /**
         * @dev Emitted when `value` tokens are moved from one account (`from`) to
         * another (`to`).
         *
         * Note that `value` may be zero.
         */
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        /**
         * @dev Emitted when the allowance of a `spender` for an `owner` is set by
         * a call to {approve}. `value` is the new allowance.
         */
        event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    
    // Dependency file: @openzeppelin/contracts/utils/Context.sol
    
    
    // pragma solidity ^0.8.0;
    
    /**
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
    
        function _msgData() internal view virtual returns (bytes calldata) {
            return msg.data;
        }
    }
    
    
    // Dependency file: @openzeppelin/contracts/access/Ownable.sol
    
    
    // pragma solidity ^0.8.0;
    
    // import "@openzeppelin/contracts/utils/Context.sol";
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * By default, the owner account will be the one that deploys the contract. This
     * can later be changed with {transferOwnership}.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    abstract contract Ownable is Context {
        address private _owner;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        constructor() {
            _setOwner(_msgSender());
        }
    
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view virtual returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            require(owner() == _msgSender(), "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 {
            _setOwner(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");
            _setOwner(newOwner);
        }
    
        function _setOwner(address newOwner) private {
            address oldOwner = _owner;
            _owner = newOwner;
            emit OwnershipTransferred(oldOwner, newOwner);
        }
    }
    
    
    // Dependency file: @openzeppelin/contracts/utils/math/SafeMath.sol
    
    
    // pragma solidity ^0.8.0;
    
    // CAUTION
    // This version of SafeMath should only be used with Solidity 0.8 or later,
    // because it relies on the compiler's built in overflow checks.
    
    /**
     * @dev Wrappers over Solidity's arithmetic operations.
     *
     * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
     * now has built in overflow checking.
     */
    library SafeMath {
        /**
         * @dev Returns the addition of two unsigned integers, with an overflow flag.
         *
         * _Available since v3.4._
         */
        function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
            unchecked {
                uint256 c = a + b;
                if (c < a) return (false, 0);
                return (true, c);
            }
        }
    
        /**
         * @dev Returns the substraction of two unsigned integers, with an overflow flag.
         *
         * _Available since v3.4._
         */
        function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
            unchecked {
                if (b > a) return (false, 0);
                return (true, a - b);
            }
        }
    
        /**
         * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
         *
         * _Available since v3.4._
         */
        function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
            unchecked {
                // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                // benefit is lost if 'b' is also tested.
                // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                if (a == 0) return (true, 0);
                uint256 c = a * b;
                if (c / a != b) return (false, 0);
                return (true, c);
            }
        }
    
        /**
         * @dev Returns the division of two unsigned integers, with a division by zero flag.
         *
         * _Available since v3.4._
         */
        function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
            unchecked {
                if (b == 0) return (false, 0);
                return (true, a / b);
            }
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
         *
         * _Available since v3.4._
         */
        function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
            unchecked {
                if (b == 0) return (false, 0);
                return (true, a % b);
            }
        }
    
        /**
         * @dev Returns the addition of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `+` operator.
         *
         * Requirements:
         *
         * - Addition cannot overflow.
         */
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            return a + b;
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         *
         * - Subtraction cannot overflow.
         */
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            return a - b;
        }
    
        /**
         * @dev Returns the multiplication of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `*` operator.
         *
         * Requirements:
         *
         * - Multiplication cannot overflow.
         */
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            return a * b;
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers, reverting on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator.
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            return a / b;
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * reverting when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            return a % b;
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
         * overflow (when the result is negative).
         *
         * CAUTION: This function is deprecated because it requires allocating memory for the error
         * message unnecessarily. For custom revert reasons use {trySub}.
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         *
         * - Subtraction cannot overflow.
         */
        function sub(
            uint256 a,
            uint256 b,
            string memory errorMessage
        ) internal pure returns (uint256) {
            unchecked {
                require(b <= a, errorMessage);
                return a - b;
            }
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers, reverting with custom message on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function div(
            uint256 a,
            uint256 b,
            string memory errorMessage
        ) internal pure returns (uint256) {
            unchecked {
                require(b > 0, errorMessage);
                return a / b;
            }
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * reverting with custom message when dividing by zero.
         *
         * CAUTION: This function is deprecated because it requires allocating memory for the error
         * message unnecessarily. For custom revert reasons use {tryMod}.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         *
         * - The divisor cannot be zero.
         */
        function mod(
            uint256 a,
            uint256 b,
            string memory errorMessage
        ) internal pure returns (uint256) {
            unchecked {
                require(b > 0, errorMessage);
                return a % b;
            }
        }
    }
    
    
    // Dependency file: contracts/BaseToken.sol
    
    // pragma solidity =0.8.4;
    
    enum TokenType {
        standard,
        antiBotStandard,
        liquidityGenerator,
        antiBotLiquidityGenerator,
        baby,
        antiBotBaby,
        buybackBaby,
        antiBotBuybackBaby
    }
    
    abstract contract BaseToken {
        event TokenCreated(
            address indexed owner,
            address indexed token,
            TokenType tokenType,
            uint256 version
        );
    }
    
    
    // Root file: contracts/standard/StandardToken.sol
    
    pragma solidity =0.8.4;
    
    // import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
    // import "@openzeppelin/contracts/access/Ownable.sol";
    // import "@openzeppelin/contracts/utils/math/SafeMath.sol";
    // import "contracts/BaseToken.sol";
    
    contract StandardToken is IERC20, Ownable, BaseToken {
        using SafeMath for uint256;
    
        uint256 public constant VERSION = 1;
    
        mapping(address => uint256) private _balances;
        mapping(address => mapping(address => uint256)) private _allowances;
    
        string private _name;
        string private _symbol;
        uint8 private _decimals;
        uint256 private _totalSupply;
    
        constructor(
            string memory name_,
            string memory symbol_,
            uint8 decimals_,
            uint256 totalSupply_,
            address serviceFeeReceiver_,
            uint256 serviceFee_
        ) payable {
            _name = name_;
            _symbol = symbol_;
            _decimals = decimals_;
            _mint(owner(), totalSupply_);
    
            emit TokenCreated(owner(), address(this), TokenType.standard, VERSION);
    
            payable(serviceFeeReceiver_).transfer(serviceFee_);
        }
    
        /**
         * @dev Returns the name of the token.
         */
        function name() public view virtual returns (string memory) {
            return _name;
        }
    
        /**
         * @dev Returns the symbol of the token, usually a shorter version of the
         * name.
         */
        function symbol() public view virtual returns (string memory) {
            return _symbol;
        }
    
        /**
         * @dev Returns the number of decimals used to get its user representation.
         * For example, if `decimals` equals `2`, a balance of `505` tokens should
         * be displayed to a user as `5,05` (`505 / 10 ** 2`).
         *
         * Tokens usually opt for a value of 18, imitating the relationship between
         * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
         * called.
         *
         * NOTE: This information is only used for _display_ purposes: it in
         * no way affects any of the arithmetic of the contract, including
         * {IERC20-balanceOf} and {IERC20-transfer}.
         */
        function decimals() public view virtual returns (uint8) {
            return _decimals;
        }
    
        /**
         * @dev See {IERC20-totalSupply}.
         */
        function totalSupply() public view virtual override returns (uint256) {
            return _totalSupply;
        }
    
        /**
         * @dev See {IERC20-balanceOf}.
         */
        function balanceOf(address account)
            public
            view
            virtual
            override
            returns (uint256)
        {
            return _balances[account];
        }
    
        /**
         * @dev See {IERC20-transfer}.
         *
         * Requirements:
         *
         * - `recipient` cannot be the zero address.
         * - the caller must have a balance of at least `amount`.
         */
        function transfer(address recipient, uint256 amount)
            public
            virtual
            override
            returns (bool)
        {
            _transfer(_msgSender(), recipient, amount);
            return true;
        }
    
        /**
         * @dev See {IERC20-allowance}.
         */
        function allowance(address owner, address spender)
            public
            view
            virtual
            override
            returns (uint256)
        {
            return _allowances[owner][spender];
        }
    
        /**
         * @dev See {IERC20-approve}.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function approve(address spender, uint256 amount)
            public
            virtual
            override
            returns (bool)
        {
            _approve(_msgSender(), spender, amount);
            return true;
        }
    
        /**
         * @dev See {IERC20-transferFrom}.
         *
         * Emits an {Approval} event indicating the updated allowance. This is not
         * required by the EIP. See the note at the beginning of {ERC20}.
         *
         * Requirements:
         *
         * - `sender` and `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `amount`.
         * - the caller must have allowance for ``sender``'s tokens of at least
         * `amount`.
         */
        function transferFrom(
            address sender,
            address recipient,
            uint256 amount
        ) public virtual override returns (bool) {
            _transfer(sender, recipient, amount);
            _approve(
                sender,
                _msgSender(),
                _allowances[sender][_msgSender()].sub(
                    amount,
                    "ERC20: transfer amount exceeds allowance"
                )
            );
            return true;
        }
    
        /**
         * @dev Atomically increases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function increaseAllowance(address spender, uint256 addedValue)
            public
            virtual
            returns (bool)
        {
            _approve(
                _msgSender(),
                spender,
                _allowances[_msgSender()][spender].add(addedValue)
            );
            return true;
        }
    
        /**
         * @dev Atomically decreases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         * - `spender` must have allowance for the caller of at least
         * `subtractedValue`.
         */
        function decreaseAllowance(address spender, uint256 subtractedValue)
            public
            virtual
            returns (bool)
        {
            _approve(
                _msgSender(),
                spender,
                _allowances[_msgSender()][spender].sub(
                    subtractedValue,
                    "ERC20: decreased allowance below zero"
                )
            );
            return true;
        }
    
        /**
         * @dev Moves tokens `amount` from `sender` to `recipient`.
         *
         * This is internal function is equivalent to {transfer}, and can be used to
         * e.g. implement automatic token fees, slashing mechanisms, etc.
         *
         * Emits a {Transfer} event.
         *
         * Requirements:
         *
         * - `sender` cannot be the zero address.
         * - `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `amount`.
         */
        function _transfer(
            address sender,
            address recipient,
            uint256 amount
        ) internal virtual {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");
    
            _beforeTokenTransfer(sender, recipient, amount);
    
            _balances[sender] = _balances[sender].sub(
                amount,
                "ERC20: transfer amount exceeds balance"
            );
            _balances[recipient] = _balances[recipient].add(amount);
            emit Transfer(sender, recipient, amount);
        }
    
        /** @dev Creates `amount` tokens and assigns them to `account`, increasing
         * the total supply.
         *
         * Emits a {Transfer} event with `from` set to the zero address.
         *
         * Requirements:
         *
         * - `to` cannot be the zero address.
         */
        function _mint(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: mint to the zero address");
    
            _beforeTokenTransfer(address(0), account, amount);
    
            _totalSupply = _totalSupply.add(amount);
            _balances[account] = _balances[account].add(amount);
            emit Transfer(address(0), account, amount);
        }
    
        /**
         * @dev Destroys `amount` tokens from `account`, reducing the
         * total supply.
         *
         * Emits a {Transfer} event with `to` set to the zero address.
         *
         * Requirements:
         *
         * - `account` cannot be the zero address.
         * - `account` must have at least `amount` tokens.
         */
        function _burn(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: burn from the zero address");
    
            _beforeTokenTransfer(account, address(0), amount);
    
            _balances[account] = _balances[account].sub(
                amount,
                "ERC20: burn amount exceeds balance"
            );
            _totalSupply = _totalSupply.sub(amount);
            emit Transfer(account, address(0), amount);
        }
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
         *
         * This internal function is equivalent to `approve`, and can be used to
         * e.g. set automatic allowances for certain subsystems, etc.
         *
         * Emits an {Approval} event.
         *
         * Requirements:
         *
         * - `owner` cannot be the zero address.
         * - `spender` cannot be the zero address.
         */
        function _approve(
            address owner,
            address spender,
            uint256 amount
        ) internal virtual {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");
    
            _allowances[owner][spender] = amount;
            emit Approval(owner, spender, amount);
        }
    
        /**
         * @dev Sets {decimals} to a value other than the default one of 18.
         *
         * WARNING: This function should only be called from the constructor. Most
         * applications that interact with token contracts will not expect
         * {decimals} to ever change, and may work incorrectly if it does.
         */
        function _setupDecimals(uint8 decimals_) internal virtual {
            _decimals = decimals_;
        }
    
        /**
         * @dev Hook that is called before any transfer of tokens. This includes
         * minting and burning.
         *
         * Calling conditions:
         *
         * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
         * will be to transferred to `to`.
         * - when `from` is zero, `amount` tokens will be minted for `to`.
         * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
         * - `from` and `to` are never both zero.
         *
         * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
         */
        function _beforeTokenTransfer(
            address from,
            address to,
            uint256 amount
        ) internal virtual {}
    }