Skip to main content
PulseScanner.io

Address

0x4e1a5ad0716d5aed378bcee9daf5a08aba3f637d
Current 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
Funded By
0x9c46…10ec

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