Address
0x9e1237ab0fed052a30d7279a1b4d58d4f7b220d2Current Holdings
$311.83
TXs sent
0
First Active
2026-04-18
block 26,312,640
Last Active
today
block 27,513,363
Net worth historyi
5,000 snapshots · to block 27,521,383coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augpartial
partial matchClankersolc 0.8.26+commit.8a97fa7aruntime partial · creation partial
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
interface IRouter {
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
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);
}
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function decimals() external view returns (uint8);
function transfer(address to, uint256 amount) external returns (bool);
}
interface IPair {
function getReserves() external view returns (uint112, uint112, uint32);
function token0() external view returns (address);
function token1() external view returns (address);
}
interface IClickerSlot {
function click() external returns (uint8);
}
contract ClickerFixedLPRatio {
address public constant ROUTER = 0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02;
address public constant WPLS = 0xA1077a294dDE1B09bB078844df40758a5D0f9a27;
address public constant TOKEN_A = 0x037645963Aece8C5Beb947dA5621362c9f7dB5a6;
address public constant TOKEN_B = 0xC607606C0DC9B084D4e4458449963a975a762093;
address public constant PAIR = 0xc53f7DDf0D3429D6B602a060Ae6241617225b396;
address public owner;
bool public enabled = true;
address public watchedAccount = 0xe64628a65aD7611a99ca994CCC498e4f515768eE;
uint256 public plsThreshold = 1 ether;
// WPLS per 1 TOKEN_A, scaled to 1e18.
uint256 public targetRatio = 1 ether;
// TOKEN_B per 1 TOKEN_A, scaled to 1e18.
uint256 public constant FIXED_LP_RATIO = 1618154261642834;
uint256 public boostFloorRatio = 1 ether;
uint256 public minBoost = 1 ether;
uint256 public maxBoost = 2 ether;
uint256 public lpAddsPerSweep = 6;
uint256 public lpAddCount;
uint256 public lastSweepAt;
uint256 public minTokenBForBuy = 1e6;
uint256 public buyDivider = 99999;
uint256 public minTokenAForLP = 1e6;
uint256 public lpDivider = 10;
uint256 private _unlocked = 1;
IRouter private constant router = IRouter(ROUTER);
IERC20 private constant tokenA = IERC20(TOKEN_A);
IERC20 private constant tokenB = IERC20(TOKEN_B);
IPair private constant ratioPair = IPair(PAIR);
enum Step {
SKIP_DISABLED,
SKIP_THRESHOLD,
WAIT,
BUY,
ADD_LP
}
Step public lastStep;
uint8 private immutable TOKEN_A_DECIMALS;
uint8 private immutable TOKEN_B_DECIMALS;
event NativeFunded(address indexed sender, uint256 amount);
event ClickGateChecked(
address indexed caller,
address indexed watchedAccount,
uint256 watchedBalance,
uint256 threshold,
bool passed
);
event ClickAction(
address indexed caller,
string action,
uint256 ratio,
uint256 amountAUsed,
uint256 amountBUsed,
uint256 buyInputUsed
);
event SweepReady(uint256 lpCount, uint256 remainingA, uint256 remainingB, uint256 remainingPLS);
event Note(string message, uint256 value);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
modifier lock() {
require(_unlocked == 1, "LOCKED");
_unlocked = 0;
_;
_unlocked = 1;
}
constructor() {
owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
uint8 a = 18;
uint8 b = 18;
try IERC20(TOKEN_A).decimals() returns (uint8 da) {
a = da;
} catch {}
try IERC20(TOKEN_B).decimals() returns (uint8 db) {
b = db;
} catch {}
TOKEN_A_DECIMALS = a;
TOKEN_B_DECIMALS = b;
}
function fund() external payable lock {
require(msg.value > 0, "No PLS sent");
emit NativeFunded(msg.sender, msg.value);
}
function watchedPlsBalance() public view returns (uint256) {
return watchedAccount.balance;
}
function gatePassed() public view returns (bool) {
return enabled && watchedAccount.balance >= plsThreshold;
}
function click() public lock returns (uint8) {
if (!enabled) {
lastStep = Step.SKIP_DISABLED;
emit ClickGateChecked(msg.sender, watchedAccount, watchedAccount.balance, plsThreshold, false);
emit ClickAction(msg.sender, "DISABLED", 0, 0, 0, 0);
return uint8(lastStep);
}
uint256 watchedBalance = watchedAccount.balance;
bool thresholdPassed = watchedBalance >= plsThreshold;
emit ClickGateChecked(msg.sender, watchedAccount, watchedBalance, plsThreshold, thresholdPassed);
uint256 ratio = getRatio();
if (ratio == 0) {
lastStep = Step.WAIT;
emit ClickAction(msg.sender, "NO_RATIO", 0, 0, 0, 0);
return uint8(lastStep);
}
// If watched PLS is below threshold, always buy.
if (!thresholdPassed) {
uint256 boostBelowThreshold = _computeBoostMultiplier(ratio);
if (_buy(ratio, boostBelowThreshold)) {
lastStep = Step.BUY;
} else {
lastStep = Step.WAIT;
}
return uint8(lastStep);
}
// LP is only allowed when both conditions are true:
// 1) watched PLS is at/above threshold
// 2) ratio is above target
if (ratio > targetRatio) {
if (_addLiquidityFixedRatio(ratio)) {
lastStep = Step.ADD_LP;
} else {
lastStep = Step.WAIT;
}
return uint8(lastStep);
}
lastStep = Step.WAIT;
emit ClickAction(msg.sender, "WAIT", ratio, 0, 0, 0);
return uint8(lastStep);
}
function getRatio() public view returns (uint256) {
(uint112 r0, uint112 r1,) = ratioPair.getReserves();
address t0 = ratioPair.token0();
uint256 reserveTokenA;
uint256 reserveWPLS;
if (t0 == TOKEN_A) {
reserveTokenA = uint256(r0);
reserveWPLS = uint256(r1);
} else {
reserveTokenA = uint256(r1);
reserveWPLS = uint256(r0);
}
if (reserveTokenA == 0) return 0;
uint256 tokenA18 = _to18(reserveTokenA, TOKEN_A_DECIMALS);
return (reserveWPLS * 1e18) / tokenA18;
}
function getFixedLPRatio() external pure returns (uint256) {
return FIXED_LP_RATIO;
}
function _buy(uint256 ratio, uint256 boost) internal returns (bool) {
uint256 balB = tokenB.balanceOf(address(this));
if (balB <= minTokenBForBuy) {
emit Note("Not enough TOKEN_B for buy", balB);
return false;
}
uint256 base = balB / buyDivider;
if (base == 0) {
emit Note("Base buy is zero", balB);
return false;
}
uint256 amountIn = (base * boost) / 1e18;
if (amountIn > balB) amountIn = balB;
if (amountIn == 0) {
emit Note("Boosted buy is zero", 0);
return false;
}
tokenB.approve(ROUTER, type(uint256).max);
address[] memory path = new address[](3);
path[0] = TOKEN_B;
path[1] = WPLS;
path[2] = TOKEN_A;
router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amountIn,
0,
path,
address(this),
block.timestamp + 900
);
emit ClickAction(msg.sender, "BUY", ratio, 0, 0, amountIn);
return true;
}
function _addLiquidityFixedRatio(uint256 policyRatio) internal returns (bool) {
uint256 balA = tokenA.balanceOf(address(this));
uint256 balB = tokenB.balanceOf(address(this));
if (balA <= minTokenAForLP || balB == 0) {
emit Note("Insufficient balances for LP", balA);
return false;
}
uint256 matchedA = _matchedTokenAForBalancesFixedRatio(FIXED_LP_RATIO, balA, balB);
if (matchedA == 0) {
emit Note("Matched TOKEN_A is zero", 0);
return false;
}
uint256 amountA = matchedA / lpDivider;
if (amountA == 0) amountA = matchedA;
if (amountA > balA) amountA = balA;
uint256 amountA18 = _to18(amountA, TOKEN_A_DECIMALS);
uint256 amountB18 = (amountA18 * FIXED_LP_RATIO) / 1e18;
uint256 amountB = _from18(amountB18, TOKEN_B_DECIMALS);
if (amountB > balB) {
amountB = balB;
uint256 amountB18Adjusted = _to18(amountB, TOKEN_B_DECIMALS);
uint256 amountA18Adjusted = (amountB18Adjusted * 1e18) / FIXED_LP_RATIO;
amountA = _from18(amountA18Adjusted, TOKEN_A_DECIMALS);
}
if (amountA == 0 || amountB == 0) {
emit Note("LP desired amount is zero", 0);
return false;
}
tokenA.approve(ROUTER, type(uint256).max);
tokenB.approve(ROUTER, type(uint256).max);
router.addLiquidity(
TOKEN_A,
TOKEN_B,
amountA,
amountB,
0,
0,
address(this),
block.timestamp + 900
);
lpAddCount += 1;
emit ClickAction(msg.sender, "ADD_LP", policyRatio, amountA, amountB, 0);
if (lpAddsPerSweep > 0 && (lpAddCount % lpAddsPerSweep == 0)) {
lastSweepAt = block.timestamp;
emit SweepReady(
lpAddCount,
tokenA.balanceOf(address(this)),
tokenB.balanceOf(address(this)),
address(this).balance
);
}
return true;
}
function _matchedTokenAForBalancesFixedRatio(
uint256 fixedRatio,
uint256 balA,
uint256 balB
) internal view returns (uint256) {
if (fixedRatio == 0 || balA == 0 || balB == 0) return 0;
uint256 balB18 = _to18(balB, TOKEN_B_DECIMALS);
uint256 maxA18FromB = (balB18 * 1e18) / fixedRatio;
uint256 maxAFromB = _from18(maxA18FromB, TOKEN_A_DECIMALS);
return balA < maxAFromB ? balA : maxAFromB;
}
function _computeBoostMultiplier(uint256 currentRatio) internal view returns (uint256) {
if (currentRatio >= boostFloorRatio) return 1 ether;
uint256 below = boostFloorRatio - currentRatio;
uint256 frac = (below * 1e18) / boostFloorRatio;
uint256 delta = maxBoost - minBoost;
uint256 boost = minBoost + ((delta * frac) / 1e18);
if (boost < minBoost) return minBoost;
if (boost > maxBoost) return maxBoost;
return boost;
}
function _pow10(uint8 n) internal pure returns (uint256) {
return 10 ** uint256(n);
}
function _to18(uint256 amount, uint8 decimals_) internal pure returns (uint256) {
if (decimals_ == 18) return amount;
if (decimals_ < 18) return amount * _pow10(18 - decimals_);
return amount / _pow10(decimals_ - 18);
}
function _from18(uint256 amount18, uint8 decimals_) internal pure returns (uint256) {
if (decimals_ == 18) return amount18;
if (decimals_ < 18) return amount18 / _pow10(18 - decimals_);
return amount18 * _pow10(decimals_ - 18);
}
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "zero addr");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
function setEnabled(bool newEnabled) external onlyOwner {
enabled = newEnabled;
}
function setWatchedAccount(address newWatchedAccount) external onlyOwner {
require(newWatchedAccount != address(0), "zero addr");
watchedAccount = newWatchedAccount;
}
function setPlsThreshold(uint256 newThreshold) external onlyOwner {
plsThreshold = newThreshold;
}
function setTargetRatio(uint256 newRatio) external onlyOwner {
targetRatio = newRatio;
}
function setBoostRange(
uint256 newFloorRatio,
uint256 newMinBoost,
uint256 newMaxBoost
) external onlyOwner {
require(newFloorRatio > 0, "floor 0");
require(newMinBoost <= newMaxBoost, "min > max");
boostFloorRatio = newFloorRatio;
minBoost = newMinBoost;
maxBoost = newMaxBoost;
}
function setLpAddsPerSweep(uint256 newCount) external onlyOwner {
lpAddsPerSweep = newCount;
}
function setBuyDivider(uint256 newDivider) external onlyOwner {
require(newDivider > 0, "divider 0");
buyDivider = newDivider;
}
function setMinTokenBForBuy(uint256 newMin) external onlyOwner {
minTokenBForBuy = newMin;
}
function setMinTokenAForLP(uint256 newMin) external onlyOwner {
minTokenAForLP = newMin;
}
function setLPDivider(uint256 newDivider) external onlyOwner {
require(newDivider > 0, "divider 0");
lpDivider = newDivider;
}
function recoverPLS(address payable to, uint256 amount) external onlyOwner {
require(to != address(0), "zero addr");
if (amount == 0) amount = address(this).balance;
(bool ok,) = to.call{value: amount}("");
require(ok, "transfer failed");
}
function recoverToken(address tokenAddr, address to, uint256 amount) external onlyOwner {
require(to != address(0), "zero addr");
IERC20 t = IERC20(tokenAddr);
if (amount == 0) amount = t.balanceOf(address(this));
require(t.transfer(to, amount), "token transfer failed");
}
receive() external payable {}
fallback() external payable {}
}
contract Clanker {
struct Slot {
address clicker;
bool active;
}
address public owner;
Slot[] private _slots;
mapping(address => uint256) public lastClankAt;
uint256 public callerCooldown = 60;
uint256 public rebateBps = 10100; // 100% estimated cost + 1% extra.
uint256 public gasOverhead = 40000; // Buffer for tx/frame costs not fully visible to gasleft().
bool public rebatesEnabled = true;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event SlotSet(uint256 indexed slotId, address indexed clicker, bool active);
event SlotCleared(uint256 indexed slotId);
event SlotActiveChanged(uint256 indexed slotId, bool active);
event SlotClicked(uint256 indexed slotId, address indexed clicker, uint8 code);
event SlotClickFailed(uint256 indexed slotId, address indexed clicker, string reason);
event SlotClickFailedLowLevel(uint256 indexed slotId, address indexed clicker, bytes data);
event Clanked(address indexed caller, uint256 start, uint256 end, uint256 attempted, uint256 succeeded);
event NativeFunded(address indexed sender, uint256 amount);
event RebatePaid(
address indexed caller,
uint256 gasUsed,
uint256 gasPrice,
uint256 estimatedCost,
uint256 rebatePaid
);
event RebateSkipped(address indexed caller, uint256 gasUsed, uint256 gasPrice, uint256 estimatedCost);
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
constructor() {
owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
}
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "zero addr");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
function fund() external payable {
require(msg.value > 0, "No PLS sent");
emit NativeFunded(msg.sender, msg.value);
}
function slotCount() external view returns (uint256) {
return _slots.length;
}
function getSlot(uint256 slotId) external view returns (address clicker, bool active) {
require(slotId < _slots.length, "slot oob");
Slot memory s = _slots[slotId];
return (s.clicker, s.active);
}
function setSlot(uint256 slotId, address clicker, bool active) external onlyOwner {
require(clicker != address(0), "zero clicker");
if (slotId == _slots.length) {
_slots.push(Slot({clicker: clicker, active: active}));
} else {
require(slotId < _slots.length, "slot oob");
_slots[slotId] = Slot({clicker: clicker, active: active});
}
emit SlotSet(slotId, clicker, active);
}
function setSlotActive(uint256 slotId, bool active) external onlyOwner {
require(slotId < _slots.length, "slot oob");
_slots[slotId].active = active;
emit SlotActiveChanged(slotId, active);
}
function clearSlot(uint256 slotId) external onlyOwner {
require(slotId < _slots.length, "slot oob");
_slots[slotId] = Slot({clicker: address(0), active: false});
emit SlotCleared(slotId);
}
function setCallerCooldown(uint256 newCooldown) external onlyOwner {
callerCooldown = newCooldown;
}
function setRebateBps(uint256 newBps) external onlyOwner {
require(newBps <= 20000, "bps too high");
rebateBps = newBps;
}
function setGasOverhead(uint256 newGasOverhead) external onlyOwner {
gasOverhead = newGasOverhead;
}
function setRebatesEnabled(bool newEnabled) external onlyOwner {
rebatesEnabled = newEnabled;
}
function recoverPLS(address payable to, uint256 amount) external onlyOwner {
require(to != address(0), "zero addr");
if (amount == 0) amount = address(this).balance;
(bool ok,) = to.call{value: amount}("");
require(ok, "transfer failed");
}
function nextClankTime(address caller) external view returns (uint256) {
return lastClankAt[caller] + callerCooldown;
}
function clank() external returns (uint256 attempted, uint256 succeeded) {
return _clankRange(0, _slots.length);
}
function clankRange(uint256 start, uint256 end) external returns (uint256 attempted, uint256 succeeded) {
return _clankRange(start, end);
}
function _clankRange(uint256 start, uint256 end) internal returns (uint256 attempted, uint256 succeeded) {
require(start <= end, "bad range");
require(end <= _slots.length, "end oob");
uint256 lastAt = lastClankAt[msg.sender];
require(block.timestamp >= lastAt + callerCooldown, "caller cooldown");
lastClankAt[msg.sender] = block.timestamp;
uint256 gasStart = gasleft();
for (uint256 i = start; i < end; i++) {
Slot memory s = _slots[i];
if (!s.active || s.clicker == address(0)) {
continue;
}
attempted += 1;
try IClickerSlot(s.clicker).click() returns (uint8 code) {
succeeded += 1;
emit SlotClicked(i, s.clicker, code);
} catch Error(string memory reason) {
emit SlotClickFailed(i, s.clicker, reason);
} catch (bytes memory data) {
emit SlotClickFailedLowLevel(i, s.clicker, data);
}
}
emit Clanked(msg.sender, start, end, attempted, succeeded);
_payRebate(msg.sender, gasStart);
}
function _payRebate(address caller, uint256 gasStart) internal {
uint256 gasUsed = (gasStart - gasleft()) + gasOverhead;
uint256 estimatedCost = gasUsed * tx.gasprice;
if (!rebatesEnabled || estimatedCost == 0) {
emit RebateSkipped(caller, gasUsed, tx.gasprice, estimatedCost);
return;
}
uint256 rebateAmount = (estimatedCost * rebateBps) / 10000;
uint256 balance = address(this).balance;
if (rebateAmount == 0 || balance == 0) {
emit RebateSkipped(caller, gasUsed, tx.gasprice, estimatedCost);
return;
}
if (rebateAmount > balance) {
rebateAmount = balance;
}
(bool ok,) = payable(caller).call{value: rebateAmount}("");
if (!ok) {
emit RebateSkipped(caller, gasUsed, tx.gasprice, estimatedCost);
return;
}
emit RebatePaid(caller, gasUsed, tx.gasprice, estimatedCost, rebateAmount);
}
receive() external payable {
emit NativeFunded(msg.sender, msg.value);
}
fallback() external payable {
if (msg.value > 0) {
emit NativeFunded(msg.sender, msg.value);
}
}
}