Address
0x4e1a5ad0716d5aed378bcee9daf5a08aba3f637dCurrent Holdings
$36.25
TXs sent
not counted
First Active
2026-04-17
block 26,306,857
Last Active
40 days ago
block 27,250,605
Net worth historyi
3,104 snapshots · to block 27,505,725coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
partial matchNeonLiquidityAddersolc 0.8.31+commit.fd3a2265runtime partial · creation partial
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
interface IERC20_NLA {
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
}
interface IWPLS_NLA {
function deposit() external payable;
function balanceOf(address account) external view returns (uint256);
}
interface IPulseXRouter {
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);
function factory() external view returns (address);
}
interface IPulseXFactory {
function getPair(address tokenA, address tokenB) external view returns (address);
}
/**
* @title NeonLiquidityAdder
* @notice Receives PLS from token tax processing. Every Nth deposit auto-triggers
* LP addition to a single configurable pair on PulseX V2.
* Owner can change the pair, trigger frequency, and withdraw anything.
*/
contract NeonLiquidityAdder {
address public owner;
address public immutable WPLS;
address public immutable router;
/// @notice The two tokens of the LP pair to add liquidity to
address public tokenA;
address public tokenB;
/// @notice How many PLS receives before auto-processing
uint256 public processEveryN = 10;
/// @notice Current receive counter
uint256 public receiveCount;
/// @notice Minimum WPLS balance required to process
uint256 public minProcessAmount = 1 ether;
/// @notice Cumulative tokenA bought via swaps (e.g. NEON)
uint256 public totalTokenABought;
/// @notice Cumulative PLS received
uint256 public totalPlsReceived;
event LiquidityAdded(address indexed pair, uint256 lpAmount);
event AutoProcessTriggered(uint256 wplsAmount);
event PairUpdated(address tokenA, address tokenB);
event ProcessEveryNUpdated(uint256 newN);
event MinProcessAmountUpdated(uint256 newMin);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
constructor(
address _wpls,
address _tokenA,
address _tokenB,
address _router,
uint256 _initialTokenABought,
uint256 _initialPlsReceived
) {
require(_wpls != address(0) && _tokenA != address(0) && _tokenB != address(0) && _router != address(0), "Zero address");
owner = msg.sender;
WPLS = _wpls;
router = _router;
tokenA = _tokenA;
tokenB = _tokenB;
totalTokenABought = _initialTokenABought;
totalPlsReceived = _initialPlsReceived;
IERC20_NLA(_wpls).approve(_router, type(uint256).max);
IERC20_NLA(_tokenA).approve(_router, type(uint256).max);
IERC20_NLA(_tokenB).approve(_router, type(uint256).max);
}
// ─── Auto-trigger on receive ─────────────────────────────────────
receive() external payable {
totalPlsReceived += msg.value;
receiveCount++;
if (receiveCount >= processEveryN) {
receiveCount = 0;
_tryProcess();
}
}
// ─── Core ────────────────────────────────────────────────────────
/// @notice Manual trigger — anyone can call
function processLiquidity() external {
_wrapPLS();
uint256 wplsBal = IWPLS_NLA(WPLS).balanceOf(address(this));
require(wplsBal >= minProcessAmount, "Below min");
_addLiquidity(wplsBal);
}
// ─── Internal ────────────────────────────────────────────────────
function _tryProcess() internal {
_wrapPLS();
uint256 wplsBal = IWPLS_NLA(WPLS).balanceOf(address(this));
if (wplsBal < minProcessAmount) return;
emit AutoProcessTriggered(wplsBal);
_addLiquidity(wplsBal);
}
function _wrapPLS() internal {
uint256 plsBal = address(this).balance;
if (plsBal > 0) {
IWPLS_NLA(WPLS).deposit{value: plsBal}();
}
}
/**
* @dev Swap half WPLS → tokenA (if != WPLS), swap half WPLS → tokenB (if != WPLS),
* then addLiquidity(tokenA, tokenB). LP tokens stay in contract.
*/
function _addLiquidity(uint256 wplsAmount) internal {
uint256 half = wplsAmount / 2;
if (half == 0) return;
address _tokenA = tokenA;
address _tokenB = tokenB;
uint256 amountA;
uint256 amountB;
// Get tokenA
if (_tokenA == WPLS) {
amountA = half;
} else {
uint256 before = IERC20_NLA(_tokenA).balanceOf(address(this));
address[] memory path = new address[](2);
path[0] = WPLS;
path[1] = _tokenA;
try IPulseXRouter(router).swapExactTokensForTokensSupportingFeeOnTransferTokens(
half, 0, path, address(this), block.timestamp
) {} catch { return; }
amountA = IERC20_NLA(_tokenA).balanceOf(address(this)) - before;
if (amountA == 0) return;
totalTokenABought += amountA;
}
// Get tokenB
uint256 otherHalf = wplsAmount - half;
if (_tokenB == WPLS) {
amountB = otherHalf;
} else {
uint256 before = IERC20_NLA(_tokenB).balanceOf(address(this));
address[] memory path = new address[](2);
path[0] = WPLS;
path[1] = _tokenB;
try IPulseXRouter(router).swapExactTokensForTokensSupportingFeeOnTransferTokens(
otherHalf, 0, path, address(this), block.timestamp
) {} catch { return; }
amountB = IERC20_NLA(_tokenB).balanceOf(address(this)) - before;
if (amountB == 0) return;
}
try IPulseXRouter(router).addLiquidity(
_tokenA, _tokenB, amountA, amountB, 0, 0, address(this), block.timestamp
) returns (uint256, uint256, uint256 liquidity) {
address pair = IPulseXFactory(IPulseXRouter(router).factory()).getPair(_tokenA, _tokenB);
emit LiquidityAdded(pair, liquidity);
} catch {}
}
// ─── View ──────────────────────────────────────────────────────────
/// @notice Returns cumulative stats
function getStats() external view returns (uint256 tokenABought, uint256 plsReceived) {
return (totalTokenABought, totalPlsReceived);
}
// ─── Owner Controls ──────────────────────────────────────────────
/// @notice Change the LP pair. Approves router for new tokens.
function setPair(address _tokenA, address _tokenB) external onlyOwner {
require(_tokenA != address(0) && _tokenB != address(0), "Zero address");
tokenA = _tokenA;
tokenB = _tokenB;
if (_tokenA != WPLS) {
IERC20_NLA(_tokenA).approve(router, type(uint256).max);
}
if (_tokenB != WPLS) {
IERC20_NLA(_tokenB).approve(router, type(uint256).max);
}
emit PairUpdated(_tokenA, _tokenB);
}
function setProcessEveryN(uint256 _n) external onlyOwner {
require(_n > 0, "Must be > 0");
processEveryN = _n;
emit ProcessEveryNUpdated(_n);
}
function setMinProcessAmount(uint256 _min) external onlyOwner {
minProcessAmount = _min;
emit MinProcessAmountUpdated(_min);
}
function withdrawToken(address token, uint256 amount) external onlyOwner {
require(token != address(0), "Zero address");
IERC20_NLA(token).transfer(owner, amount);
}
function withdrawPLS(uint256 amount) external onlyOwner {
(bool ok, ) = owner.call{value: amount}("");
require(ok, "Transfer failed");
}
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "Zero address");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}