Skip to main content
PulseScanner.io

Address

0x4e0d5e6e92860f7b3cebc727e1d04d875d061c4e
Current Holdings
$0.00
TXs sent
not counted
First Active
2025-10-19
block 24,797,465
Last Active
333 days ago
block 24,797,465
Funded By
not identified

Net worth historyi

No net-worth snapshots recorded yet
exact matchAlphaMultiSystem_MAX_LP_Distro_v2solc 0.8.28+commit.7893614aruntime exact · creation exact
// SPDX-License-Identifier: Unlicensed

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

pragma solidity 0.8.28;

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;

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

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

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

    // Modifier to require caller to be owner
    modifier onlyOwner() {
        require(isOwner(msg.sender), "You Aren't My Daddy");
        _;
    }

    // Modifier to require caller to be authorized
    modifier authorized() {
        require(isAuthorized(msg.sender), "You Make Me Laugh");
        _;
    }

    // Function to authorize an address
    function authorize(address account) public onlyOwner {
        require(account != address(0), "You Cant Do That , Ser");
        require(!authorizations[account], "Pay Attention Dummy");

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

    // Function to revoke authorization
    function warningRevokeAuthorization(address account) public onlyOwner {
        require(account != address(0), "What Planet Are You From");
        require(authorizations[account], "They Were Never Here");
        require(account != owner, "Oh, You Got Some Balls");

        // Set the authorization status to false
        authorizations[account] = false;

        // Remove from the authorized list (if you're tracking this in an array)
        for (uint256 i = 0; i < authorizedList.length; i++) {
            if (authorizedList[i] == account) {
                authorizedList[i] = authorizedList[authorizedList.length - 1]; // Replace with last element
                authorizedList.pop(); // Remove last element (now a duplicate)
                break;
            }
        }

        // Emit event to confirm it was revoked
        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);
    }

    // Check if an address is the contract owner
    function isOwner(address account) public view returns (bool) {
        return account == owner;
    }

    // Check if an address is authorized
    function isAuthorized(address account) public view returns (bool) {
        return authorizations[account];
    }

    // Get total number of authorized addresses
    function getAuthorizedCount() public view returns (uint256) {
        return authorizedList.length;
    }

    // See every address in the Authorized List via an index number
    function getAuthorizedAddressByIndex(
        uint256 index
    ) public view returns (address) {
        require(index < authorizedList.length, "Index out of bounds");
        return authorizedList[index];
    }
}

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;

    function quote(
        uint256 amountA,
        uint256 reserveA,
        uint256 reserveB
    ) external pure returns (uint256 amountB);

    function getAmountOut(
        uint256 amountIn,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountOut);

    function getAmountIn(
        uint256 amountOut,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountIn);

    function getAmountsOut(
        uint256 amountIn,
        address[] calldata path
    ) external view returns (uint256[] memory amounts);

    function getAmountsIn(
        uint256 amountOut,
        address[] calldata path
    ) external view returns (uint256[] memory amounts);
}

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

// Storing this here if another contract ever needs to talk to me
// remove comment out function and insert into other contract

interface IOldDistributor {
    // External functions to interact with the contract
    function setDistributionCriteria(
        uint256 _minPeriod,
        uint256 _minDistribution
    ) external;

    function setShare(address shareholder, uint256 amount) external;

    function deposit() external payable;

    function process(uint256 gas) external;

    function claimDividend() external;

    function importShares(address externalContract) external;

    function importBatchShares(
        address externalContract,
        uint256 start,
        uint256 end
    ) external;

    function exportprimaryTokens()
        external
        view
        returns (address[] memory, address[] memory);

    function getShareholderCount() external view returns (uint256);

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

    function getTotalPaid() external view returns (uint256);

    function getAllShares() external view returns (Share[] memory);

    function getSharesBatches(
        uint256 start,
        uint256 end
    ) external view returns (Share[] memory);

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

    // Struct for Shareholder data
    struct Share {
        address shareholder;
        uint256 amount;
        uint256 totalExcluded;
        uint256 totalRealised;
    }

    function inAddLiquidity() external view returns (bool);

    function getPrimaryTokenCount() external view returns (uint256);
    function getPrimaryTokenDetails(
        uint256 index
    )
        external
        view
        returns (
            string memory tokenName,
            address tokenAddress,
            uint256 sellPercentForMint,
            uint256 sellPercentForWPLS,
            address wplsReceiver,
            uint256 holdAmount
        );

    function getSecondaryTokenCount() external view returns (uint256);
    function getSecondaryTokenDetails(
        uint256 index
    )
        external
        view
        returns (
            string memory tokenName,
            address tokenAddress,
            bool sellEnabled,
            uint256 sellPercent,
            address transferReceiver,
            uint256 holdAmount
        );
}

interface IWPLS {
    function deposit() external payable;
    function withdraw(uint256) external;
    function transfer(address to, uint256 value) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}

interface MintToken is IERC20 {
    function externalMint(address to, uint256 amount) external;
}

contract AlphaMultiSystem_MAX_LP_Distro_v2 is ReentrancyGuard, Auth {
    using SafeMath for uint256;

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

    struct PrimaryToken {
        string tokenName;
        IERC20 token;
        uint256 sellPercentForMint;
        uint256 sellPercentForWPLS;
        address wplsReceiver;
        uint256 holdAmount; // ability to bankroll tokens 
    }

    struct SecondaryToken {
        string tokenName;
        IERC20 token;
        bool sellEnabled; // whether we sell some of this token
        uint256 sellPercent; // in basis points, % of balance to sell if sellEnabled
        address transferReceiver; // address to send excess if not selling
        uint256 holdAmount; // minimum balance to keep in contract
    }

    MintToken public mintToken;

    IWPLS constant WPLS = IWPLS(0xA1077a294dDE1B09bB078844df40758a5D0f9a27);

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

    address v1Router = 0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02;
    address v2Router = 0x165C3410fC91EF562C50559f7d2289fEbed552d9;

    address public autoLiquidityReceiver;

    PrimaryToken[] primaryTokens;
    mapping(address => bool) tokenExists;

    SecondaryToken[] secondaryTokens;
    mapping(address => bool) secondaryTokenExists;

    IDEXRouter public router;

    bool initialized;
    modifier initialization() {
        require(!initialized);
        _;
        initialized = true;
    }

    modifier tokenNotExists(address tokenAddress) {
        require(!tokenExists[tokenAddress], "Token already exists");
        _;
    }

    bool lpGeneratorEnabled = false;
    bool lpGeneratorBackupEnabled = false;

    bool public inAddLiquidity;

    event SecondaryTokenRemoved(address tokenAddress);

    constructor() Auth(msg.sender, address(this)) {
        router = IDEXRouter(0x165C3410fC91EF562C50559f7d2289fEbed552d9);
        mintToken = MintToken(0x0000000000000000000000000000000000000000);

        autoLiquidityReceiver = msg.sender;
    }

    receive() external payable {
        if (msg.value > 0) {
            WPLS.deposit{value: msg.value}(); // wrap into WPLS
        }
    }

    function setAutoLpReceiver(address _new) external authorized {
        autoLiquidityReceiver = _new;
    }

    function setMintToken(address _new) external authorized {
        mintToken = MintToken(_new);

        // Approve the router for max amount
        mintToken.approve(address(router), type(uint256).max);
    }

    function getTokenHoldingsInfo(
        address tokenAddress
    ) external view returns (string memory tokenName, uint256 balance) {
        if (tokenAddress == address(0)) {
            // ETH balance (address(0) is a common convention for ETH)
            tokenName = "WPLS";
            balance = address(this).balance;
        } else {
            // ERC-20 token balance
            IERC20 token = IERC20(tokenAddress);
            tokenName = token.name();
            balance = token.balanceOf(address(this));
        }
        return (tokenName, balance);
    }

    // External function to add a PrimaryToken
    function addPrimaryToken(address tokenAddress) external authorized {
        addPrimary(tokenAddress);
    }

    function addPrimary(address tokenAddress) private {
        require(tokenAddress != address(0), "Invalid token address");
        require(!tokenExists[tokenAddress], "Token already added");

        if (tokenAddress == address(WPLS)) {
            // Special handling for WPLS
            primaryTokens.push(
                PrimaryToken({
                    tokenName: "Wrapped PLS",
                    token: IERC20(address(WPLS)),
                    sellPercentForMint: 0, // default percentage for mint
                    sellPercentForWPLS: 0, // default percentage to sell for WPLS
                    wplsReceiver: address(this), // default to contract itself
                    holdAmount: 0 // NEW: default hold amount is 0
                })
            );
            tokenExists[address(WPLS)] = true;

            IERC20(address(WPLS)).approve(address(router), type(uint256).max);
        } else {
            // Generic ERC20 path
            string memory tokenName = IERC20(tokenAddress).name();
            primaryTokens.push(
                PrimaryToken({
                    tokenName: tokenName,
                    token: IERC20(tokenAddress),
                    sellPercentForMint: 0, // default percentage for mint
                    sellPercentForWPLS: 0, // default percentage to sell for WPLS
                    wplsReceiver: address(this), // default to contract itself
                    holdAmount: 0 // NEW: default hold amount is 0
                })
            );
            tokenExists[tokenAddress] = true;

            IERC20(tokenAddress).approve(address(router), type(uint256).max);
        }
    }

    function updatePrimaryTokenSellPercent(
        uint256 index,
        uint256 newPercent
    ) external authorized {
        require(index < primaryTokens.length, "Invalid index");
        require(newPercent <= 10000, "Max is 10000 (100%)");

        primaryTokens[index].sellPercentForMint = newPercent;
    }

    function updatePrimaryTokenWPLSReceiver(
        uint256 index,
        address newReceiver
    ) external authorized {
        require(index < primaryTokens.length, "Invalid index");
        require(newReceiver != address(0), "Invalid receiver address");

        primaryTokens[index].wplsReceiver = newReceiver;
    }

    function updatePrimaryTokenWPLSPercentage(
        uint256 index,
        uint256 percent
    ) external authorized {
        require(index < primaryTokens.length, "Invalid index");
        require(percent <= 10000, "Percent must be 0-10000");

        primaryTokens[index].sellPercentForWPLS = percent;
    }

    function updatePrimaryTokenHoldAmount(
        uint256 index,
        uint256 holdAmount
    ) external authorized {
        require(index < primaryTokens.length, "Invalid index");

        primaryTokens[index].holdAmount = holdAmount * 10 ** 18;
    }

    function getPrimaryTokenCount() external view returns (uint256) {
        return primaryTokens.length;
    }

    function _removePrimaryToken(uint256 index) private {
        require(index < primaryTokens.length, "Invalid index");

        address tokenAddress = address(primaryTokens[index].token);

        // Transfer remaining balance to the caller
        uint256 remainingBalance = primaryTokens[index].token.balanceOf(
            address(this)
        );
        if (remainingBalance > 0) {
            primaryTokens[index].token.transfer(msg.sender, remainingBalance);
        }

        // Remove the token from the array efficiently
        primaryTokens[index] = primaryTokens[primaryTokens.length - 1];
        primaryTokens.pop();

        // Clean up the mapping
        tokenExists[tokenAddress] = false;

        emit TokenRemoved(tokenAddress);
    }

    function removePrimaryToken(uint256 index) external authorized {
        _removePrimaryToken(index);
    }

    function removeAllPrimaryTokens() external authorized {
        for (uint256 i = primaryTokens.length; i > 0; i--) {
            _removePrimaryToken(i - 1);
        }
    }

    event TokenRemoved(address tokenAddress);

    function getPrimaryTokenDetails(
        uint256 index
    )
        external
        view
        returns (
            string memory tokenName,
            address tokenAddress,
            uint256 sellPercentForMint,
            uint256 sellPercentForWPLS,
            address wplsReceiver,
            uint256 holdAmount
        )
    {
        require(index < primaryTokens.length, "Invalid index");

        PrimaryToken storage primaryToken = primaryTokens[index];

        return (
            primaryToken.tokenName,
            address(primaryToken.token),
            primaryToken.sellPercentForMint,
            primaryToken.sellPercentForWPLS,
            primaryToken.wplsReceiver,
            primaryToken.holdAmount
        );
    }

    function addSecondaryToken(address tokenAddress) external authorized {
        addSecondary(tokenAddress);
    }

    function addSecondary(address tokenAddress) private {
        require(tokenAddress != address(0), "Invalid token address");
        require(!secondaryTokenExists[tokenAddress], "Token already added");

        string memory tokenName = IERC20(tokenAddress).name();

        IERC20(tokenAddress).approve(address(router), type(uint256).max);

        secondaryTokens.push(
            SecondaryToken({
                tokenName: tokenName,
                token: IERC20(tokenAddress),
                sellEnabled: false, // default: don't sell
                sellPercent: 10000, // default: 100% if sell enabled
                transferReceiver: tokenAddress, // default: self
                holdAmount: type(uint256).max // default: max balance
            })
        );

        secondaryTokenExists[tokenAddress] = true;
    }

    function _removeSecondaryToken(uint256 index) private {
        require(index < secondaryTokens.length, "Invalid index");

        address tokenAddress = address(secondaryTokens[index].token);

        // Transfer remaining balance of the token back to caller (if any)
        uint256 remainingBalance = secondaryTokens[index].token.balanceOf(
            address(this)
        );
        if (remainingBalance > 0) {
            secondaryTokens[index].token.transfer(msg.sender, remainingBalance);
        }

        // Swap-and-pop to keep array packed
        if (index != secondaryTokens.length - 1) {
            secondaryTokens[index] = secondaryTokens[
                secondaryTokens.length - 1
            ];
        }
        secondaryTokens.pop();

        // Clean up mapping
        secondaryTokenExists[tokenAddress] = false;

        emit SecondaryTokenRemoved(tokenAddress);
    }

    function removeSecondaryToken(uint256 index) external authorized {
        _removeSecondaryToken(index);
    }

    function removeAllSecondaryTokens() external authorized {
        for (uint256 i = secondaryTokens.length; i > 0; i--) {
            _removeSecondaryToken(i - 1);
        }
    }

    function getSecondaryTokenDetails(
        uint256 index
    )
        external
        view
        returns (
            string memory tokenName,
            address tokenAddress,
            bool sellEnabled,
            uint256 sellPercent,
            address transferReceiver,
            uint256 holdAmount
        )
    {
        require(index < secondaryTokens.length, "Invalid index");

        SecondaryToken storage sToken = secondaryTokens[index];
        return (
            sToken.tokenName,
            address(sToken.token),
            sToken.sellEnabled,
            sToken.sellPercent,
            sToken.transferReceiver,
            sToken.holdAmount
        );
    }

    function getSecondaryTokenCount() external view returns (uint256) {
        return secondaryTokens.length;
    }

    function setSecondarySellConfig(
        uint256 index,
        bool enabled,
        uint256 percent
    ) external authorized {
        require(index < secondaryTokens.length, "Invalid index");
        require(percent <= 10000, "Max 10000 (100%)");

        SecondaryToken storage sec = secondaryTokens[index];
        sec.sellEnabled = enabled;
        sec.sellPercent = percent;
    }

    function setSecondaryTransferReceiver(
        uint256 index,
        address receiver
    ) external authorized {
        require(index < secondaryTokens.length, "Invalid index");
        require(receiver != address(0), "Invalid address");
        secondaryTokens[index].transferReceiver = receiver;
    }

    function setSecondaryHoldAmount(
        uint256 index,
        uint256 amount
    ) external authorized {
        require(index < secondaryTokens.length, "Invalid index");
        secondaryTokens[index].holdAmount = amount * 10 ** 18;
    }

    // ---------------------------------------------------------------------
    // Import Data from Old LP Distro
    // ---------------------------------------------------------------------

    function importPrimaryFromOld(address oldContract) external authorized {
        IOldDistributor old = IOldDistributor(oldContract);
        uint256 count = old.getPrimaryTokenCount();

        for (uint256 i = 0; i < count; i++) {
            (
                , // skip tokenName
                address tokenAddr,
                uint256 sellMint,
                uint256 sellWPLS,
                address wplsRecv,
                uint256 holdAmount
            ) = old.getPrimaryTokenDetails(i);

            // Add token to new contract
            addPrimary(tokenAddr);

            // Set percentages, receiver, and hold amount
            uint256 index = primaryTokens.length - 1;
            primaryTokens[index].sellPercentForMint = sellMint;
            primaryTokens[index].sellPercentForWPLS = sellWPLS;
            primaryTokens[index].wplsReceiver = wplsRecv == address(0)
                ? address(this)
                : wplsRecv;
            primaryTokens[index].holdAmount = holdAmount;
        }
    }

    function importSecondaryFromOld(address oldContract) external authorized {
        IOldDistributor old = IOldDistributor(oldContract);
        uint256 count = old.getSecondaryTokenCount();

        for (uint256 i = 0; i < count; i++) {
            (
                , // skip tokenName
                address tokenAddr,
                bool sellEnabled,
                uint256 sellPercent,
                address receiver,
                uint256 holdAmount
            ) = old.getSecondaryTokenDetails(i);

            // Add token to new contract
            addSecondary(tokenAddr);

            // Set config
            uint256 index = secondaryTokens.length - 1;
            secondaryTokens[index].sellEnabled = sellEnabled;
            secondaryTokens[index].sellPercent = sellPercent;
            secondaryTokens[index].transferReceiver = receiver == address(0)
                ? address(this)
                : receiver;
            secondaryTokens[index].holdAmount = holdAmount;
        }
    }

    // ---------------------------------------------------------------------
    // Import Data from Old LP Distro End
    // ---------------------------------------------------------------------

    function recoverLostTokens(
        address _lostToken,
        address _destination
    ) external authorized nonReentrant {
        if (_lostToken == address(0)) {
            uint256 ethAmount = address(this).balance;
            require(ethAmount > 0, "No Cookies in the Jar");
            payable(_destination).transfer(ethAmount);
        } else {
            uint256 tokenAmount = IERC20(_lostToken).balanceOf(address(this));
            require(tokenAmount > 0, "No Tokens Left All Gone");
            IERC20(_lostToken).transfer(_destination, tokenAmount);
        }
    }

    function recoverLostTokensPercentage(
        address tokenAddy,
        uint256 percentage
    ) external authorized nonReentrant {
        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(msg.sender).transfer(amountToSend);
        } else {
            // Handle ERC20 tokens
            uint256 tokenAmount = IERC20(tokenAddy).balanceOf(address(this));
            require(tokenAmount > 0, "No Tokens To Recover");

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

    function recoverAllTokens(
        address _destination
    ) external authorized nonReentrant {
        uint256 ethAmount = address(this).balance;
        uint256 totalRecovered = ethAmount;

        // ✅ Recover native PLS
        if (ethAmount > 0) {
            payable(_destination).transfer(ethAmount);
        }

        // ✅ Recover all ERC20 PrimaryTokens
        for (uint256 i = 0; i < primaryTokens.length; i++) {
            PrimaryToken storage primary = primaryTokens[i];
            uint256 tokenAmount = IERC20(address(primary.token)).balanceOf(
                address(this)
            );
            if (tokenAmount > 0) {
                IERC20(address(primary.token)).transfer(
                    _destination,
                    tokenAmount
                );
                totalRecovered += tokenAmount;
            }
        }

        // ✅ Recover all ERC20 secondary tokens
        for (uint256 i = 0; i < secondaryTokens.length; i++) {
            SecondaryToken storage sec = secondaryTokens[i];
            uint256 tokenAmount = IERC20(address(sec.token)).balanceOf(
                address(this)
            );
            if (tokenAmount > 0) {
                IERC20(address(sec.token)).transfer(_destination, tokenAmount);
                totalRecovered += tokenAmount;
            }
        }

        // ✅ Recover mintToken balance
        uint256 mintTokenAmount = IERC20(address(mintToken)).balanceOf(
            address(this)
        );
        if (mintTokenAmount > 0) {
            IERC20(address(mintToken)).transfer(_destination, mintTokenAmount);
            totalRecovered += mintTokenAmount;
        }

        // ✅ Ensure something was recovered
        require(
            totalRecovered > 0,
            "Ok, Debo you already check my pockets... Chill !!!"
        );
    }

    function deposit() external payable authorized nonReentrant {
        require(msg.value > 0, "Must send PLS to deposit");

        if (inAddLiquidity) return; // recursion guard
        inAddLiquidity = true;

        // Wrap PLS
        WPLS.deposit{value: msg.value}();

        // LP generators
        if (generatorPrimed()) tokenLPGenerator();
        if (tokenBackUpGeneratorPrimed()) tokenLPGeneratorBackup();

        // Process secondary tokens
        processSecondaryTokens();

        inAddLiquidity = false;
    }

    function processSecondaryTokens() private {
        for (uint256 i = 0; i < secondaryTokens.length; i++) {
            SecondaryToken storage sec = secondaryTokens[i];
            uint256 balance = IERC20(address(sec.token)).balanceOf(
                address(this)
            );
            // Skip if nothing to process
            if (balance == 0) continue;
            // Calculate amount above holdAmount
            uint256 excess = balance > sec.holdAmount
                ? balance - sec.holdAmount
                : 0;
            if (excess == 0) continue;
            if (sec.sellEnabled && sec.sellPercent > 0) {
                // Sell the configured percentage of excess for mintToken
                uint256 sellAmount = (excess * sec.sellPercent) / 10000;
                if (sellAmount > 0) {
                    address[] memory path = new address[](2);
                    path[0] = address(sec.token);
                    path[1] = address(WPLS);
                    IERC20(address(sec.token)).approve(
                        address(router),
                        sellAmount
                    );
                    try
                        router
                            .swapExactTokensForTokensSupportingFeeOnTransferTokens(
                                sellAmount,
                                0,
                                path,
                                address(this),
                                block.timestamp
                            )
                    {} catch {}
                }
            }
            // Transfer remaining excess to receiver if set
            uint256 remaining = IERC20(address(sec.token)).balanceOf(
                address(this)
            ) - sec.holdAmount;
            if (remaining > 0 && sec.transferReceiver != address(0)) {
                IERC20(address(sec.token)).transfer(
                    sec.transferReceiver,
                    remaining
                );
            }
        }
    }

    function tokenLPGeneratorBackup() private {
        if (primaryTokens.length == 0) return;

        for (uint256 i = 0; i < primaryTokens.length; i++) {
            PrimaryToken storage primaryToken = primaryTokens[i];
            address token = address(primaryToken.token);
            if (token == address(0)) continue;

            address pair = IDEXFactory(IDEXRouter(router).factory()).getPair(
                token,
                address(this)
            );
            if (pair == address(0)) continue;

            (uint112 reserve0, uint112 reserve1, ) = IDEXPair(pair)
                .getReserves();
            (uint112 reserveToken, uint112 reserveProject) = token <
                address(this)
                ? (reserve0, reserve1)
                : (reserve1, reserve0);

            // 🔸 Handle sell portion (holdAmount respected inside)
            if (
                primaryToken.sellPercentForMint > 0 ||
                primaryToken.sellPercentForWPLS > 0
            ) {
                _processPrimaryTokenSells(primaryToken, token);
            }

            // 🔹 Respect hold amount after selling
            uint256 tokenBalance = IERC20(token).balanceOf(address(this));
            uint256 availableToken;

            // If holdAmount is set and there’s excess, use only the excess
            if (primaryToken.holdAmount > 0) {
                if (tokenBalance <= primaryToken.holdAmount) {
                    continue; // Not enough to use, skip this token entirely
                }
                availableToken = tokenBalance - primaryToken.holdAmount;
            } else {
                availableToken = tokenBalance; // No holdAmount, use full balance
            }

            // 🔹 Skip minting if availableToken is 0
            if (availableToken == 0) {
                continue;
            }

            // 🟢 STEP 2: Calculate how much project tokens to mint based on current pool ratio
            uint256 amountProject = reserveToken > 0
                ? (availableToken * reserveProject) / reserveToken
                : availableToken;

            // Mint project tokens to contract
            mintToken.externalMint(address(this), amountProject);
            if (amountProject == 0) continue;

            // Approve for router
            IERC20(address(mintToken)).approve(address(router), amountProject);
            IERC20(token).approve(address(router), availableToken);

            try
                router.addLiquidity(
                    token,
                    address(mintToken),
                    availableToken,
                    amountProject,
                    (availableToken * 75) / 100,
                    (amountProject * 75) / 100,
                    autoLiquidityReceiver,
                    block.timestamp
                )
            {} catch {
                continue;
            }
        }
    }

    function tokenLPGenerator() private {
        if (primaryTokens.length == 0) return;

        for (uint256 i = 0; i < primaryTokens.length; i++) {
            PrimaryToken storage primaryToken = primaryTokens[i];
            address token = address(primaryToken.token);
            if (token == address(0)) continue;

            address pair = IDEXFactory(IDEXRouter(router).factory()).getPair(
                token,
                address(mintToken)
            );
            if (pair == address(0)) continue;

            (uint112 reserve0, uint112 reserve1, ) = IDEXPair(pair)
                .getReserves();
            (uint112 reserveToken, uint112 reserveProject) = token <
                address(mintToken)
                ? (reserve0, reserve1)
                : (reserve1, reserve0);

            // 🔸 Handle sell portion (holdAmount respected inside)
            if (
                primaryToken.sellPercentForMint > 0 ||
                primaryToken.sellPercentForWPLS > 0
            ) {
                _processPrimaryTokenSells(primaryToken, token);
            }

            // 🔹 Respect hold amount after selling
            uint256 tokenBalance = IERC20(token).balanceOf(address(this));
            uint256 availableToken;

            if (primaryToken.holdAmount > 0) {
                if (tokenBalance <= primaryToken.holdAmount) {
                    continue; // Not enough to use, skip this token
                }
                availableToken = tokenBalance - primaryToken.holdAmount;
            } else {
                availableToken = tokenBalance; // No holdAmount, use full balance
            }

            // 🔹 Skip if nothing to use
            if (availableToken == 0) continue;

            // 🟢 STEP 2: Calculate how much project tokens to use based on current pool ratio
            uint256 projectTokenBalance = IERC20(mintToken).balanceOf(
                address(this)
            );
            if (projectTokenBalance == 0) continue;

            uint256 amountProject = reserveToken > 0
                ? (availableToken * reserveProject) / reserveToken
                : availableToken;

            if (amountProject == 0) continue;

            // Cap project token usage to contract balance
            if (amountProject > projectTokenBalance) {
                amountProject = projectTokenBalance;
                amountProject = reserveProject > 0
                    ? (amountProject * reserveToken) / reserveProject
                    : amountProject;
            }

            // Approve for router
            IERC20(address(mintToken)).approve(address(router), amountProject);
            IERC20(token).approve(address(router), availableToken);

            // Add liquidity using only availableToken and corresponding project tokens
            try
                router.addLiquidity(
                    token,
                    address(mintToken),
                    availableToken,
                    amountProject,
                    (availableToken * 75) / 100,
                    (amountProject * 75) / 100,
                    autoLiquidityReceiver,
                    block.timestamp
                )
            {} catch {
                continue;
            }
        }
    }

    function _processPrimaryTokenSells(
        PrimaryToken storage primaryToken,
        address token
    ) private {
        uint256 tokenBalance = IERC20(token).balanceOf(address(this));
        if (tokenBalance == 0) return;

        // 🔹 Respect hold amount
        if (
            primaryToken.holdAmount > 0 &&
            tokenBalance <= primaryToken.holdAmount
        ) {
            return; // nothing to sell
        }
        uint256 availableToken = tokenBalance;
        if (primaryToken.holdAmount > 0) {
            availableToken = tokenBalance - primaryToken.holdAmount;
        }

        uint256 sellAmountForMint;
        uint256 sellAmountForWPLS;

        if (primaryToken.sellPercentForMint > 0) {
            uint256 totalSellAmount = (availableToken *
                primaryToken.sellPercentForMint) / 10000;
            sellAmountForWPLS =
                (totalSellAmount * primaryToken.sellPercentForWPLS) / 10000;
            sellAmountForMint = totalSellAmount - sellAmountForWPLS;
        } else {
            sellAmountForMint = 0;
            sellAmountForWPLS =
                (availableToken * primaryToken.sellPercentForWPLS) / 10000;
        }

        // 🔹 Sell for MintToken
        if (sellAmountForMint > 0) {
            IERC20(token).approve(address(router), sellAmountForMint);
            address[] memory path = new address[](2);
            path[0] = token;
            path[1] = address(mintToken);
            try
                router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
                    sellAmountForMint,
                    0,
                    path,
                    address(this),
                    block.timestamp
                )
            {} catch {}
        }

        // 🔹 Sell for WPLS
        if (sellAmountForWPLS > 0) {
            IERC20(token).approve(address(router), sellAmountForWPLS);
            address[] memory pathWPLS = new address[](2);
            pathWPLS[0] = token;
            pathWPLS[1] = address(WPLS);
            try
                router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
                    sellAmountForWPLS,
                    0,
                    pathWPLS,
                    address(this),
                    block.timestamp
                )
            {} catch {}
            // Send WPLS to receiver if set
            uint256 wplsBalance = WPLS.balanceOf(address(this));
            if (wplsBalance > 0) {
                address receiver = primaryToken.wplsReceiver == address(0)
                    ? address(this)
                    : primaryToken.wplsReceiver;
                WPLS.transfer(receiver, wplsBalance);
            }
        }
    }

    function generatorPrimed() internal view returns (bool) {
        return lpGeneratorEnabled;
    }

    function tokenBackUpGeneratorPrimed() internal view returns (bool) {
        return lpGeneratorBackupEnabled;
    }

    function warningMainGeneratorOveride() external authorized {
        lpGeneratorEnabled = true;
        lpGeneratorBackupEnabled = false;
    }

    function warningBackupGeneratorOveride() external authorized {
        lpGeneratorEnabled = false;
        lpGeneratorBackupEnabled = true;
    }

    function warningManualGeneratorOveride(
        bool _lpStatus,
        bool _lpBackUpStatus
    ) external authorized {
        lpGeneratorEnabled = _lpStatus;
        lpGeneratorBackupEnabled = _lpBackUpStatus;
    }

    function getContractStatus()
        external
        view
        returns (bool LP_Generator_On, bool LP_Generator_Backup_on)
    {
        return (lpGeneratorEnabled, lpGeneratorBackupEnabled);
    }
}