Address
0xcd1094c07f2dcf774cb0576e4e6c19c1319a3033Current Holdings
$4.71
TXs sent
0
First Active
2026-02-18
block 25,824,968
Last Active
10 days ago
block 27,455,932
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
);
}
}