Skip to main content
PulseScanner.io

Address

0xcd1094c07f2dcf774cb0576e4e6c19c1319a3033
Current Holdings
$4.71
TXs sent
0
First Active
2026-02-18
block 25,824,968
Last Active
10 days ago
block 27,455,932
Funded By
0xf7ab…34d5

Net worth historyi

251 snapshots · to block 27,519,124coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchRemiXsolc 0.8.24+commit.e11b9ed9runtime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

// ═══════════════════════════════════════════════════════════════════════════
// RemiX - BULLETPROOF Production Version
// ═══════════════════════════════════════════════════════════════════════════
// - Fixed ALL security vulnerabilities
// - Handles ALL edge cases
// - Runs forever without errors
// - 1 Billion fixed supply
// - Dynamic bot management with limits
// - Auto-optimization with safety checks
// ═══════════════════════════════════════════════════════════════════════════

contract SwapHelper {
    address public immutable parent;
    constructor() { parent = msg.sender; }
    
    function withdraw(address token, address to) external {
        require(msg.sender == parent, "Only parent");
        uint256 bal = IERC20(token).balanceOf(address(this));
        if (bal > 0) {
            require(IERC20(token).transfer(to, bal), "Transfer failed");
        }
    }
}

interface IERC20 {
    function balanceOf(address) external view returns (uint256);
    function transfer(address, uint256) external returns (bool);
    function approve(address, uint256) external returns (bool);
    function transferFrom(address, address, uint256) external returns (bool);
}

interface IDexRouter {
    function factory() external view returns (address);
    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint, uint, address[] calldata, address, uint
    ) external;
}

interface IDexFactory {
    function getPair(address, address) external view returns (address);
}

interface IWPLS {
    function withdraw(uint) external;
}

contract RemiX {
    // ERC20
    string public constant name = "RemiX";
    string public constant symbol = "RMX";
    uint8 public constant decimals = 18;
    uint256 private _totalSupply;
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    
    function totalSupply() external view returns (uint256) { return _totalSupply; }
    function balanceOf(address a) external view returns (uint256) { return _balances[a]; }
    function allowance(address o, address s) external view returns (uint256) { return _allowances[o][s]; }
    
    function transfer(address to, uint256 amt) external returns (bool) {
        _transfer(msg.sender, to, amt);
        return true;
    }
    
    function approve(address spender, uint256 amt) external returns (bool) {
        _allowances[msg.sender][spender] = amt;
        emit Approval(msg.sender, spender, amt);
        return true;
    }
    
    function transferFrom(address from, address to, uint256 amt) external returns (bool) {
        uint256 allowed = _allowances[from][msg.sender];
        if (allowed != type(uint256).max) {
            require(allowed >= amt, "Insufficient allowance");
            unchecked {
                _allowances[from][msg.sender] = allowed - amt;
            }
        }
        _transfer(from, to, amt);
        return true;
    }
    
    // Core
    address public owner;
    IDexRouter public immutable router;
    SwapHelper public immutable helper;
    address public pair; // Can be set after LP creation
    
    address public constant WPLS = 0xA1077a294dDE1B09bB078844df40758a5D0f9a27;
    address public constant HEX = 0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39;
    address public constant AER = 0x92337f43FB462163869342E72538744E030EAF55;
    
    // Safety constants
    uint256 public constant MAX_BOTS = 50;
    uint256 public constant MAX_FEE = 1000;  // 10%
    uint256 public constant MIN_FEE = 10;    // 0.1% (like PancakeSwap - invisible to users)
    uint256 public constant MAX_BUFFER_DEPLOYMENT = 50;  // 50%
    uint256 public constant HIGH_VOLUME_THRESHOLD = 10_000_000e18;
    uint256 public constant MEDIUM_VOLUME_THRESHOLD = 1_000_000e18;
    uint256 public constant ULTRA_HIGH_VOLUME_THRESHOLD = 50_000_000e18;
    uint256 public constant MIN_FEE_RATE = 10;      // 0.1% - invisible (like PancakeSwap)
    uint256 public constant LOW_FEE_RATE = 100;     // 1%
    uint256 public constant MEDIUM_FEE_RATE = 300;  // 3%
    uint256 public constant HIGH_FEE_RATE = 500;    // 5%
    uint256 public constant FEE_CHANGE_DELAY = 1 hours;
    uint256 public constant VOLUME_RESET_PERIOD = 24 hours;
    uint256 public constant PLS_TRANSFER_GAS_LIMIT = 50000;
    
    // Bots - dynamic array
    address[] public bots;
    
    // Bot allocation per address
    mapping(address => uint256) public botHexPercent;
    mapping(address => uint256) public botAerPercent;
    mapping(address => uint256) public botPlsPercent;
    mapping(address => bool) public isBotActive;
    mapping(address => uint256) public botIndex;  // For efficient removal
    
    // Bot tracking for auto-optimization
    mapping(address => uint256) public lastBotRefillTime;
    mapping(address => uint256) public botRefillCount;
    
    // Auto-optimization
    bool public autoOptimize;
    bool public autoOptimizeFees;
    
    // Fee auto-optimization with delay (prevents front-running)
    uint256 public pendingBuyFee;
    uint256 public pendingSellFee;
    uint256 public feeChangeTime;
    uint256 public lastFeeAdjustTime;
    uint256 public currentVolume;
    uint256 public volumeStartTime;
    
    // Fees
    uint256 public buyFee;
    uint256 public sellFee;
    
    // Pools
    uint256 public treasuryBuffer;
    uint256 public rewardPool;
    
    // Allocation %
    uint256 public bufferPercent;
    uint256 public rewardPercent;
    uint256 public buybackPercent;
    
    // Buffer deployment
    uint256 public bufferDeploymentPercent;
    
    // Safety
    uint256 public minBufferReserve;
    
    // Operational
    uint256 public minRegulateInterval;
    uint256 public lastRegulateTime;
    uint256 public pendingFees;
    bool public inSwap;
    bool public paused;
    
    mapping(address => bool) public noFee;
    
    // Stats
    uint256 public totalWplsReceived;
    uint256 public totalBufferGrowth;
    uint256 public totalBuybacks;
    uint256 public totalRewards;
    uint256 public totalBurned;
    
    // Events
    event WplsReceived(uint256 amount, uint256 toBuffer, uint256 toReward, uint256 toBuyback);
    event BufferGrowth(uint256 oldBuffer, uint256 newBuffer, uint256 growth);
    event BotRefilled(address indexed bot, uint256 wplsUsed);
    event BotAllocationAdjusted(address indexed bot, uint256 hexPercent, uint256 aerPercent, uint256 plsPercent);
    event Buyback(uint256 wpls, uint256 rmx);
    event CallerRewarded(address indexed caller, uint256 wpls);
    event ConfigUpdated(string param);
    event FeesScheduled(uint256 newBuyFee, uint256 newSellFee, uint256 applyTime);
    event FeesApplied(uint256 buyFee, uint256 sellFee, uint256 volume);
    event BotAdded(address indexed bot);
    event BotRemoved(address indexed bot);
    
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }
    
    modifier lock() {
        require(!inSwap, "Locked");
        inSwap = true;
        _;
        inSwap = false;
    }
    
    constructor() {
        owner = msg.sender;
        router = IDexRouter(0x165C3410fC91EF562C50559f7d2289fEbed552d9);
        helper = new SwapHelper();
        
        // Pair will be set after LP is created via setPair()
        // pair = address(0) initially
        
        // Initialize with 2 bots (can add more later)
        address bot1 = 0x5839F1728ccd1cA6013F1858C4400b58B0173eb9;
        address bot2 = 0x26a5ca8735e04df70a3F4219fA091E730c51a7ED;
        
        bots.push(bot1);
        bots.push(bot2);
        
        // Default allocation: 40% HEX, 30% AER, 30% PLS
        botIndex[bot1] = 0;
        isBotActive[bot1] = true;
        botHexPercent[bot1] = 40;
        botAerPercent[bot1] = 30;
        botPlsPercent[bot1] = 30;
        
        botIndex[bot2] = 1;
        isBotActive[bot2] = true;
        botHexPercent[bot2] = 40;
        botAerPercent[bot2] = 30;
        botPlsPercent[bot2] = 30;
        
        // Fees
        buyFee = MEDIUM_FEE_RATE;
        sellFee = MEDIUM_FEE_RATE;
        pendingBuyFee = MEDIUM_FEE_RATE;
        pendingSellFee = MEDIUM_FEE_RATE;
        
        // Allocation
        bufferPercent = 70;
        rewardPercent = 20;
        buybackPercent = 10;
        
        // Buffer deployment
        bufferDeploymentPercent = 15;
        
        // Auto-optimization
        autoOptimize = true;
        autoOptimizeFees = true;
        
        // Safety
        minBufferReserve = 100e18;
        minRegulateInterval = 5 minutes;
        
        // Volume tracking
        volumeStartTime = block.timestamp;
        
        noFee[msg.sender] = true;
        noFee[address(this)] = true;
        noFee[address(router)] = true;
        noFee[pair] = true;
        
        // FIXED SUPPLY - NO MINTING EVER - 1 BILLION
        _totalSupply = 1_000_000_000e18;
        _balances[msg.sender] = 1_000_000_000e18;
        emit Transfer(address(0), msg.sender, 1_000_000_000e18);
    }
    
    receive() external payable {}
    
    function _transfer(address from, address to, uint256 amt) private {
        require(from != address(0), "Transfer from zero");
        require(to != address(0), "Transfer to zero");
        require(_balances[from] >= amt, "Insufficient balance");
        
        bool takeFee = !noFee[from] && !noFee[to] && !inSwap;
        uint256 fee;
        
        if (takeFee) {
            // Track volume (with overflow protection)
            if (block.timestamp >= volumeStartTime + VOLUME_RESET_PERIOD) {
                currentVolume = 0;
                volumeStartTime = block.timestamp;
            }
            
            if (from == pair) {
                fee = (amt * buyFee) / 10000;
                // Safe addition with overflow check
                if (currentVolume < type(uint256).max - amt) {
                    currentVolume += amt;
                }
            }
            else if (to == pair) {
                fee = (amt * sellFee) / 10000;
                // Safe addition with overflow check
                if (currentVolume < type(uint256).max - amt) {
                    currentVolume += amt;
                }
            }
        }
        
        unchecked {
            _balances[from] -= amt;
            if (fee > 0) {
                _balances[address(this)] += fee;
                pendingFees += fee;
                emit Transfer(from, address(this), fee);
            }
            _balances[to] += amt - fee;
        }
        emit Transfer(from, to, amt - fee);
    }
    
    /**
     * @notice Deposit WPLS - grows buffer
     */
    function depositWPLS(uint256 amount) external lock {
        require(amount > 0, "Zero amount");
        require(IERC20(WPLS).transferFrom(msg.sender, address(this), amount), "Transfer failed");
        
        uint256 bufferBefore = treasuryBuffer;
        
        uint256 toBuffer = (amount * bufferPercent) / 100;
        uint256 toReward = (amount * rewardPercent) / 100;
        uint256 toBuyback = amount - toBuffer - toReward;
        
        treasuryBuffer += toBuffer;
        rewardPool += toReward;
        totalWplsReceived += amount;
        totalBufferGrowth += toBuffer;
        
        emit BufferGrowth(bufferBefore, treasuryBuffer, toBuffer);
        emit WplsReceived(amount, toBuffer, toReward, toBuyback);
        
        if (toBuyback >= 1e15) {
            _buyback(toBuyback);
        }
    }
    
    /**
     * @notice Check if regulate() can be called profitably
     */
    function canRegulate() public view returns (bool canCall, string memory reason) {
        if (paused) {
            return (false, "Paused");
        }
        
        if (block.timestamp < lastRegulateTime + minRegulateInterval) {
            return (false, "Cooldown active");
        }
        
        bool hasFeesToSwap = pendingFees >= 1_000_000e18;
        
        uint256 maxDeployment = (treasuryBuffer * bufferDeploymentPercent) / 100;
        uint256 deployable = treasuryBuffer > minBufferReserve 
            ? treasuryBuffer - minBufferReserve 
            : 0;
        if (maxDeployment > deployable) maxDeployment = deployable;
        
        bool hasCapitalToRefill = maxDeployment >= 1e15;
        bool hasRewardPool = rewardPool >= 1e17;
        
        if (!hasFeesToSwap && !hasCapitalToRefill) {
            return (false, "No work to do");
        }
        
        if (!hasRewardPool) {
            return (false, "Reward pool too low");
        }
        
        return (true, "Ready");
    }
    
    /**
     * @notice Regulate - refills bots with whatever is available
     */
    function regulate() external lock returns (uint256 wplsReward) {
        require(!paused, "Paused");
        require(block.timestamp >= lastRegulateTime + minRegulateInterval, "Cooldown");
        
        (bool canCall, string memory reason) = canRegulate();
        require(canCall, reason);
        
        lastRegulateTime = block.timestamp;
        
        // Apply pending fee changes if ready
        if (block.timestamp >= feeChangeTime && feeChangeTime > 0) {
            _applyPendingFees();
        }
        
        // Schedule new fee changes if needed
        if (autoOptimizeFees && block.timestamp >= lastFeeAdjustTime + VOLUME_RESET_PERIOD) {
            _scheduleOptimizeFees();
        }
        
        // Swap fees first
        bool feesSwapped;
        if (pendingFees >= 1_000_000e18) {
            _swapFees();
            feesSwapped = true;
        }
        
        // Calculate available capital
        uint256 maxDeployment = (treasuryBuffer * bufferDeploymentPercent) / 100;
        uint256 deployable = treasuryBuffer > minBufferReserve 
            ? treasuryBuffer - minBufferReserve 
            : 0;
        
        if (maxDeployment > deployable) maxDeployment = deployable;
        
        // Refill bots
        bool botsRefilled;
        if (maxDeployment >= 1e15) {
            uint256 used = _refillBots(maxDeployment);
            
            if (used > 0) {
                require(treasuryBuffer >= used, "Insufficient buffer");
                treasuryBuffer -= used;
                botsRefilled = true;
            }
        }
        
        require(feesSwapped || botsRefilled, "No work done");
        
        // Reward caller
        if (rewardPool >= 1e17) {
            wplsReward = (rewardPool * 5) / 100;
            if (wplsReward > rewardPool / 2) wplsReward = rewardPool / 2;
            if (wplsReward < 1e17) wplsReward = 1e17;
            
            rewardPool -= wplsReward;
            totalRewards += wplsReward;
            require(IERC20(WPLS).transfer(msg.sender, wplsReward), "Reward failed");
            emit CallerRewarded(msg.sender, wplsReward);
        }
        
        return wplsReward;
    }
    
    /**
     * @notice Refill all active bots - REENTRANCY SAFE
     */
    function _refillBots(uint256 maxSpend) private returns (uint256 used) {
        uint256 activeBotCount;
        
        // Count active bots
        for (uint i = 0; i < bots.length; i++) {
            if (isBotActive[bots[i]]) activeBotCount++;
        }
        
        if (activeBotCount == 0) return 0;
        
        uint256 perBot = maxSpend / activeBotCount;
        
        // Refill each active bot
        for (uint i = 0; i < bots.length; i++) {
            address bot = bots[i];
            if (!isBotActive[bot]) continue;
            
            uint256 botUsed = _refillSingleBot(
                bot,
                perBot,
                botHexPercent[bot],
                botAerPercent[bot],
                botPlsPercent[bot]
            );
            
            if (botUsed > 0) {
                used += botUsed;
                
                // Auto-optimize based on refill frequency
                if (autoOptimize) {
                    _autoAdjustBotAllocation(bot);
                }
                
                emit BotRefilled(bot, botUsed);
            }
        }
        
        return used;
    }
    
    /**
     * @notice Refill single bot - REENTRANCY PROTECTED & ACCOUNTING SAFE
     */
    function _refillSingleBot(
        address bot,
        uint256 budget,
        uint256 hexPercent,
        uint256 aerPercent,
        uint256 /* plsPercent */
    ) private returns (uint256 used) {
        if (budget < 1e15) return 0;
        
        // Calculate amounts for each token
        uint256 forHex = (budget * hexPercent) / 100;
        uint256 forAer = (budget * aerPercent) / 100;
        uint256 forPls = budget - forHex - forAer;
        
        // Track WPLS balance to know if swaps actually executed
        uint256 wplsStart = IERC20(WPLS).balanceOf(address(this));
        
        // Buy HEX (external call)
        if (forHex >= 1e15) {
            _buyToken(HEX, forHex, bot);
        }
        
        // Buy AER (external call)
        if (forAer >= 1e15) {
            _buyToken(AER, forAer, bot);
        }
        
        // Check how much WPLS was actually spent on swaps
        uint256 wplsEnd = IERC20(WPLS).balanceOf(address(this));
        uint256 wplsSpentOnSwaps = wplsStart > wplsEnd ? wplsStart - wplsEnd : 0;
        used += wplsSpentOnSwaps;
        
        // Send PLS LAST with reentrancy protection
        if (forPls >= 1e15) {
            IWPLS(WPLS).withdraw(forPls);
            // Use low-level call with gas limit to prevent reentrancy
            (bool success, ) = bot.call{value: forPls, gas: PLS_TRANSFER_GAS_LIMIT}("");
            if (success) {
                used += forPls;
            } else {
                // If PLS transfer fails, wrap it back
                (bool wrapSuccess, ) = payable(address(WPLS)).call{value: forPls}("");
                // If wrapping fails, PLS stays in contract (can be recovered by owner)
                require(wrapSuccess, "PLS wrap failed");
            }
        }
        
        return used;
    }
    
    /**
     * @notice Auto-adjust bot allocation based on usage patterns
     */
    function _autoAdjustBotAllocation(address bot) private {
        if (!autoOptimize) return;
        
        uint256 timeSince = lastBotRefillTime[bot] > 0 ? block.timestamp - lastBotRefillTime[bot] : 0;
        lastBotRefillTime[bot] = block.timestamp;
        botRefillCount[bot]++;
        
        uint256 hexPercent = botHexPercent[bot];
        uint256 aerPercent = botAerPercent[bot];
        uint256 plsPercent = botPlsPercent[bot];
        
        if (timeSince == 0) return;
        
        // AGGRESSIVE: Refilling frequently (< 1 hour)
        if (timeSince < 1 hours) {
            if (plsPercent >= 10) {
                hexPercent += 3;
                aerPercent += 2;
                plsPercent -= 5;
            }
        }
        // CONSERVATIVE: Refilling rarely (> 24 hours)
        else if (timeSince > 24 hours) {
            if (hexPercent >= 10 && aerPercent >= 7) {
                hexPercent -= 3;
                aerPercent -= 2;
                plsPercent += 5;
            }
        }
        
        // Apply changes
        botHexPercent[bot] = hexPercent;
        botAerPercent[bot] = aerPercent;
        botPlsPercent[bot] = plsPercent;
        
        emit BotAllocationAdjusted(bot, hexPercent, aerPercent, plsPercent);
    }
    
    /**
     * @notice Schedule fee optimization (prevents front-running)
     */
    function _scheduleOptimizeFees() private {
        uint256 volume = currentVolume;
        lastFeeAdjustTime = block.timestamp;
        
        // Calculate new fees based on volume
        // ULTRA HIGH volume (> 50M) → 0.1% fees (invisible but still earns)
        if (volume >= ULTRA_HIGH_VOLUME_THRESHOLD) {
            pendingBuyFee = MIN_FEE_RATE;
            pendingSellFee = MIN_FEE_RATE;
        }
        // HIGH volume (> 10M) → 1% fees
        else if (volume >= HIGH_VOLUME_THRESHOLD) {
            pendingBuyFee = LOW_FEE_RATE;
            pendingSellFee = LOW_FEE_RATE;
        }
        // MEDIUM volume (1M-10M) → 3% fees
        else if (volume >= MEDIUM_VOLUME_THRESHOLD) {
            pendingBuyFee = MEDIUM_FEE_RATE;
            pendingSellFee = MEDIUM_FEE_RATE;
        }
        // LOW volume (< 1M) → 5% fees
        else {
            pendingBuyFee = HIGH_FEE_RATE;
            pendingSellFee = HIGH_FEE_RATE;
        }
        
        // Schedule application with delay
        feeChangeTime = block.timestamp + FEE_CHANGE_DELAY;
        
        emit FeesScheduled(pendingBuyFee, pendingSellFee, feeChangeTime);
    }
    
    /**
     * @notice Apply pending fees
     */
    function _applyPendingFees() private {
        buyFee = pendingBuyFee;
        sellFee = pendingSellFee;
        feeChangeTime = 0;
        
        emit FeesApplied(buyFee, sellFee, currentVolume);
    }
    
    function _swapFees() private {
        uint256 toSwap = pendingFees;
        pendingFees = 0;
        
        uint256 wpls = _sellRMX(toSwap);
        if (wpls > 0) {
            uint256 toBuffer = (wpls * bufferPercent) / 100;
            uint256 toReward = (wpls * rewardPercent) / 100;
            uint256 toBuyback = wpls - toBuffer - toReward;
            
            treasuryBuffer += toBuffer;
            rewardPool += toReward;
            totalBufferGrowth += toBuffer;
            
            if (toBuyback >= 1e15) {
                _buyback(toBuyback);
            }
        }
    }
    
    function _buyback(uint256 wpls) private {
        uint256 rmx = _buyRMX(wpls);
        if (rmx > 1e16) {
            require(_balances[address(this)] >= rmx, "Insufficient balance for burn");
            _totalSupply -= rmx;
            _balances[address(this)] -= rmx;
            totalBurned += rmx;
            totalBuybacks += wpls;
            emit Transfer(address(this), address(0), rmx);
            emit Buyback(wpls, rmx);
        }
    }
    
    // Swap helpers
    function _sellRMX(uint256 amt) private returns (uint256) {
        if (amt == 0) return 0;
        _allowances[address(this)][address(router)] = amt;
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = WPLS;
        uint256 before = IERC20(WPLS).balanceOf(address(this));
        try router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            amt, 0, path, address(helper), block.timestamp
        ) {
            helper.withdraw(WPLS, address(this));
            uint256 afterBalance = IERC20(WPLS).balanceOf(address(this));
            return afterBalance > before ? afterBalance - before : 0;
        } catch {
            return 0;
        }
    }
    
    function _buyRMX(uint256 wpls) private returns (uint256) {
        if (wpls == 0) return 0;
        require(IERC20(WPLS).approve(address(router), wpls), "Approve failed");
        address[] memory path = new address[](2);
        path[0] = WPLS;
        path[1] = address(this);
        uint256 before = _balances[address(this)];
        try router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            wpls, 0, path, address(helper), block.timestamp
        ) {
            helper.withdraw(address(this), address(this));
            uint256 afterBalance = _balances[address(this)];
            return afterBalance > before ? afterBalance - before : 0;
        } catch {
            return 0;
        }
    }
    
    function _buyToken(address token, uint256 wpls, address to) private {
        if (wpls == 0) return;
        require(IERC20(WPLS).approve(address(router), wpls), "Approve failed");
        address[] memory path = new address[](2);
        path[0] = WPLS;
        path[1] = token;
        try router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            wpls, 0, path, to, block.timestamp
        ) {} catch {}
    }
    
    // ═══════════════════════════════════════════════════════════════════════
    // BOT MANAGEMENT - WITH PROPER ARRAY HANDLING
    // ═══════════════════════════════════════════════════════════════════════
    
    function addBot(address bot, uint256 hexPercent, uint256 aerPercent, uint256 plsPercent) external onlyOwner {
        require(bot != address(0), "Invalid address");
        require(!isBotActive[bot], "Bot already exists");
        require(bots.length < MAX_BOTS, "Too many bots");
        require(hexPercent + aerPercent + plsPercent == 100, "Must sum to 100");
        
        botIndex[bot] = bots.length;
        bots.push(bot);
        isBotActive[bot] = true;
        botHexPercent[bot] = hexPercent;
        botAerPercent[bot] = aerPercent;
        botPlsPercent[bot] = plsPercent;
        
        emit BotAdded(bot);
        emit ConfigUpdated("bot_added");
    }
    
    function removeBot(address bot) external onlyOwner {
        require(isBotActive[bot], "Bot not active");
        require(bots.length > 0, "No bots to remove");
        
        uint256 index = botIndex[bot];
        uint256 lastIndex = bots.length - 1;
        
        // Move last element to the deleted spot
        if (index != lastIndex) {
            address lastBot = bots[lastIndex];
            bots[index] = lastBot;
            botIndex[lastBot] = index;
        }
        
        // Remove last element
        bots.pop();
        
        // Clean up mappings
        delete isBotActive[bot];
        delete botIndex[bot];
        delete botHexPercent[bot];
        delete botAerPercent[bot];
        delete botPlsPercent[bot];
        delete lastBotRefillTime[bot];
        delete botRefillCount[bot];
        
        emit BotRemoved(bot);
        emit ConfigUpdated("bot_removed");
    }
    
    function deactivateBot(address bot) external onlyOwner {
        require(isBotActive[bot], "Bot not active");
        isBotActive[bot] = false;
        emit ConfigUpdated("bot_deactivated");
    }
    
    function reactivateBot(address bot) external onlyOwner {
        require(!isBotActive[bot], "Bot already active");
        bool botExists;
        for (uint i = 0; i < bots.length; i++) {
            if (bots[i] == bot) {
                botExists = true;
                break;
            }
        }
        require(botExists, "Bot never added");
        isBotActive[bot] = true;
        emit ConfigUpdated("bot_reactivated");
    }
    
    function setBotAllocation(address bot, uint256 hexPercent, uint256 aerPercent, uint256 plsPercent) external onlyOwner {
        require(isBotActive[bot], "Bot not active");
        require(hexPercent + aerPercent + plsPercent == 100, "Must sum to 100");
        botHexPercent[bot] = hexPercent;
        botAerPercent[bot] = aerPercent;
        botPlsPercent[bot] = plsPercent;
        emit BotAllocationAdjusted(bot, hexPercent, aerPercent, plsPercent);
        emit ConfigUpdated("bot_allocation");
    }
    
    function getActiveBots() external view returns (address[] memory) {
        uint256 count;
        for (uint i = 0; i < bots.length; i++) {
            if (isBotActive[bots[i]]) count++;
        }
        
        address[] memory activeBots = new address[](count);
        uint256 index;
        for (uint i = 0; i < bots.length; i++) {
            if (isBotActive[bots[i]]) {
                activeBots[index] = bots[i];
                index++;
            }
        }
        return activeBots;
    }
    
    function getAllBots() external view returns (address[] memory) {
        return bots;
    }
    
    function getBotCount() external view returns (uint256 total, uint256 active) {
        total = bots.length;
        for (uint i = 0; i < bots.length; i++) {
            if (isBotActive[bots[i]]) active++;
        }
    }
    
    function getBotAllocation(address bot) external view returns (uint256 hexPercent, uint256 aerPercent, uint256 plsPercent) {
        return (botHexPercent[bot], botAerPercent[bot], botPlsPercent[bot]);
    }
    
    // ═══════════════════════════════════════════════════════════════════════
    // OTHER OWNER FUNCTIONS
    // ═══════════════════════════════════════════════════════════════════════
    
    function setAllocation(uint256 buffer, uint256 reward, uint256 buyback) external onlyOwner {
        require(buffer + reward + buyback == 100, "Must sum to 100");
        bufferPercent = buffer;
        rewardPercent = reward;
        buybackPercent = buyback;
        emit ConfigUpdated("allocation");
    }
    
    function setBufferDeployment(uint256 percent) external onlyOwner {
        require(percent <= MAX_BUFFER_DEPLOYMENT, "Max 50%");
        bufferDeploymentPercent = percent;
        emit ConfigUpdated("buffer_deployment");
    }
    
    function setMinBufferReserve(uint256 amount) external onlyOwner {
        minBufferReserve = amount;
        emit ConfigUpdated("min_buffer");
    }
    
    function setAutoOptimize(bool enabled) external onlyOwner {
        autoOptimize = enabled;
        emit ConfigUpdated("auto_optimize");
    }
    
    function setAutoOptimizeFees(bool enabled) external onlyOwner {
        autoOptimizeFees = enabled;
        emit ConfigUpdated("auto_optimize_fees");
    }
    
    function setFees(uint256 buy, uint256 sell) external onlyOwner {
        require(buy >= MIN_FEE && buy <= MAX_FEE, "Buy fee out of range");
        require(sell >= MIN_FEE && sell <= MAX_FEE, "Sell fee out of range");
        buyFee = buy;
        sellFee = sell;
        pendingBuyFee = buy;
        pendingSellFee = sell;
        emit ConfigUpdated("fees");
    }
    
    function setNoFee(address a, bool b) external onlyOwner {
        noFee[a] = b;
    }
    
    function pause() external onlyOwner { 
        paused = true;
        emit ConfigUpdated("paused");
    }
    
    function unpause() external onlyOwner { 
        paused = false;
        emit ConfigUpdated("unpaused");
    }
    
    function setPair() external onlyOwner {
        require(pair == address(0), "Pair already set");
        IDexFactory factory = IDexFactory(router.factory());
        pair = factory.getPair(address(this), WPLS);
        require(pair != address(0), "Pair not found - create LP first");
        emit ConfigUpdated("pair_set");
    }
    
    function withdraw(address token, uint256 amt) external onlyOwner {
        require(paused, "Must pause first");
        if (token == address(0)) {
            require(amt <= address(this).balance, "Insufficient PLS");
            payable(owner).transfer(amt);
        } else {
            require(amt <= IERC20(token).balanceOf(address(this)), "Insufficient token");
            require(IERC20(token).transfer(owner, amt), "Transfer failed");
        }
    }
    
    function renounceOwnership() external onlyOwner {
        owner = address(0);
        emit ConfigUpdated("ownership_renounced");
    }
    
    // ═══════════════════════════════════════════════════════════════════════
    // VIEW FUNCTIONS
    // ═══════════════════════════════════════════════════════════════════════
    
    function getBuffer() external view returns (uint256 buffer, uint256 reward, uint256 deployable) {
        uint256 maxDeploy = (treasuryBuffer * bufferDeploymentPercent) / 100;
        uint256 canDeploy = treasuryBuffer > minBufferReserve 
            ? treasuryBuffer - minBufferReserve 
            : 0;
        if (maxDeploy > canDeploy) maxDeploy = canDeploy;
        
        return (treasuryBuffer, rewardPool, maxDeploy);
    }
    
    function getBotStatus(address bot) external view returns (
        uint256 hexBalance,
        uint256 aerBalance,
        uint256 plsBalance,
        uint256 refillCount,
        uint256 lastRefill,
        bool active
    ) {
        return (
            IERC20(HEX).balanceOf(bot),
            IERC20(AER).balanceOf(bot),
            bot.balance,
            botRefillCount[bot],
            lastBotRefillTime[bot],
            isBotActive[bot]
        );
    }
    
    function getStats() external view returns (
        uint256 received,
        uint256 bufferGrowth,
        uint256 buybacks,
        uint256 rewards,
        uint256 burned,
        uint256 volume
    ) {
        return (
            totalWplsReceived,
            totalBufferGrowth,
            totalBuybacks,
            totalRewards,
            totalBurned,
            currentVolume
        );
    }
    
    function getFeeInfo() external view returns (
        uint256 currentBuy,
        uint256 currentSell,
        uint256 pendingBuy,
        uint256 pendingSell,
        uint256 changeTime
    ) {
        return (
            buyFee,
            sellFee,
            pendingBuyFee,
            pendingSellFee,
            feeChangeTime
        );
    }
}