// Original license: SPDX_License_Identifier: UNLICENSED
pragma solidity ^0.8.21;





contract Wojak2050 is Ownable, ERC20 {
    IUniswapV2Router02 public router;
    IUniswapV2Factory public factory;
    IUniswapV2Pair public pair;

    uint private constant INITIAL_SUPPLY = 2_050_000_000 * 10 ** 18;
    uint constant LP_BPS = 9000;

    bool isSellingCollectedTaxes;
    uint public buyTaxBps = 200;
    uint public sellTaxBps = 200;
    uint public maxHoldingAmount = 1_025_000 * 10 ** 18;
    address public feeReceiver;

    bool public isTradingEnabled;
    bool public isLimitsDisabled;
    bool public isLaunched;

    event TokenLaunched();

    constructor(address _feeReceiver) ERC20("Wojak 2050", "WTF", 18) {
        setFeeReceiver(_feeReceiver);

        router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
        factory = IUniswapV2Factory(router.factory());

        allowance[address(this)][address(router)] = type(uint).max;
        emit Approval(address(this), address(router), type(uint).max);

        _mint(msg.sender, (INITIAL_SUPPLY * (10_000 - LP_BPS)) / 10_000);
    }

    modifier lockTheSwap() {
        isSellingCollectedTaxes = true;
        _;
        isSellingCollectedTaxes = false;
    }

    receive() external payable {}

    fallback() external payable {}

    function burn(uint amount) external {
        _burn(msg.sender, amount);
    }

    function getMinSwapAmount() internal view returns (uint) {
        return (totalSupply * 1) / 10_000;
    }

    function setFeeReceiver(address _feeReceiver) public onlyOwner {
        require(_feeReceiver != address(0), "null address");
        feeReceiver = _feeReceiver;
    }

    function setMaxHoldingAmount(uint _maxHoldingAmount) external onlyOwner {
        maxHoldingAmount = _maxHoldingAmount;
    }

    function launch() external payable onlyOwner {
        require(!isLaunched, "already launched");
        require(feeReceiver != address(0), "null address");

        _mint(address(this), (INITIAL_SUPPLY * LP_BPS) / 10_000);
        router.addLiquidityETH{value: msg.value}(
            address(this),
            balanceOf[address(this)],
            0,
            0,
            owner(),
            block.timestamp
        );

        pair = IUniswapV2Pair(factory.getPair(address(this), router.WETH()));

        require(totalSupply == INITIAL_SUPPLY, "numbers dont add up");

        isLaunched = true;
        emit TokenLaunched();
    }

    function enableTrading() external onlyOwner {
        require(isLaunched, "not yet launched");
        require(!isTradingEnabled, "trading already enabled");
        isTradingEnabled = true;
    }

    function disableLimits() external onlyOwner {
        require(isLaunched, "not yet launched");
        isLimitsDisabled = true;
    }

    function calculateTax(
        address from,
        address to,
        uint amount
    ) internal view returns (uint) {
        if (from == owner() || to == owner() || from == address(this)) {
            return 0;
        } else if (from == address(pair)) {
            return (amount * buyTaxBps) / 10_000;
        } else if (to == address(pair)) {
            return (amount * sellTaxBps) / 10_000;
        } else {
            return 0;
        }
    }

    function sellCollectedTaxes() internal lockTheSwap {
        uint tokensToSwap = balanceOf[address(this)];

        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = router.WETH();
        router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokensToSwap,
            0,
            path,
            address(this),
            block.timestamp
        );

        feeReceiver.call{value: address(this).balance}("");
    }

    function transfer(address to, uint amount) public override returns (bool) {
        return transferFrom(msg.sender, to, amount);
    }

    function transferFrom(
        address from,
        address to,
        uint amount
    ) public override returns (bool) {
        if (from != msg.sender) {
            uint allowed = allowance[from][msg.sender];

            if (allowed != type(uint).max) {
                allowance[from][msg.sender] = allowed - amount;
            }
        }

        if (isLaunched && !isTradingEnabled) {
            require(
                from != address(pair) && to != address(pair),
                "trading disabled"
            );
        }

        if (
            balanceOf[address(this)] > getMinSwapAmount() &&
            !isSellingCollectedTaxes &&
            from != address(pair) &&
            from != address(this)
        ) {
            sellCollectedTaxes();
        }

        uint tax = calculateTax(from, to, amount);
        uint afterTaxAmount = amount - tax;

        if (isLaunched && !isLimitsDisabled && from == address(pair)) {
            require(
                balanceOf[to] + afterTaxAmount <= maxHoldingAmount,
                "exceeds max holding amount"
            );
        }

        balanceOf[from] -= amount;

        unchecked {
            balanceOf[to] += afterTaxAmount;
        }

        emit Transfer(from, to, afterTaxAmount);

        if (tax > 0) {
            unchecked {
                balanceOf[address(this)] += tax;
            }

            emit Transfer(from, address(this), tax);
        }

        return true;
    }
}
[{"inputs":[{"internalType":"address","name":"_feeReceiver","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"TokenLaunched","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyTaxBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"disableLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IUniswapV2Factory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isLaunched","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isLimitsDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTradingEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"maxHoldingAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"contract IUniswapV2Pair","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellTaxBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_feeReceiver","type":"address"}],"name":"setFeeReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxHoldingAmount","type":"uint256"}],"name":"setMaxHoldingAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]