Skip to main content
PulseScanner.io

Address

0xec54d281380bdbf0c41f26b52d8bf6edd2de36ee
Current Holdings
$0.00
TXs sent
not counted
First Active
2024-03-25
block 19,946,547
Last Active
906 days ago
block 19,946,547
Funded By
not identified

Net worth historyi

No net-worth snapshots recorded yet
exact matchBabyTokensolc 0.8.19+commit.7dd6d404runtime exact · creation exact
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

/**
 *  ____  _______  _______           _     
 * |  _ \| ____\ \/ /_   _|__   ___ | |___ 
 * | | | |  _|  \  /  | |/ _ \ / _ \| / __|
 * | |_| | |___ /  \  | | (_) | (_) | \__ \
 * |____/|_____/_/\_\ |_|\___/ \___/|_|___/
 *
 * This smart contract was created effortlessly using the DEXTools Token Creator.
 * 
 * 🌐 Website: https://www.dextools.io/
 * 🐦 Twitter: https://twitter.com/DEXToolsApp
 * 💬 Telegram: https://t.me/DEXToolsCommunity
 * 
 * 🚀 Unleash the power of decentralized finances and tokenization with DEXTools Token Creator. Customize your token seamlessly. Manage your created tokens conveniently from your user panel - start creating your dream token today!
 */
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { SafeERC20NoRevert, BabyTokenDividendTracker } from "./BabyTokenDividendTracker.sol";
import { IUniswapV2Factory } from "./interfaces/IUniswapV2Factory.sol";
import { IUniswapV2Router02 } from "./interfaces/IUniswapV2Router02.sol";
import { IAntiBot } from "./interfaces/IAntiBot.sol";

enum TokenType {
    Standard,
    Liquidity,
    LiquidityFee,
    LiquidityBuySellFee,
    Burn,
    Baby
}

contract BabyToken is ERC20Upgradeable, OwnableUpgradeable {
    using Address for address;
    using Address for address payable;
    using SafeERC20 for IERC20;

    uint256 public constant VERSION = 1;

    IUniswapV2Router02 public uniswapV2Router;
    address public uniswapV2Pair;

    bool private swapping;

    BabyTokenDividendTracker public dividendTracker;

    address public rewardToken;

    uint256 public swapTokensAtAmount;

    uint256 public tokenRewardsFee;
    uint256 public liquidityFee;
    uint256 public marketingFee;
    uint256 public totalFees;

    address public _marketingWalletAddress;

    uint256 public gasForProcessing;

    // exlcude from fees and max transaction amount
    mapping(address => bool) private _isExcludedFromFees;

    // store addresses that a automatic market maker pairs. Any transfer *to* these addresses
    // could be subject to a maximum transfer amount
    mapping(address => bool) public automatedMarketMakerPairs;

    event ExcludeFromFees(address indexed account);
    event ExcludeMultipleAccountsFromFees(address[] accounts);

    event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);

    event GasForProcessingUpdated(
        uint256 indexed newValue,
        uint256 indexed oldValue
    );

    event SwapAndLiquify(
        uint256 tokensSwapped,
        uint256 ethReceived,
        uint256 tokensIntoLiqudity
    );

    event SendDividends(uint256 tokensSwapped, uint256 amount);

    event ProcessedDividendTracker(
        uint256 iterations,
        uint256 claims,
        uint256 lastProcessedIndex,
        bool indexed automatic,
        uint256 gas,
        address indexed processor
    );

    IAntiBot public antiBot;
    bool public enableAntiBot;

    //@custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize(
        address owner_,
        string memory name_,
        string memory symbol_,
        uint256 totalSupply_,
        address[5] memory addrs, // reward, router, marketing wallet, dividendTracker, antibot
        uint256[3] memory feeSettings, // rewards, liquidity, marketing
        uint256 minimumTokenBalanceForDividends_,
        bool enableAntiBot_
    ) external initializer {
        __ERC20_init(name_, symbol_);
        __Ownable_init();
        transferOwnership(owner_);

        rewardToken = addrs[0];
        _marketingWalletAddress = addrs[2];
        require(
            owner_ != _marketingWalletAddress,
            "Owner and marketing wallet cannot be the same"
        );
        require(
            !_marketingWalletAddress.isContract(),
            "Marketing wallet cannot be a contract"
        );

        if (enableAntiBot_) {
            antiBot = IAntiBot(addrs[4]);
            antiBot.setTokenOwner(owner());
            enableAntiBot = true;
        }

        tokenRewardsFee = feeSettings[0];
        liquidityFee = feeSettings[1];
        marketingFee = feeSettings[2];
        totalFees = tokenRewardsFee + liquidityFee + marketingFee;
        require(totalFees <= 20, "Total fee is over 20%");
        swapTokensAtAmount = totalSupply_ / 1000; // 0.1%

        // use by default 300,000 gas to process auto-claiming dividends
        gasForProcessing = 300000;

        dividendTracker = BabyTokenDividendTracker(
            payable(Clones.clone(addrs[3]))
        );

        dividendTracker.initialize(
            rewardToken,
            minimumTokenBalanceForDividends_
        );

        IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(addrs[1]);
        // Create a uniswap pair for this new token
        address _uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
            .createPair(address(this), _uniswapV2Router.WETH());
        uniswapV2Router = _uniswapV2Router;
        uniswapV2Pair = _uniswapV2Pair;
        _setAutomatedMarketMakerPair(_uniswapV2Pair, true);

        // exclude from receiving dividends
        dividendTracker.excludeFromDividends(address(dividendTracker));
        dividendTracker.excludeFromDividends(address(this));
        dividendTracker.excludeFromDividends(owner());
        dividendTracker.excludeFromDividends(address(0xdead));
        dividendTracker.excludeFromDividends(address(_uniswapV2Router));
        // exclude from paying fees or having max transaction amount
        _isExcludedFromFees[owner()] = true;
        _isExcludedFromFees[_marketingWalletAddress] = true;
        _isExcludedFromFees[address(this)] = true;
        /*
            _mint is an internal function in ERC20.sol that is only called here,
            and CANNOT be called ever again
        */
        _mint(owner(), totalSupply_);
    }

    receive() external payable {}

    function setSwapTokensAtAmount(uint256 amount) external onlyOwner {
        require(
            amount > totalSupply() / 10 ** 5,
            "BabyToken: Amount must be greater than 0.001% of total supply"
        );
        swapTokensAtAmount = amount;
    }

    function excludeFromFees(address account) external onlyOwner {
        require(
            !_isExcludedFromFees[account],
            "BabyToken: Account is already excluded"
        );
        _isExcludedFromFees[account] = true;

        emit ExcludeFromFees(account);
    }

    function excludeMultipleAccountsFromFees(
        address[] calldata accounts
    ) external onlyOwner {
        for (uint256 i = 0; i < accounts.length; i++) {
            _isExcludedFromFees[accounts[i]] = true;
        }

        emit ExcludeMultipleAccountsFromFees(accounts);
    }

    function setMarketingWallet(address payable wallet) external onlyOwner {
        require(
            wallet != address(0),
            "BabyToken: The marketing wallet cannot be the value of zero"
        );
        require(!wallet.isContract(), "Marketing wallet cannot be a contract");
        _marketingWalletAddress = wallet;
    }

    function setTokenRewardsFee(uint256 value) external onlyOwner {
        tokenRewardsFee = value;
        totalFees = tokenRewardsFee + liquidityFee + marketingFee;
        require(totalFees <= 20, "Total fee is over 20%");
    }

    function setLiquidityFee(uint256 value) external onlyOwner {
        liquidityFee = value;
        totalFees = tokenRewardsFee + liquidityFee + marketingFee;
        require(totalFees <= 20, "Total fee is over 20%");
    }

    function setMarketingFee(uint256 value) external onlyOwner {
        marketingFee = value;
        totalFees = tokenRewardsFee + liquidityFee + marketingFee;
        require(totalFees <= 20, "Total fee is over 20%");
    }

    function addToBlacklist(address[] calldata addresses) external onlyOwner {
        require(enableAntiBot, "antibot not enabled");
        antiBot.addToBlacklist(_msgSender(), addresses);
    }

    function removeFromBlacklist(address addr) external onlyOwner {
        require(enableAntiBot, "antibot not enabled");
        antiBot.removeFromBlacklist(_msgSender(), addr);
    }

    function getBlacklistStatus()
        external
        view
        returns (bool, uint256, uint256, uint256, uint256)
    {
        if (enableAntiBot == false) return (false, 0, 0, 0, 0);

        (
            uint256 creationTime,
            uint256 blacklistTime,
            uint256 blacklistLimit,
            uint256 blacklistSize
        ) = antiBot.getBlacklistStatus(address(this));

        return (
            enableAntiBot,
            creationTime,
            blacklistTime,
            blacklistLimit,
            blacklistSize
        );
    }

    function getBlacklist() external view returns (address[] memory) {
        require(enableAntiBot, "antibot not enabled");
        return antiBot.getBlacklist(address(this));
    }

    function isBlacklisted(address account) external view returns (bool) {
        require(enableAntiBot, "antibot not enabled");
        return antiBot.isBlacklisted(address(this), account);
    }

    function _setAutomatedMarketMakerPair(address pair, bool value) private {
        require(
            automatedMarketMakerPairs[pair] != value,
            "BabyToken: Automated market maker pair is already set to that value"
        );
        automatedMarketMakerPairs[pair] = value;

        if (value) {
            dividendTracker.excludeFromDividends(pair);
        }

        emit SetAutomatedMarketMakerPair(pair, value);
    }

    function updateGasForProcessing(uint256 newValue) public onlyOwner {
        require(
            newValue >= 200000 && newValue <= 500000,
            "BabyToken: gasForProcessing must be between 200,000 and 500,000"
        );
        require(
            newValue != gasForProcessing,
            "BabyToken: Cannot update gasForProcessing to same value"
        );
        emit GasForProcessingUpdated(newValue, gasForProcessing);
        gasForProcessing = newValue;
    }

    function updateClaimWait(uint256 claimWait) external onlyOwner {
        dividendTracker.updateClaimWait(claimWait);
    }

    function getClaimWait() external view returns (uint256) {
        return dividendTracker.claimWait();
    }

    function updateMinimumTokenBalanceForDividends(
        uint256 amount
    ) external onlyOwner {
        dividendTracker.updateMinimumTokenBalanceForDividends(amount);
    }

    function getMinimumTokenBalanceForDividends()
        external
        view
        returns (uint256)
    {
        return dividendTracker.minimumTokenBalanceForDividends();
    }

    function getTotalDividendsDistributed() external view returns (uint256) {
        return dividendTracker.totalDividendsDistributed();
    }

    function isExcludedFromFees(address account) public view returns (bool) {
        return _isExcludedFromFees[account];
    }

    function withdrawableDividendOf(
        address account
    ) public view returns (uint256) {
        return dividendTracker.withdrawableDividendOf(account);
    }

    function dividendTokenBalanceOf(
        address account
    ) public view returns (uint256) {
        return dividendTracker.balanceOf(account);
    }

    function excludeFromDividends(address account) external onlyOwner {
        dividendTracker.excludeFromDividends(account);
    }

    function isExcludedFromDividends(
        address account
    ) public view returns (bool) {
        return dividendTracker.isExcludedFromDividends(account);
    }

    function getAccountDividendsInfo(
        address account
    )
        external
        view
        returns (
            address,
            int256,
            int256,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256
        )
    {
        return dividendTracker.getAccount(account);
    }

    function getAccountDividendsInfoAtIndex(
        uint256 index
    )
        external
        view
        returns (
            address,
            int256,
            int256,
            uint256,
            uint256,
            uint256,
            uint256,
            uint256
        )
    {
        return dividendTracker.getAccountAtIndex(index);
    }

    function processDividendTracker(uint256 gas) external {
        (
            uint256 iterations,
            uint256 claims,
            uint256 lastProcessedIndex
        ) = dividendTracker.process(gas);
        emit ProcessedDividendTracker(
            iterations,
            claims,
            lastProcessedIndex,
            false,
            gas,
            tx.origin // solhint-disable-line avoid-tx-origin
        );
    }

    function claim() external {
        dividendTracker.processAccount(payable(msg.sender), false);
    }

    function getLastProcessedIndex() external view returns (uint256) {
        return dividendTracker.getLastProcessedIndex();
    }

    function getNumberOfDividendTokenHolders() external view returns (uint256) {
        return dividendTracker.getNumberOfTokenHolders();
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal override {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        if (amount == 0) {
            super._transfer(from, to, 0);
            return;
        }

        if (enableAntiBot) {
            antiBot.onPreTransferCheck(from, to);
        }

        uint256 contractTokenBalance = balanceOf(address(this));

        bool canSwap = contractTokenBalance >= swapTokensAtAmount;

        if (
            canSwap &&
            !swapping &&
            !automatedMarketMakerPairs[from] &&
            from != owner() &&
            to != owner() &&
            totalFees > 0
        ) {
            swapping = true;

            if (marketingFee > 0) {
                uint256 marketingTokens = (contractTokenBalance *
                    marketingFee) / totalFees;
                swapAndSendToFee(marketingTokens);
            }

            if (liquidityFee > 0) {
                uint256 swapTokens = (contractTokenBalance * liquidityFee) /
                    totalFees;
                swapAndLiquify(swapTokens);
            }

            uint256 sellTokens = balanceOf(address(this));
            if (sellTokens > 0) {
                swapAndSendDividends(sellTokens);
            }

            swapping = false;
        }

        bool takeFee = !swapping;

        // if any account belongs to _isExcludedFromFee account then remove the fee
        if (_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
            takeFee = false;
        }

        if (takeFee && totalFees > 0) {
            uint256 fees = (amount * totalFees) / 100;
            amount = amount - fees;

            super._transfer(from, address(this), fees);
        }

        super._transfer(from, to, amount);

        try
            dividendTracker.setBalance(payable(from), balanceOf(from))
        {} catch {}
        try dividendTracker.setBalance(payable(to), balanceOf(to)) {} catch {}

        if (!swapping) {
            uint256 gas = gasForProcessing;

            try dividendTracker.process(gas) returns (
                uint256 iterations,
                uint256 claims,
                uint256 lastProcessedIndex
            ) {
                emit ProcessedDividendTracker(
                    iterations,
                    claims,
                    lastProcessedIndex,
                    true,
                    gas,
                    tx.origin // solhint-disable-line avoid-tx-origin
                );
            } catch {}
        }
    }

    function swapAndSendToFee(uint256 tokens) private {
        uint256 initialCAKEBalance = IERC20(rewardToken).balanceOf(
            address(this)
        );

        swapTokensForCake(tokens);
        uint256 newBalance = IERC20(rewardToken).balanceOf(address(this)) -
            initialCAKEBalance;
        IERC20(rewardToken).safeTransfer(_marketingWalletAddress, newBalance);
    }

    function swapAndLiquify(uint256 tokens) private {
        // split the contract balance into halves
        uint256 half = tokens / 2;
        uint256 otherHalf = tokens - half;

        // capture the contract's current ETH balance.
        // this is so that we can capture exactly the amount of ETH that the
        // swap creates, and not make the liquidity event include any ETH that
        // has been manually sent to the contract
        uint256 initialBalance = address(this).balance;

        // swap tokens for ETH
        swapTokensForEth(half); // <- this breaks the ETH -> HATE swap when swap+liquify is triggered

        // how much ETH did we just swap into?
        uint256 newBalance = address(this).balance - initialBalance;

        // add liquidity to uniswap
        addLiquidity(otherHalf, newBalance);

        emit SwapAndLiquify(half, newBalance, otherHalf);
    }

    function swapTokensForEth(uint256 tokenAmount) private {
        // generate the uniswap pair path of token -> weth
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = uniswapV2Router.WETH();

        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // make the swap
        uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            0, // accept any amount of ETH
            path,
            address(this),
            block.timestamp
        );
    }

    function swapTokensForCake(uint256 tokenAmount) private {
        address[] memory path = new address[](3);
        path[0] = address(this);
        path[1] = uniswapV2Router.WETH();
        path[2] = rewardToken;

        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // make the swap
        uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            tokenAmount,
            0,
            path,
            address(this),
            block.timestamp
        );
    }

    function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
        // approve token transfer to cover all possible scenarios
        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // add the liquidity
        uniswapV2Router.addLiquidityETH{ value: ethAmount }(
            address(this),
            tokenAmount,
            0, // slippage is unavoidable
            0, // slippage is unavoidable
            address(0xdead),
            block.timestamp
        );
    }

    function swapAndSendDividends(uint256 tokens) private {
        swapTokensForCake(tokens);
        uint256 dividends = IERC20(rewardToken).balanceOf(address(this));
        bool success = SafeERC20NoRevert.safeTransfer(
            IERC20(rewardToken),
            address(dividendTracker),
            dividends
        );
        if (success) {
            dividendTracker.distributeCAKEDividends(dividends);
            emit SendDividends(tokens, dividends);
        }
    }
}