Skip to main content
PulseScanner.io

Address

0x8cf3ca2720de36dcf4ffed5500f03d7fc7bbfc67
Current Holdings
$0.7517
TXs sent
not counted
First Active
2025-11-13
block 25,007,793
Last Active
117 days ago
block 26,596,973
Funded By
0x81e0…91e1

Net worth historyi

462 snapshots · to block 27,557,073coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchAlphaMultiBurnersolc 0.8.20+commit.a1b79de6runtime exact · creation exact
// SPDX-License-Identifier: Unlicensed

//                                                ██████   ██████      ████████ ███████  ██████ ██   ██
//                                                     ██  ██   ██        ██    ██      ██      ██   ██
//                                                   ██    ██   ███       ██    █████   ██      ███████
//                                                     ██  ██   ██        ██    ██      ██      ██   ██
//                                                ██████   ██████         ██    ███████  ██████ ██   ██

pragma solidity 0.8.20;

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

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    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, "SafeMath: multiplication overflow");
        return c;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        return c;
    }
}

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

    function decimals() external view returns (uint8);

    function symbol() external view returns (string memory);

    function name() external view returns (string memory);

    function getOwner() external view returns (address);

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

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

    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
    );
}

abstract contract Auth {
    address internal owner;
    mapping(address => bool) internal authorizations;
    address[] internal authorizedList;

    // New mapping for labels
    mapping(address => string) public authLabels;

    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );
    event AddressAuthorized(address indexed account, string label);
    event AddressRevoked(address indexed account);

    constructor(address _owner, address _authorizedAccount) {
        owner = _owner;
        authorizations[_owner] = true;
        authorizedList.push(_owner);

        authLabels[_owner] = _getAddressLabel(_owner);
        emit AddressAuthorized(_owner, authLabels[_owner]);

        if (_authorizedAccount != address(0)) {
            authorizations[_authorizedAccount] = true;
            authorizedList.push(_authorizedAccount);

            authLabels[_authorizedAccount] = _getAddressLabel(
                _authorizedAccount
            );
            emit AddressAuthorized(
                _authorizedAccount,
                authLabels[_authorizedAccount]
            );
        }
    }

    // Determine if an address is a contract or EOA
    function _getAddressLabel(
        address account
    ) internal view returns (string memory) {
        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0 ? "Contract" : "EOA";
    }

    // Authorize an address and set label automatically
    function authorize(address account) public onlyOwner {
        require(account != address(0), "Invalid address");
        require(!authorizations[account], "Already authorized");

        authorizations[account] = true;
        authorizedList.push(account);

        // Automatically label as Contract or EOA
        authLabels[account] = _getAddressLabel(account);
        emit AddressAuthorized(account, authLabels[account]);
    }

    function warningRevokeAuthorization(address account) public onlyOwner {
        require(account != address(0), "Are you Sure They Were Allowed");
        require(authorizations[account], "Never Seen the Guy");
        require(account != owner, "You Got Some Balls");

        authorizations[account] = false;

        // Remove from list
        for (uint256 i = 0; i < authorizedList.length; i++) {
            if (authorizedList[i] == account) {
                authorizedList[i] = authorizedList[authorizedList.length - 1];
                authorizedList.pop();
                break;
            }
        }

        emit AddressRevoked(account);
    }

    // Transfer ownership to a new address
    function warningTransferOwnership(
        address payable newOwner
    ) public onlyOwner {
        emit OwnershipTransferred(owner, newOwner);
        authorizations[owner] = false;
        owner = newOwner;
        authorizations[newOwner] = true;
        authorizedList.push(newOwner);
        authLabels[newOwner] = _getAddressLabel(newOwner);
    }

    modifier onlyOwner() {
        require(isOwner(msg.sender), "Not owner");
        _;
    }

    modifier authorized() {
        require(isAuthorized(msg.sender), "Stop That Tickles");
        _;
    }

    function isOwner(address account) public view returns (bool) {
        return account == owner;
    }

    function isAuthorized(address account) public view returns (bool) {
        return authorizations[account];
    }

    function getAuthorizedCount() public view returns (uint256) {
        return authorizedList.length;
    }

    // Returns authorized address and its label
    function getAuthorizedByIndex(
        uint256 index
    ) public view returns (address account, string memory label) {
        require(index < authorizedList.length, "Index out of bounds");
        account = authorizedList[index];
        label = authLabels[account];
    }
}

interface IDEXFactory {
    function createPair(
        address tokenA,
        address tokenB
    ) external returns (address pair);

    function getPair(
        address tokenA,
        address tokenB
    ) external view returns (address pair);
}

interface IDEXPair {
    function token0() external view returns (address);

    function token1() external view returns (address);

    function getReserves()
        external
        view
        returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
}

interface IDEXRouter {
    function factory() external pure returns (address);

    function WPLS() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);

    function addLiquidityETH(
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
        external
        payable
        returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;

    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable;

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;
}

abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

contract UltimateFactory is ReentrancyGuard, Auth {
    using SafeMath for uint256;
    address _token;
    struct structDistributors {
        Ultimate udistributorAddress;
        uint256 index;
        string tokenName;
        bool exists;
    }
    address WPLS = 0xA1077a294dDE1B09bB078844df40758a5D0f9a27;
    address[] public tokenAddresses; // Array to store token addresses
    mapping(uint256 => address) public indexedTokens; // Mapping to access tokens by index
    mapping(address => structDistributors) public udistributorsMapping;
    address[] public ultimatesArrayOfGifts;

    mapping(address => uint256) public distributionPercentages; // basis points

    constructor() Auth(msg.sender, address(this)) {
        _token = msg.sender;
    }

    function addUltimate(
        address _router,
        address _ERC_TOKEN
    ) external authorized returns (bool) {
        require(
            !udistributorsMapping[_ERC_TOKEN].exists,
            "You Gotta Layoff The Drinking"
        );

        IERC20 ERC_TOKEN = IERC20(_ERC_TOKEN);
        Ultimate udistributor = new Ultimate(_router, _ERC_TOKEN);

        uint256 tokenIndex = tokenAddresses.length;
        tokenAddresses.push(_ERC_TOKEN);
        indexedTokens[tokenIndex] = _ERC_TOKEN;

        ultimatesArrayOfGifts.push(_ERC_TOKEN);
        udistributorsMapping[_ERC_TOKEN].udistributorAddress = udistributor;
        udistributorsMapping[_ERC_TOKEN].index = tokenIndex;
        udistributorsMapping[_ERC_TOKEN].tokenName = ERC_TOKEN.name();
        udistributorsMapping[_ERC_TOKEN].exists = true;

        // ✅ Explicitly initialize percentage to 0
        distributionPercentages[_ERC_TOKEN] = 0;

        return true;
    }

    function setDistributionPercentage(
        address token,
        uint256 percentage
    ) external authorized {
        require(udistributorsMapping[token].exists, "Token not found");
        require(percentage <= 10000, "Cannot exceed 100%");
        distributionPercentages[token] = percentage;
    }

    function getShareholderAmount(
        address _ERC_TOKEN,
        address shareholder
    ) external view returns (uint256) {
        return
            udistributorsMapping[_ERC_TOKEN]
                .udistributorAddress
                .getShareholderAmount(shareholder);
    }

    function deleteUltimate(
        address _ERC_TOKEN
    ) external authorized returns (bool) {
        require(
            udistributorsMapping[_ERC_TOKEN].exists,
            "You Must Be Confused , Try Again"
        );

        Ultimate distributor = udistributorsMapping[_ERC_TOKEN]
            .udistributorAddress;

        // Try to recover ERC token, ignore if revert
        try distributor.recoverLostTokens(_ERC_TOKEN, msg.sender) {
            // success, do nothing
        } catch {
            // ignore errors (like "No Tokens To Recover")
        }
        // Try to recover WPLS, ignore if revert
        try distributor.recoverLostTokens(WPLS, msg.sender) {
            // success, do nothing
        } catch {
            // ignore errors
        }
        // Proceed with removal as before
        structDistributors memory deletedDistributer = udistributorsMapping[
            _ERC_TOKEN
        ];
        uint256 indexToDelete = deletedDistributer.index;

        if (indexToDelete != ultimatesArrayOfGifts.length - 1) {
            address lastAddress = ultimatesArrayOfGifts[
                ultimatesArrayOfGifts.length - 1
            ];
            ultimatesArrayOfGifts[indexToDelete] = lastAddress;
            udistributorsMapping[lastAddress].index = indexToDelete;
        }
        ultimatesArrayOfGifts.pop();

        for (uint256 i = 0; i < tokenAddresses.length; i++) {
            if (tokenAddresses[i] == _ERC_TOKEN) {
                tokenAddresses[i] = tokenAddresses[tokenAddresses.length - 1];
                tokenAddresses.pop();
                break;
            }
        }

        delete indexedTokens[deletedDistributer.index];
        delete udistributorsMapping[_ERC_TOKEN];
        delete distributionPercentages[_ERC_TOKEN];

        return true;
    }

    function getFactoryTokenDetails(
        uint256 index
    )
        external
        view
        returns (
            string memory tokenName,
            address tokenAddress,
            uint256 percentage
        )
    {
        require(index < tokenAddresses.length, "Invalid index");

        tokenAddress = indexedTokens[index];
        IERC20 token = IERC20(tokenAddress);
        tokenName = token.name();
        percentage = distributionPercentages[tokenAddress];
    }

    function getUltimatesAddresses() public view returns (address[] memory) {
        return ultimatesArrayOfGifts;
    }

    function setShare(
        address shareholder,
        uint256 amount
    ) external nonReentrant authorized {
        uint256 arrayLength = ultimatesArrayOfGifts.length;
        for (uint256 i = 0; i < arrayLength; i++) {
            udistributorsMapping[ultimatesArrayOfGifts[i]]
                .udistributorAddress
                .setShare(shareholder, amount);
        }
    }

    function process(uint256 gas) external nonReentrant authorized {
        uint256 arrayLength = ultimatesArrayOfGifts.length;
        for (uint256 i = 0; i < arrayLength; i++) {
            udistributorsMapping[ultimatesArrayOfGifts[i]]
                .udistributorAddress
                .process(gas);
        }
    }

    function deposit() external payable nonReentrant authorized {
        uint256 totalAmount = msg.value;
        uint256 arrayLength = ultimatesArrayOfGifts.length;

        require(arrayLength > 0, "No tokens available");

        uint256 totalPercentUsed = 0;
        uint256 totalAllocated = 0;
        uint256 zeroPercentCount = 0;

        // First pass: calculate how much goes to tokens with set percentages
        for (uint256 i = 0; i < arrayLength; i++) {
            address token = ultimatesArrayOfGifts[i];
            uint256 pct = distributionPercentages[token]; // 0 to 10000

            if (pct > 0) {
                uint256 amount = totalAmount.mul(pct).div(10000);
                totalAllocated += amount;
                totalPercentUsed += pct;

                udistributorsMapping[token].udistributorAddress.deposit{
                    value: amount
                }();
            } else {
                zeroPercentCount++;
            }
        }

        require(totalPercentUsed <= 10000, "Invalid distribution config");

        // Second pass: divide remainder among tokens with 0% set
        if (zeroPercentCount > 0) {
            uint256 remaining = totalAmount.sub(totalAllocated);
            uint256 perToken = remaining.div(zeroPercentCount);

            for (uint256 i = 0; i < arrayLength; i++) {
                address token = ultimatesArrayOfGifts[i];
                if (distributionPercentages[token] == 0) {
                    udistributorsMapping[token].udistributorAddress.deposit{
                        value: perToken
                    }();
                }
            }
        }
    }

    function getUltimate(address _ERC_TOKEN) public view returns (Ultimate) {
        return udistributorsMapping[_ERC_TOKEN].udistributorAddress;
    }

    function getTotalDistributers() public view returns (uint256) {
        return ultimatesArrayOfGifts.length;
    }

    function setUltimateDistributionCriteria(
        address _ERC_TOKEN,
        uint256 _minPeriod,
        uint256 _minDistribution
    ) external authorized {
        udistributorsMapping[_ERC_TOKEN]
            .udistributorAddress
            .setUltimateDistributionCriteria(_minPeriod, _minDistribution);
    }

    function recoverLostTokens(
        address _ERC_TOKEN,
        address _lostToken,
        address _destination
    ) external nonReentrant authorized {
        // Ensure the distributor exists
        require(
            udistributorsMapping[_ERC_TOKEN].exists,
            "No distributor found for this token"
        );
        // Call recoverLostTokens function on the distributor contract
        udistributorsMapping[_ERC_TOKEN].udistributorAddress.recoverLostTokens(
            _lostToken,
            _destination
        );
    }

    function getPaidDividends(
        address _ERC_TOKEN,
        address shareholder
    ) external view returns (uint256) {
        return
            udistributorsMapping[_ERC_TOKEN]
                .udistributorAddress
                .getPaidDividends(shareholder);
    }

    function getTotalPaid(address _ERC_TOKEN) external view returns (uint256) {
        return
            udistributorsMapping[_ERC_TOKEN].udistributorAddress.getTotalPaid();
    }

    function warningRecoverLostTokens(address tokenAddy) external authorized {
        require(msg.sender == owner, "You Didn't Say The Magic Word");

        // Use actual token address to recover
        if (tokenAddy == WPLS) {
            uint256 ethAmount = address(this).balance;
            require(ethAmount > 0, "I'm Broke, Go Away");
            payable(msg.sender).transfer(ethAmount);
        } else {
            // Handle ERC20 token recovery
            uint256 tokenAmount = IERC20(tokenAddy).balanceOf(address(this));
            require(tokenAmount > 0, "No Tokens To Recover");
            IERC20(tokenAddy).transfer(msg.sender, tokenAmount);
        }
    }

    //======================================================================
    // Distributor Authority
    //======================================================================

    function authorizeOnDistributor(
        address _ERC_TOKEN,
        address user
    ) external authorized {
        require(
            udistributorsMapping[_ERC_TOKEN].exists,
            "No distributor found for this token"
        );

        udistributorsMapping[_ERC_TOKEN].udistributorAddress.authorize(user);
    }

    function warningRevokeAuthorizationOnDistributor(
        address _ERC_TOKEN,
        address user
    ) external authorized {
        // Revoke the user's authorization for a specific token distributor

        require(
            udistributorsMapping[_ERC_TOKEN].exists,
            "No distributor found for this token"
        );

        udistributorsMapping[_ERC_TOKEN]
            .udistributorAddress
            .warningRevokeAuthorization(user);
    }
}

interface IUltimate {
    function setUltimateDistributionCriteria(
        uint256 _minPeriod,
        uint256 _minDistribution
    ) external;

    function recoverLostTokens(
        address _lostToken,
        address _destination
    ) external;

    function setShare(address shareholder, uint256 amount) external;

    function deposit() external payable;

    function process(uint256 gas) external;

    function getPaidDividends(
        address shareholder
    ) external view returns (uint256);

    function getTotalPaid() external view returns (uint256);
}

contract Ultimate is IUltimate, ReentrancyGuard, Auth {
    using SafeMath for uint256;
    address _token;
    struct Share {
        uint256 amount;
        uint256 totalExcluded;
        uint256 totalRealised;
    }

    address public ERC_TOKEN;

    address WPLS;
    IDEXRouter router;
    address[] public shareholders;
    mapping(address => uint256) shareholderIndexes;
    mapping(address => uint256) shareholderClaims;
    mapping(address => Share) public shares;
    uint256 public totalShares;
    uint256 public totalDividends;
    uint256 public totalDistributed;
    uint256 public dividendsPerShare;
    uint256 public dividendsPerShareAccuracyFactor = 10 ** 36;
    uint256 public minPeriod = 1 seconds;
    uint256 public minDistribution = 1 * (10 ** 5);
    uint256 currentIndex;
    bool initialized;
    modifier initialization() {
        require(!initialized);
        _;
        initialized = true;
    }

    constructor(
        address _router,
        address _ERC_TOKEN
    ) Auth(msg.sender, address(this)) {
        router = _router != address(0)
            ? IDEXRouter(_router)
            : IDEXRouter(0x165C3410fC91EF562C50559f7d2289fEbed552d9);
        _token = msg.sender;
        ERC_TOKEN = _ERC_TOKEN;
        WPLS = 0xA1077a294dDE1B09bB078844df40758a5D0f9a27;
    }

    function recoverLostTokens(
        address _lostToken,
        address _destination
    ) external override authorized {
        if (_lostToken == WPLS) {
            uint256 ethAmount = address(this).balance;
            require(ethAmount > 0, "I'm Broke, Go Away");
            payable(_destination).transfer(ethAmount);
        } else {
            uint256 tokenAmount = IERC20(_lostToken).balanceOf(address(this));
            require(tokenAmount > 0, "No Tokens To Recover");
            IERC20(_lostToken).transfer(_destination, tokenAmount);
        }
    }

    function setUltimateDistributionCriteria(
        uint256 _minPeriod,
        uint256 _minDistribution
    ) external override authorized {
        minPeriod = _minPeriod;
        minDistribution = _minDistribution;
    }

    function setShare(
        address shareholder,
        uint256 amount
    ) external override authorized {
        if (shares[shareholder].amount > 0) {
            distributeDividend(shareholder);
        }
        if (amount > 0 && shares[shareholder].amount == 0) {
            addShareholder(shareholder);
        } else if (amount == 0 && shares[shareholder].amount > 0) {
            removeShareholder(shareholder);
        }
        totalShares = totalShares.sub(shares[shareholder].amount).add(amount);
        shares[shareholder].amount = amount;
        shares[shareholder].totalExcluded = getCumulativeDividends(
            shares[shareholder].amount
        );
    }

    function deposit() external payable override nonReentrant authorized {
        require(msg.value > 0, "Must send ETH to deposit");
        if (ERC_TOKEN == WPLS) {
            totalDividends = totalDividends + msg.value;
            dividendsPerShare =
                dividendsPerShare +
                (dividendsPerShareAccuracyFactor * msg.value) / totalShares;
        } else {
            uint256 balanceBefore = IERC20(ERC_TOKEN).balanceOf(address(this));
            address[] memory path = new address[](2);
            path[0] = WPLS;
            path[1] = address(ERC_TOKEN);
            router.swapExactETHForTokensSupportingFeeOnTransferTokens{
                value: msg.value
            }(0, path, address(this), block.timestamp);
            uint256 amount = IERC20(ERC_TOKEN).balanceOf(address(this)).sub(
                balanceBefore
            );
            totalDividends = totalDividends.add(amount);
            dividendsPerShare = dividendsPerShare.add(
                dividendsPerShareAccuracyFactor.mul(amount).div(totalShares)
            );
        }
    }

    function process(uint256 gas) external override nonReentrant authorized {
        uint256 shareholderCount = shareholders.length;
        if (shareholderCount == 0) {
            return;
        }
        uint256 gasUsed = 0;
        uint256 gasLeft = gasleft();
        uint256 iterations = 0;
        while (gasUsed < gas && iterations < shareholderCount) {
            if (currentIndex >= shareholderCount) {
                currentIndex = 0;
            }
            if (shouldDistribute(shareholders[currentIndex])) {
                distributeDividend(shareholders[currentIndex]);
            }
            gasUsed = gasUsed + gasLeft - gasleft();
            gasLeft = gasleft();
            currentIndex++;
            iterations++;
        }
    }

    function shouldDistribute(
        address shareholder
    ) internal view returns (bool) {
        return
            shareholderClaims[shareholder] + minPeriod < block.timestamp &&
            getUnpaidEarnings(shareholder) > minDistribution;
    }

    function distributeDividend(address shareholder) internal {
        if (shares[shareholder].amount == 0) {
            return;
        }

        uint256 amount = getUnpaidEarnings(shareholder);
        if (amount > 0) {
            if (ERC_TOKEN == WPLS) {
                (bool success, ) = shareholder.call{value: amount}("");
                if (success) {
                    totalDistributed = totalDistributed.add(amount);
                    shareholderClaims[shareholder] = block.timestamp;
                    shares[shareholder].totalRealised = shares[shareholder]
                        .totalRealised
                        .add(amount);
                    shares[shareholder].totalExcluded = getCumulativeDividends(
                        shares[shareholder].amount
                    );
                }
            } else {
                totalDistributed = totalDistributed.add(amount);
                IERC20(ERC_TOKEN).transfer(shareholder, amount);
                shareholderClaims[shareholder] = block.timestamp;
                shares[shareholder].totalRealised = shares[shareholder]
                    .totalRealised
                    .add(amount);
                shares[shareholder].totalExcluded = getCumulativeDividends(
                    shares[shareholder].amount
                );
            }
        }
    }

    function claimDividend() external {
        distributeDividend(msg.sender);
    }

    function getUnpaidEarnings(
        address shareholder
    ) public view returns (uint256) {
        if (shares[shareholder].amount == 0) {
            return 0;
        }
        uint256 shareholderTotalDividends = getCumulativeDividends(
            shares[shareholder].amount
        );
        uint256 shareholderTotalExcluded = shares[shareholder].totalExcluded;
        if (shareholderTotalDividends <= shareholderTotalExcluded) {
            return 0;
        }
        return shareholderTotalDividends.sub(shareholderTotalExcluded);
    }

    function getCumulativeDividends(
        uint256 share
    ) internal view returns (uint256) {
        return
            share.mul(dividendsPerShare).div(dividendsPerShareAccuracyFactor);
    }

    function addShareholder(address shareholder) internal {
        shareholderIndexes[shareholder] = shareholders.length;
        shareholders.push(shareholder);
    }

    function getShareholders() external view returns (address[] memory) {
        return shareholders;
    }

    function getShareholderAmount(
        address shareholder
    ) external view returns (uint256) {
        return shares[shareholder].amount;
    }

    function removeShareholder(address shareholder) internal {
        shareholders[shareholderIndexes[shareholder]] = shareholders[
            shareholders.length - 1
        ];
        shareholderIndexes[
            shareholders[shareholders.length - 1]
        ] = shareholderIndexes[shareholder];
        shareholders.pop();
    }

    function getPaidDividends(
        address shareholder
    ) external view returns (uint256) {
        return shares[shareholder].totalRealised;
    }

    function getTotalPaid() external view returns (uint256) {
        return totalDistributed;
    }
}

interface IDividendDistributor {
    function deposit() external payable;
}

contract AlphaMultiBurner is IERC20, Auth {
    using SafeMath for uint256;

    struct LPPairInfo {
        address lpPair;
        address token0;
        address token1;
        bool isDividendExemptStatus;
        BuyTaxInfo buyTax;
        SellTaxInfo sellTax;
    }

    struct BuyTaxInfo {
        uint256 buyFee;
        uint256 buyBurnFee;
        uint256 buyTrashFee;
        uint256 totalBuyFee;
    }

    struct SellTaxInfo {
        uint256 sellFee;
        uint256 sellBurnFee;
        uint256 sellTrashFee;
        uint256 totalSellFee;
    }

    struct Share {
        address shareholder;
        uint256 amount;
        uint256 totalExcluded;
        uint256 totalRealised;
    }

    modifier swapping() {
        inSwap = true;
        _;
        inSwap = false;
    }

    address GAS = 0xA1077a294dDE1B09bB078844df40758a5D0f9a27;
    address DEAD = 0x000000000000000000000000000000000000dEaD;
    address ZERO = 0x0000000000000000000000000000000000000000;
    address BURN = 0x0000000000000000000000000000000000000369;

    string constant _name = "MoneyInTheBank";
    string constant _symbol = "MITB ";
    uint8 constant _decimals = 18;

    uint256 _totalSupply = 10_000_000 * (10 ** _decimals);
    uint256 public swapThreshold = 5_000 * 10 ** _decimals; // Amount of Tokens Sold During Swapback
    uint256 public _maxTxAmount = type(uint256).max;

    mapping(address => uint256) public _balances;
    mapping(address => mapping(address => uint256)) _allowances;

    mapping(address => bool) public isBuyFeeExempt;
    mapping(address => bool) public isSellFeeExempt;
    mapping(address => bool) public isTxLimitExempt;
    mapping(address => bool) public isDividendExempt;

    // These settings will control how SwapBack splits tokens used for SwapThreshold
    uint256 private liquidityFee = 0;
    uint256 private bot1 = 0;
    uint256 private bot2 = 0;
    uint256 private bot3 = 0;
    uint256 private rwrdFee = 0;
    uint256 private slot1Fee = 0;
    uint256 private slot2Fee = 0;
    uint256 private slot3Fee = 0;
    uint256 private slot4Fee = 0;

    uint256 public totalSwapMetric =
        liquidityFee +
            bot1 +
            bot2 +
            bot3 +
            rwrdFee +
            slot1Fee +
            slot2Fee +
            slot3Fee +
            slot4Fee;

    uint256 public transferTax = 30;

    uint256 public feeDenominator = 1000; // Using a larger denominator for precise calculations

    address public main1;
    address public main2;
    address public burn1;
    address public burn2;
    address public trash1;
    address public trash2;

    address public botLogic1;
    address public botLogic2;
    address public botLogic3;
    address public txFeeReceiver;
    address public autoLiquidityReceiver;

    // Mapping for the tax breakdown (buy and sell) for each LP pair
    mapping(address => BuyTaxInfo) lpPairBuyTaxes;
    mapping(address => SellTaxInfo) lpPairSellTaxes;
    mapping(address => LPPairInfo) lpPairInfo;
    mapping(address => LPPairInfo) lpPairTokens;
    mapping(address => bool) isLPPair;
    address[] lpPairs;
    address[] divExemptUsers;

    IDEXRouter public router;
    IDEXRouter public router2;

    // Reward Factory
    UltimateFactory udistributor;

    // Bonus Distributors
    IDividendDistributor public wdistributor;
    IDividendDistributor public xdistributor;
    IDividendDistributor public ydistributor;
    IDividendDistributor public zdistributor;

    uint256 public udistributorGas = 250000;

    bool devPrivilegesOnly = true;
    bool tradingEnabled = true;
    bool swapEnabled = false;
    bool megaSwap = false;

    bool inSwap;

    address public intermediaryToken;

    modifier whenNotPaused(address sender, address recipient) {
        require(
            !devPrivilegesOnly ||
                sender == address(router) ||
                recipient == address(router) ||
                isLPPair[recipient] ||
                isAuthorized(msg.sender),
            "Dev is working ,Please be patient"
        );
        _;
    }

    // Internal Book Keeping System for Project Token

    address[] shareholders;
    mapping(address => uint256) shareholderIndexes;
    mapping(address => Share) public shares;
    uint256 public totalShares;
    uint256 currentIndex;

    event AutoLiquify(uint256 amountGas, uint256 amountBOG);
    event LPPairCreated(address indexed token, address indexed pair);
    event LiquidityAdded(uint256 ethAmount, uint256 tokenAmount);
    event LiquidityFailed(string reason);

    constructor() Auth(msg.sender, address(this)) {
        router = IDEXRouter(0x165C3410fC91EF562C50559f7d2289fEbed552d9);
        router2 = IDEXRouter(0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02); // Pulsex V2 Router Default for Lp Creation
        _allowances[address(this)][address(router)] = type(uint256).max;
        _allowances[address(this)][address(router2)] = type(uint256).max;

        udistributor = new UltimateFactory();

        wdistributor = IDividendDistributor(wdistributor);
        xdistributor = IDividendDistributor(xdistributor);
        ydistributor = IDividendDistributor(ydistributor);
        zdistributor = IDividendDistributor(zdistributor);

        isSellFeeExempt[msg.sender] = true;
        isSellFeeExempt[address(this)] = true;
        isBuyFeeExempt[msg.sender] = true;
        isBuyFeeExempt[address(this)] = true;
        isTxLimitExempt[msg.sender] = true;
        isDividendExempt[address(this)] = true;
        isDividendExempt[DEAD] = true;
        isDividendExempt[ZERO] = true;
        isDividendExempt[BURN] = true;

        botLogic2 = msg.sender;
        botLogic1 = msg.sender;
        botLogic3 = msg.sender;
        main1 = address(this);
        main2 = address(this);
        burn1 = 0x0000000000000000000000000000000000000000;
        burn2 = 0x0000000000000000000000000000000000000000;
        trash1 = 0x000000000000000000000000000000000000dEaD;
        trash2 = 0x000000000000000000000000000000000000dEaD;
        txFeeReceiver = msg.sender;
        autoLiquidityReceiver = msg.sender;

        _balances[msg.sender] = _totalSupply;
        emit Transfer(address(0), msg.sender, _totalSupply);
    }

    receive() external payable {}

    //======================================================================
    // Basic Token Info
    //======================================================================

    function totalSupply() external view override returns (uint256) {
        return _totalSupply.sub(balanceOf(ZERO));
    }

    function decimals() external pure override returns (uint8) {
        return _decimals;
    }

    function symbol() external pure override returns (string memory) {
        return _symbol;
    }

    function name() external pure override returns (string memory) {
        return _name;
    }

    function getOwner() external view override returns (address) {
        return owner;
    }

    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    function allowance(
        address holder,
        address spender
    ) external view override returns (uint256) {
        return _allowances[holder][spender];
    }

    function approve(
        address spender,
        uint256 amount
    ) public override returns (bool) {
        _allowances[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

    function approveMax(address spender) external returns (bool) {
        return approve(spender, type(uint256).max);
    }

    function getCirculatingSupply() public view returns (uint256) {
        return
            _totalSupply.sub(balanceOf(DEAD)).sub(balanceOf(ZERO)).sub(
                balanceOf(BURN)
            );
    }

    //======================================================================
    // Distributor Authority
    //======================================================================

    function warningAuthorizeOnDistributor(
        address _ERC_TOKEN,
        address user
    ) external onlyOwner {
        udistributor.authorizeOnDistributor(_ERC_TOKEN, user);
    }

    function authorizeOnFactory(address adr) external onlyOwner {
        udistributor.authorize(adr);
    }

    function warningRevokeOnDistributor(
        address _ERC_TOKEN,
        address user
    ) external onlyOwner {
        // Revoke the user's authorization for a specific token distributor
        udistributor.warningRevokeAuthorizationOnDistributor(_ERC_TOKEN, user);
    }

    function revokeOnFactory(address adr) external onlyOwner {
        // Revoke a general factory authorization
        udistributor.warningRevokeAuthorization(adr);
    }

    //======================================================================
    //  Reward Factory Stuff
    //======================================================================

    function getRewardFactory() external view returns (UltimateFactory) {
        return udistributor;
    }

    // Everytime you add a reward token all users must
    // send themselves 1 token to be logged into the distributor
    // they dont  get rewards until they do
    function addRewardToken(
        address _dexRouter,
        address _ERC_TOKEN
    ) external authorized {
        udistributor.addUltimate(_dexRouter, _ERC_TOKEN);
    }

    function setDistributionPercentageForToken(
        address token,
        uint256 percentage
    ) external onlyOwner {
        udistributor.setDistributionPercentage(token, percentage);
    }

    function removeRewardToken(address _ERC_TOKEN) external authorized {
        udistributor.deleteUltimate(_ERC_TOKEN);
    }

    function getRewardTokenCount() public view returns (uint256) {
        return udistributor.getTotalDistributers();
    }

    function getRewardTokenDetails(
        uint256 index
    )
        external
        view
        returns (
            string memory tokenName,
            address tokenAddr,
            Ultimate distributor,
            uint256 percentage
        )
    {
        (
            string memory fetchedName,
            address fetchedAddr,
            uint256 fetchedPct
        ) = udistributor.getFactoryTokenDetails(index);

        Ultimate dist = udistributor.getUltimate(fetchedAddr);

        return (fetchedName, fetchedAddr, dist, fetchedPct);
    }

    function setUltimateDistributionCriteria(
        address _ERC_TOKEN,
        uint256 _minPeriod,
        uint256 _minDistribution
    ) external authorized {
        udistributor.setUltimateDistributionCriteria(
            _ERC_TOKEN,
            _minPeriod,
            _minDistribution
        );
    }

    function setUltimateGasSetting(uint256 gas) external authorized {
        require(gas < 750000, "Gas is greater than limit");
        udistributorGas = gas;
    }

    function warningRecoverDistributorLostTokens(
        address _ERC_TOKEN,
        address _lostToken,
        address _destination
    ) external authorized {
        udistributor.recoverLostTokens(_ERC_TOKEN, _lostToken, _destination);
    }

    //======================================================================
    // Distributor Settings
    //======================================================================

    function set_W_Distributor(address _newW) external authorized {
        wdistributor = IDividendDistributor(_newW);
    }

    function set_X_Distributor(address _newX) external authorized {
        xdistributor = IDividendDistributor(_newX);
    }

    function set_Y_Distributor(address _newY) external authorized {
        ydistributor = IDividendDistributor(_newY);
    }

    function set_Z_Distributor(address _newZ) external authorized {
        zdistributor = IDividendDistributor(_newZ);
    }

    //======================================================================
    // Liquidity Creation
    //======================================================================

    function createLaunchLPPairs(
        address tokenAddress,
        address _router
    ) external authorized {
        require(tokenAddress != address(0), "Invalid token address");
        require(_router != address(0), "Invalid router address");
        require(!swapEnabled, "Swap is enabled, cannot create new LP pair");

        IDEXFactory factory = IDEXFactory(IDEXRouter(_router).factory());

        // 📣 Check if the pair already exists
        address existingPair = factory.getPair(tokenAddress, address(this));
        require(existingPair == address(0), "Pair already exists");

        address newPair = factory.createPair(tokenAddress, address(this));
        require(newPair != address(0), "Failed to create pair");

        isDividendExempt[newPair] = true;
        divExemptUsers.push(newPair);

        IDEXPair pairContract = IDEXPair(newPair);

        // Store LP info in struct
        lpPairTokens[newPair] = LPPairInfo({
            lpPair: newPair,
            token0: pairContract.token0(),
            token1: pairContract.token1(),
            isDividendExemptStatus: true, // automatically exempt
            buyTax: BuyTaxInfo({
                buyFee: 0,
                buyBurnFee: 0,
                buyTrashFee: 0,
                totalBuyFee: 0
            }),
            sellTax: SellTaxInfo({
                sellFee: 0,
                sellBurnFee: 0,
                sellTrashFee: 0,
                totalSellFee: 0
            })
        });

        // Mark LP as active
        isLPPair[newPair] = true;
        lpPairs.push(newPair);

        lpPairBuyTaxes[newPair] = BuyTaxInfo({
            buyFee: 0,
            buyBurnFee: 0,
            buyTrashFee: 0,
            totalBuyFee: 0
        });

        lpPairSellTaxes[newPair] = SellTaxInfo({
            sellFee: 0,
            sellBurnFee: 0,
            sellTrashFee: 0,
            totalSellFee: 0
        });
    }

    // Only add V1 or V2 LP addresses , Will break if V3 is added
    // Add or remove an LP pair
    function setLPPair(address _pair, bool _status) external authorized {
        require(_pair != address(0), "Invalid pair address");

        if (_status) {
            // ✅ Adding a new LP pair
            require(!isLPPair[_pair], "Pair already added");

            IDEXPair pairContract = IDEXPair(_pair);

            // Exclude LP from dividends and reflections
            isDividendExempt[_pair] = true;
            divExemptUsers.push(_pair);

            // Initialize LP info struct
            lpPairTokens[_pair] = LPPairInfo({
                lpPair: _pair,
                token0: pairContract.token0(),
                token1: pairContract.token1(),
                isDividendExemptStatus: true,
                buyTax: BuyTaxInfo({
                    buyFee: 0,
                    buyBurnFee: 0,
                    buyTrashFee: 0,
                    totalBuyFee: 0
                }),
                sellTax: SellTaxInfo({
                    sellFee: 0,
                    sellBurnFee: 0,
                    sellTrashFee: 0,
                    totalSellFee: 0
                })
            });

            // Initialize buy/sell tax mappings
            lpPairBuyTaxes[_pair] = BuyTaxInfo({
                buyFee: 0,
                buyBurnFee: 0,
                buyTrashFee: 0,
                totalBuyFee: 0
            });
            lpPairSellTaxes[_pair] = SellTaxInfo({
                sellFee: 0,
                sellBurnFee: 0,
                sellTrashFee: 0,
                totalSellFee: 0
            });

            // Add to LP array if not already present
            bool exists = false;
            for (uint256 i = 0; i < lpPairs.length; i++) {
                if (lpPairs[i] == _pair) {
                    exists = true;
                    break;
                }
            }
            if (!exists) lpPairs.push(_pair);

            // Mark as active
            isLPPair[_pair] = true;
        } else {
            // ✅ Removing an LP pair
            require(isLPPair[_pair], "Pair not found");

            // Delete mapping and flags
            delete lpPairTokens[_pair];
            delete lpPairBuyTaxes[_pair];
            delete lpPairSellTaxes[_pair];
            isLPPair[_pair] = false;

            // Remove from LP array efficiently
            uint256 len = lpPairs.length;
            for (uint256 i = 0; i < len; i++) {
                if (lpPairs[i] == _pair) {
                    lpPairs[i] = lpPairs[len - 1]; // swap with last element
                    lpPairs.pop(); // remove last
                    break;
                }
            }
        }
    }

    function getLPPairInfo(
        uint256 index
    )
        external
        view
        returns (
            address lpPair,
            string memory token0Name,
            address token0,
            string memory token1Name,
            address token1,
            bool isDividendExemptStatus,
            uint256 buyFee,
            uint256 buyBurnFee,
            uint256 buyTrashFee,
            uint256 totalBuyFee,
            uint256 sellFee,
            uint256 sellBurnFee,
            uint256 sellTrashFee,
            uint256 totalSellFee
        )
    {
        require(index < lpPairs.length, "Index out of bounds");

        lpPair = lpPairs[index];
        LPPairInfo storage info = lpPairTokens[lpPair];

        token0 = info.token0;
        token1 = info.token1;
        token0Name = IERC20(info.token0).name();
        token1Name = IERC20(info.token1).name();
        isDividendExemptStatus = info.isDividendExemptStatus;

        // Unpack struct values
        buyFee = info.buyTax.buyFee;
        buyBurnFee = info.buyTax.buyBurnFee;
        buyTrashFee = info.buyTax.buyTrashFee;
        totalBuyFee = info.buyTax.totalBuyFee;

        sellFee = info.sellTax.sellFee;
        sellBurnFee = info.sellTax.sellBurnFee;
        sellTrashFee = info.sellTax.sellTrashFee;
        totalSellFee = info.sellTax.totalSellFee;
    }

    function getLPPairCount() external view returns (uint256) {
        return lpPairs.length;
    }

    function setLPPairTaxes(
        uint256 index,
        uint256 _buyFee,
        uint256 _buyBurnFee,
        uint256 _buyTrashFee,
        uint256 _sellFee,
        uint256 _sellBurnFee,
        uint256 _sellTrashFee
    ) external authorized {
        require(index < lpPairs.length, "Index out of bounds");
        address _pair = lpPairs[index];
        require(isLPPair[_pair], "Not a valid LP pair");

        uint256 totalBuy = _buyFee + _buyBurnFee + _buyTrashFee;
        uint256 totalSell = _sellFee + _sellBurnFee + _sellTrashFee;

        // ✅ Update only tax fields inside existing LPPairInfo
        LPPairInfo storage info = lpPairTokens[_pair];

        info.buyTax = BuyTaxInfo({
            buyFee: _buyFee,
            buyBurnFee: _buyBurnFee,
            buyTrashFee: _buyTrashFee,
            totalBuyFee: totalBuy
        });

        info.sellTax = SellTaxInfo({
            sellFee: _sellFee,
            sellBurnFee: _sellBurnFee,
            sellTrashFee: _sellTrashFee,
            totalSellFee: totalSell
        });

        // Optional: also update convenience mappings if you’re using them
        lpPairBuyTaxes[_pair] = info.buyTax;
        lpPairSellTaxes[_pair] = info.sellTax;
    }

    //======================================================================
    // Internal Project Book Keeping Functions
    //======================================================================

    function set_Manual_Share_Overide(
        address shareholder,
        uint256 amount
    ) external authorized {
        if (amount == 0 && shares[shareholder].amount > 0) {
            removeShareholder(shareholder);
        } else if (amount > 0 && shares[shareholder].amount == 0) {
            addShareholder(shareholder);
        }

        uint256 previousAmount = shares[shareholder].amount;
        shares[shareholder].amount = amount;

        totalShares = totalShares.sub(previousAmount).add(amount);
    }

    function setShare(address shareholder, uint256 amount) private {
        if (amount == 0 && shares[shareholder].amount > 0) {
            removeShareholder(shareholder);
        } else if (amount > 0 && shares[shareholder].amount == 0) {
            addShareholder(shareholder);
        }

        uint256 previousAmount = shares[shareholder].amount;
        shares[shareholder].amount = amount;

        totalShares = totalShares.sub(previousAmount).add(amount);
    }

    function addShareholder(address shareholder) private {
        shareholderIndexes[shareholder] = shareholders.length;
        shareholders.push(shareholder);

        shares[shareholder].shareholder = shareholder;
    }

    function removeShareholder(address shareholder) private {
        shareholders[shareholderIndexes[shareholder]] = shareholders[
            shareholders.length - 1
        ];
        shareholderIndexes[
            shareholders[shareholders.length - 1]
        ] = shareholderIndexes[shareholder];
        shareholders.pop();
        delete shareholderIndexes[shareholder];
    }

    function getAllShares() external view returns (Share[] memory) {
        uint256 total = shareholders.length;
        Share[] memory info = new Share[](total);

        for (uint256 i = 0; i < total; i++) {
            address holder = shareholders[i];
            Share memory shareData = shares[holder];

            // Populate the Share array with the data for each shareholder
            info[i] = Share({
                shareholder: holder,
                amount: shareData.amount,
                totalExcluded: shares[holder].totalExcluded,
                totalRealised: shares[holder].totalRealised
            });
        }

        return info;
    }

    function getShareholderCount() external view returns (uint256) {
        return shareholders.length;
    }

    //======================================================================
    // Tax Handling
    //======================================================================

    function transfer(
        address recipient,
        uint256 amount
    ) external override whenNotPaused(msg.sender, recipient) returns (bool) {
        return _transferFrom(msg.sender, recipient, amount);
    }

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external override whenNotPaused(sender, recipient) returns (bool) {
        if (_allowances[sender][msg.sender] != type(uint256).max) {
            _allowances[sender][msg.sender] = _allowances[sender][msg.sender]
                .sub(amount, "Being Dumb Must Hurt");
        }

        return _transferFrom(sender, recipient, amount);
    }

    function _transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) internal whenNotPaused(sender, recipient) returns (bool) {
        bool isSenderAuthorized = authorizations[sender];
        bool isRecipientAuthorized = authorizations[recipient];

        if (inSwap) {
            return _basicTransfer(sender, recipient, amount);
        }

        if (!isSenderAuthorized && !isRecipientAuthorized) {
            require(tradingEnabled, "Trading not open yet");
        }

        checkTxLimit(sender, amount);
        uint256 amountReceived;
        bool isSenderLPPair = isLPPair[sender];
        bool isRecipientLPPair = isLPPair[recipient];

        if (
            isSenderLPPair ||
            sender == address(router) ||
            sender == address(router2)
        ) {
            // ✅ Buy transaction (allowed for all)
            _balances[sender] = _balances[sender].sub(
                amount,
                "Insufficient Balance"
            );
            address lpPair = isSenderLPPair ? sender : address(0);
            amountReceived = shouldTakeBuyFee(sender)
                ? takeBuyFee(lpPair, amount)
                : amount;
            _balances[recipient] = _balances[recipient].add(amountReceived);
        } else if (
            isRecipientLPPair ||
            recipient == address(router) ||
            recipient == address(router2)
        ) {
            if (shouldSwapBack()) {
                swapBack();
            }

            _balances[sender] = _balances[sender].sub(
                amount,
                "Insufficient Balance"
            );
            address lpPair = isRecipientLPPair ? recipient : address(0);
            amountReceived = shouldTakeSellFee(recipient)
                ? takeSellFee(lpPair, amount)
                : amount;
            _balances[recipient] = _balances[recipient].add(amountReceived);
        } else {
            // ✅ Wallet-to-wallet transfer with fee
            _balances[sender] = _balances[sender].sub(
                amount,
                "Insufficient Balance"
            );

            uint256 feeAmount = (amount * transferTax) / feeDenominator;
            amountReceived = amount - feeAmount;

            _balances[recipient] = _balances[recipient].add(amountReceived);
            _balances[txFeeReceiver] = _balances[txFeeReceiver].add(feeAmount);

            emit Transfer(sender, txFeeReceiver, feeAmount);
        }

        if (!isDividendExempt[sender]) {
            setShare(sender, _balances[sender]);
            try udistributor.setShare(sender, _balances[sender]) {} catch {}
        } else {
            setShare(sender, 0);
            try udistributor.setShare(sender, 0) {} catch {}
        }

        if (!isDividendExempt[recipient]) {
            setShare(recipient, _balances[recipient]);
            try
                udistributor.setShare(recipient, _balances[recipient])
            {} catch {}
        } else {
            setShare(recipient, 0);
            try udistributor.setShare(recipient, 0) {} catch {}
        }

        try udistributor.process(udistributorGas) {} catch {}
        emit Transfer(sender, recipient, amountReceived);
        return true;
    }

    function _basicTransfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal whenNotPaused(sender, recipient) returns (bool) {
        _balances[sender] = _balances[sender].sub(amount, "Awful Simply Awful");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
        return true;
    }

    function takeBuyFee(
        address sender,
        uint256 amount
    ) internal returns (uint256) {
        uint256 feeAmount;
        uint256 burnAmount;
        uint256 trashAmount;

        // Retrieve the tax details for the LP pair (sender)
        BuyTaxInfo memory taxInfo = lpPairBuyTaxes[sender]; // This will get the tax info for the sender LP pair

        // Calculate the total fee by summing individual fees (using totalBuyFee for simplicity)
        uint256 totalFee = taxInfo.totalBuyFee; // This already includes all the buy fees

        // Calculate the fee components based on the retrieved tax info
        feeAmount = amount
            .mul(totalFee.sub((taxInfo.buyBurnFee).add(taxInfo.buyTrashFee)))
            .div(feeDenominator); // Using total fee for simpler calculation
        burnAmount = amount.mul(taxInfo.buyBurnFee).div(feeDenominator);
        trashAmount = amount.mul(taxInfo.buyTrashFee).div(feeDenominator);

        // Transfer the amounts to the respective addresses
        _balances[main1] = _balances[main1].add(feeAmount);
        _balances[burn1] = _balances[burn1].add(burnAmount);
        _balances[trash1] = _balances[trash1].add(trashAmount);

        emit Transfer(sender, main1, feeAmount);
        emit Transfer(sender, burn1, burnAmount);
        emit Transfer(sender, trash1, trashAmount);

        // Return the amount after deducting the fee, burn, and trash amounts
        return amount.sub(feeAmount.add(burnAmount).add(trashAmount));
    }

    function takeSellFee(
        address recipient,
        uint256 amount
    ) internal returns (uint256) {
        uint256 feeAmount;
        uint256 burnAmount;
        uint256 trashAmount;

        // Retrieve the tax details for the LP pair (recipient)
        SellTaxInfo memory taxInfo = lpPairSellTaxes[recipient]; // This will get the tax info for the recipient LP pair

        // Calculate the total fee by summing individual fees (using totalSellFee for simplicity)
        uint256 totalFee = taxInfo.totalSellFee; // This already includes all the sell fees

        // Calculate the fee components based on the retrieved tax info
        feeAmount = amount
            .mul(totalFee.sub(taxInfo.sellBurnFee).add(taxInfo.sellTrashFee))
            .div(feeDenominator); // Using total fee for simpler calculation
        burnAmount = amount.mul(taxInfo.sellBurnFee).div(feeDenominator);
        trashAmount = amount.mul(taxInfo.sellTrashFee).div(feeDenominator);

        // Transfer the amounts to the respective addresses
        _balances[main2] = _balances[main2].add(feeAmount);
        _balances[burn2] = _balances[burn2].add(burnAmount);
        _balances[trash2] = _balances[trash2].add(trashAmount);

        emit Transfer(recipient, main2, feeAmount);
        emit Transfer(recipient, burn2, burnAmount);
        emit Transfer(recipient, trash2, trashAmount);

        // Return the amount after deducting the fee, burn, and trash amounts
        return amount.sub(feeAmount.add(burnAmount).add(trashAmount));
    }

    //======================================================================
    // Internal Management of Tax
    //======================================================================

    function swapBack() private swapping {
        uint256 amountToLiquify = swapThreshold
            .mul(liquidityFee)
            .div(totalSwapMetric)
            .div(2);

        uint256 amountToSwap = swapThreshold.sub(amountToLiquify);

        address[] memory path;

        if (megaSwap) {
            path = new address[](3);
            path[0] = address(this);
            path[1] = intermediaryToken;
            path[2] = GAS;
        } else {
            path = new address[](2);
            path[0] = address(this);
            path[1] = GAS;
        }

        uint256 balanceBefore = address(this).balance;

        router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            amountToSwap,
            0,
            path,
            address(this),
            block.timestamp
        );
        uint256 amountGas = address(this).balance.sub(balanceBefore);
        uint256 totalFee = totalSwapMetric.sub(liquidityFee.div(2));

        uint256 amountGasBot1 = amountGas.mul(bot1).div(totalFee);
        uint256 amountGasBot2 = amountGas.mul(bot2).div(totalFee);
        uint256 amountGasBot3 = amountGas.mul(bot3).div(totalFee);

        uint256 amountGasMRWRD = amountGas.mul(rwrdFee).div(totalFee);

        uint256 amountGasSub1 = amountGas.mul(slot1Fee).div(totalFee);
        uint256 amountGasSub2 = amountGas.mul(slot2Fee).div(totalFee);
        uint256 amountGasSub3 = amountGas.mul(slot3Fee).div(totalFee);
        uint256 amountGasSub4 = amountGas.mul(slot4Fee).div(totalFee);

        uint256 amountGasLiquidity = amountGas
            .mul(liquidityFee)
            .div(totalFee)
            .div(2);

        if (address(udistributor) != address(0)) {
            try udistributor.deposit{value: amountGasMRWRD}() {} catch {}
        }

        if (address(wdistributor) != address(0)) {
            try wdistributor.deposit{value: amountGasSub1}() {} catch {}
        }

        if (address(xdistributor) != address(0)) {
            try xdistributor.deposit{value: amountGasSub2}() {} catch {}
        }

        if (address(ydistributor) != address(0)) {
            try ydistributor.deposit{value: amountGasSub3}() {} catch {}
        }

        if (address(zdistributor) != address(0)) {
            try zdistributor.deposit{value: amountGasSub4}() {} catch {}
        }

        payable(botLogic1).transfer(amountGasBot1);
        payable(botLogic2).transfer(amountGasBot2);
        payable(botLogic3).transfer(amountGasBot3);

        if (amountToLiquify > 0) {
            router.addLiquidityETH{value: amountGasLiquidity}(
                address(this),
                amountToLiquify,
                0,
                0,
                autoLiquidityReceiver,
                block.timestamp
            );
            emit AutoLiquify(amountGasLiquidity, amountToLiquify);
        }
    }

    //======================================================================
    // Exemptions & Checks
    //======================================================================
    function approveContractforRouter(address _address) external authorized {
        IERC20(_address).approve(address(router), type(uint256).max);
    }

    function setMegaSwap(bool _status) external authorized {
        megaSwap = _status;
    }

    function warningSetTradingEnabled(bool _status) external authorized {
        tradingEnabled = _status;
    }

    function setIntermediaryToken(address _token) external authorized {
        intermediaryToken = _token;
    }

    function shouldTakeSellFee(address sender) internal view returns (bool) {
        return !isSellFeeExempt[sender];
    }

    function shouldTakeBuyFee(address recipient) internal view returns (bool) {
        return !isBuyFeeExempt[recipient];
    }

    function setMaxTxAmount(uint256 newMaxTxAmount) external authorized {
        _maxTxAmount = newMaxTxAmount * 10 ** _decimals;
    }

    function shouldSwapBack() internal view returns (bool) {
        return
            !isLPPair[msg.sender] &&
            !inSwap &&
            swapEnabled &&
            _balances[address(this)] >= swapThreshold;
    }

    function setSwapBackSettings(
        bool _enabled,
        uint256 _amount
    ) external authorized {
        swapEnabled = _enabled;
        swapThreshold = _amount * 10 ** _decimals;
    }

    function checkTxLimit(address sender, uint256 amount) internal view {
        require(
            amount <= _maxTxAmount || isTxLimitExempt[sender],
            "TX Limit Exceeded"
        );
    }

    function setIsFeeExempt(
        address holder,
        bool sell,
        bool buy,
        bool txlimit
    ) external authorized {
        isSellFeeExempt[holder] = sell;
        isBuyFeeExempt[holder] = buy;
        isTxLimitExempt[holder] = txlimit;
    }

    function setDividendExempt(
        address account,
        bool exempt
    ) external authorized {
        if (exempt && isDividendExempt[account]) {
            revert("Address is already on the shit list");
        }

        if (!exempt && !isDividendExempt[account]) {
            revert("Address is not on the List");
        }

        if (exempt && !isDividendExempt[account]) {
            divExemptUsers.push(account);
        }

        if (!exempt && isDividendExempt[account]) {
            for (uint256 i = 0; i < divExemptUsers.length; i++) {
                if (divExemptUsers[i] == account) {
                    divExemptUsers[i] = divExemptUsers[
                        divExemptUsers.length - 1
                    ];
                    divExemptUsers.pop();
                    break;
                }
            }
        }

        isDividendExempt[account] = exempt;
        if (exempt) {
            setShare(account, 0);
            udistributor.setShare(account, 0);
        } else {
            setShare(account, _balances[account]);
            udistributor.setShare(account, _balances[account]);
        }
    }

    function getExemptUserCount() external view returns (uint256) {
        return divExemptUsers.length;
    }

    //======================================================================
    // Set Addresses and Fees
    //======================================================================

    function setTransferTax(uint256 amount) external authorized {
        transferTax = amount;
    }

    function setSwapBackMetrics(
        uint256 _liquidityFee,
        uint256 _bot1,
        uint256 _bot2,
        uint256 _bot3,
        uint256 _rwrdFee,
        uint256 _slot1Fee,
        uint256 _slot2Fee,
        uint256 _slot3Fee,
        uint256 _slot4Fee
    ) external authorized {
        liquidityFee = _liquidityFee;
        bot1 = _bot1;
        bot2 = _bot2;
        bot3 = _bot3;
        rwrdFee = _rwrdFee;
        slot1Fee = _slot1Fee;
        slot2Fee = _slot2Fee;
        slot3Fee = _slot3Fee;
        slot4Fee = _slot4Fee;
        totalSwapMetric =
            _slot1Fee +
            _slot2Fee +
            _slot3Fee +
            _slot4Fee +
            _rwrdFee +
            _bot1 +
            _bot2 +
            _bot3 +
            _liquidityFee;

        require(totalSwapMetric <= feeDenominator);
    }

    function setBotLogic1(address _botLogic1) external authorized {
        botLogic1 = _botLogic1;
    }

    function setBotLogic2(address _botLogic2) external authorized {
        botLogic2 = _botLogic2;
    }

    function setBotLogic3(address _botLogic3) external authorized {
        botLogic3 = _botLogic3;
    }

    function setMain1(address _main1) external authorized {
        main1 = _main1;
    }

    function setMain2(address _main2) external authorized {
        main2 = _main2;
    }

    function setBurn1(address _burn1) external authorized {
        burn1 = _burn1;
    }

    function setBurn2(address _burn2) external authorized {
        burn2 = _burn2;
    }

    function setTrash1(address _trash1) external authorized {
        trash1 = _trash1;
    }

    function setTrash2(address _trash2) external authorized {
        trash2 = _trash2;
    }

    function setAutoLiquidityReceiver(address _lpReceiver) external authorized {
        autoLiquidityReceiver = _lpReceiver;
    }

    function setTxReceiver(address _txReceiver) external authorized {
        txFeeReceiver = _txReceiver;
    }

    //======================================================================
    // Extra Stuff
    //======================================================================

    function warningRecoverLostTokens(address tokenAddy) external authorized {
        // Handle ETH recovery if the tokenAddress is the zero address
        // Use this address to recover GAS Token   0x0000000000000000000000000000000000000000
        // Use actual token address to recover others if needed
        if (tokenAddy == address(0)) {
            uint256 gasAmount = address(this).balance;
            require(gasAmount > 0, "I'm Broke, Go Away");
            payable(msg.sender).transfer(gasAmount);
        } else {
            uint256 tokenAmount = IERC20(tokenAddy).balanceOf(address(this));
            require(tokenAmount > 0, "No Tokens To Recover");
            IERC20(tokenAddy).transfer(msg.sender, tokenAmount);
        }
    }

    function recoverLostTokensPercentage(
        address tokenAddy,
        address _destination,
        uint256 percentage
    ) external authorized {
        require(percentage > 0 && percentage <= 100, "Invalid percentage");

        if (tokenAddy == address(0)) {
            // Handle raw gas token (native coin like ETH or WPLS)
            uint256 gasAmount = address(this).balance;
            require(gasAmount > 0, "I'm Broke, Go Away");

            uint256 amountToSend = (gasAmount * percentage) / 100;
            payable(_destination).transfer(amountToSend);
        } else {
            // Handle ERC20 tokens
            uint256 tokenAmount = IERC20(tokenAddy).balanceOf(address(this));
            require(tokenAmount > 0, "No Tokens Left All Gone");

            uint256 amountToSend = (tokenAmount * percentage) / 100;
            IERC20(tokenAddy).transfer(_destination, amountToSend);
        }
    }

    function externalMint(address to, uint256 amount) external authorized {
        require(amount > 0, "Mint amount must be greater than zero");

        _totalSupply = _totalSupply.add(amount);
        _balances[to] = _balances[to].add(amount);
        emit Transfer(address(0), to, amount);
    }

    function getTokenHoldingsInfo(
        address tokenAddress
    ) external view returns (string memory tokenName, uint256 balance) {
        IERC20 token = IERC20(tokenAddress);
        tokenName = token.name();
        balance = token.balanceOf(address(this));
        return (tokenName, balance);
    }

    //======================================================================
    // Launch Phase Functions
    //======================================================================

    // This allows the dev to buy before snipers
    // Also allows for Dev to setup V3 pools if being used
    // After making V3 go to Tx and add the LP address to mapping for Dividend Exemption
    // Do Not Use "addLPPair" use "setIsDividendExempt" and mark as true
    // does Not allow pulling on LP only Making
    function activateOnlyDevPrivileges() external authorized {
        tradingEnabled = false;
        swapEnabled = false;
        devPrivilegesOnly = false;
    }

    function activateActualTrading() external authorized {
        tradingEnabled = true;
        swapEnabled = true;
        devPrivilegesOnly = false;
    }

    function getContractStatus()
        external
        view
        returns (
            bool Dev_Privileges_On,
            bool Trading_Enabled,
            bool Swap_Enabled,
            bool Mega_Swap
        )
    {
        return (devPrivilegesOnly, tradingEnabled, swapEnabled, megaSwap);
    }
}