Skip to main content
PulseScanner.io

Address

0xee4b908367ae0fe8607b70d9acfaf7eafd7f32e9
Current Holdings
$0.1132
TXs sent
not counted
First Active
2025-11-03
block 24,929,987
Last Active
318 days ago
block 24,930,001
Funded By
0xfa40…f20f

Net worth historyi

2 snapshots · to block 27,438,541coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchPulseIndexsolc 0.8.20+commit.a1b79de6runtime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

// ---------------------------------------------------------
// Basic ERC20 implementation (self-contained)
// ---------------------------------------------------------
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }
}

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

contract ERC20 is Context, IERC20 {
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    uint256 private _totalSupply;
    string private _name;
    string private _symbol;

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    function name() public view virtual returns (string memory) {
        return _name;
    }

    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _allowances[sender][_msgSender()] = currentAllowance - amount;
        }
        return true;
    }

    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from zero");
        require(recipient != address(0), "ERC20: transfer to zero");
        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;
        emit Transfer(sender, recipient, amount);
    }

    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to zero");
        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);
    }

    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from zero");
        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            _totalSupply -= amount;
        }
        emit Transfer(account, address(0), amount);
    }

    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from zero");
        require(spender != address(0), "ERC20: approve to zero");
        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }
}

// ---------------------------------------------------------
// Ownable
// ---------------------------------------------------------
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        _transferOwnership(_msgSender());
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not owner");
        _;
    }

    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is zero");
        _transferOwnership(newOwner);
    }

    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// ---------------------------------------------------------
// PulseX / Uniswap V2 interfaces
// ---------------------------------------------------------
interface IUniswapV2Factory {
    function getPair(address tokenA, address tokenB) external view returns (address pair);
}

interface IUniswapV2Pair {
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function token0() external view returns (address);
    function token1() external view returns (address);
}

interface IUniswapV2Router02 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address); // WPLS on PulseChain

    function swapExactETHForTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable returns (uint[] memory amounts);

    function swapExactTokensForETH(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);

    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
}

// ---------------------------------------------------------
// PulseIndex – LP sent directly to DEAD
// ---------------------------------------------------------
contract PulseIndex is ERC20, Ownable {
    address public immutable routerAddress;
    address public immutable wplsAddress;
    address[] public basketTokens; // PLSX, INC, HEX, eHEX, WBTC, WETH

    address public constant DEAD = 0x000000000000000000000000000000000000dEaD;

    constructor() ERC20("Pulse Index", "PINDEX") {
        routerAddress = 0x165C3410fC91EF562C50559f7d2289fEbed552d9; // PulseX V2 router
        wplsAddress   = 0xA1077a294dDE1B09bB078844df40758a5D0f9a27; // WPLS

        basketTokens = [
            0x95B303987A60C71504D99Aa1b13B4DA07b0790ab, // PLSX
            0x2fa878Ab3F87CC1C9737Fc071108F904c0B0C95d, // INC
            0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39, // HEX
            0x57fde0a71132198BBeC939B98976993d8D89D225, // eHEX
            0xb17D901469B9208B17d916112988A3FeD19b5cA1, // WBTC
            0x02DcdD04e3F455D838cd1249292C58f3B79e3C3C  // WETH
        ];
    }

    receive() external payable {}

    // -----------------------------------------------------
    // Deposit PLS -> mint PINDEX, buy basket, thicken LP
    // -----------------------------------------------------
    function deposit() external payable {
        uint256 amount = msg.value;
        require(amount > 0, "No PLS deposited");

        // Mint PINDEX 1:1 to user
        _mint(msg.sender, amount);

        uint256 seventyPercent = (amount * 70) / 100;
        uint256 thirtyPercent  = amount - seventyPercent;

        // Buy basket with 70% (hold 1/7th as PLS, swap 6/7th split equally)
        uint256 part = seventyPercent / 7;
        IUniswapV2Router02 router = IUniswapV2Router02(routerAddress);

        for (uint256 i = 0; i < basketTokens.length; i++) {
            address[] memory path = new address[](2);
            path[0] = wplsAddress;
            path[1] = basketTokens[i];

            router.swapExactETHForTokens{value: part}(
                0,
                path,
                address(this),
                block.timestamp + 300
            );
        }
        // Remaining 1/7th of seventyPercent stays as PLS in contract

        address factory = router.factory();
        address pair    = IUniswapV2Factory(factory).getPair(wplsAddress, address(this));

        uint256 reservePLS;
        uint256 reservePINDEX;
        bool isInitial = (pair == address(0));

        if (!isInitial) {
            (uint112 r0, uint112 r1,) = IUniswapV2Pair(pair).getReserves();
            address token0 = IUniswapV2Pair(pair).token0();
            reservePLS     = (token0 == wplsAddress) ? r0 : r1;
            reservePINDEX  = (token0 == wplsAddress) ? r1 : r0;
            if (reservePLS == 0 && reservePINDEX == 0) isInitial = true;
        }

        if (isInitial) {
            // Bootstrap LP at 1:1 price
            uint256 lpPindex = thirtyPercent;
            _mint(address(this), lpPindex);
            _approve(address(this), address(router), lpPindex);

            router.addLiquidityETH{value: thirtyPercent}(
                address(this),
                lpPindex,
                0,
                0,
                DEAD, // LP minted directly to DEAD (burnt)
                block.timestamp + 300
            );
        } else {
            // Single-sided LP add: calculate how much PLS to swap to keep ratio
            uint256 amountToSwap = _calculateSwapAmount(reservePLS, reservePINDEX, thirtyPercent);

            if (amountToSwap > 0 && amountToSwap < thirtyPercent) {
                // Swap PLS -> PINDEX
               address[] memory path2 = new address[](2);
                path2[0] = wplsAddress;
                path2[1] = address(this);

                uint256 beforeBal = balanceOf(address(this));

                router.swapExactETHForTokens{value: amountToSwap}(
                    0,
                    path2,
                    address(this),
                    block.timestamp + 300
                );

                uint256 afterBal  = balanceOf(address(this));
                uint256 received  = afterBal - beforeBal;

                uint256 remainingPLS = thirtyPercent - amountToSwap;

                _approve(address(this), address(router), received);

                router.addLiquidityETH{value: remainingPLS}(
                    address(this),
                    received,
                    0,
                    0,
                    DEAD, // LP minted directly to DEAD (burnt)
                    block.timestamp + 300
                );
            }
        }
    }

    // -----------------------------------------------------
    // Redeem PINDEX -> PLS (sell proportional share)
    // -----------------------------------------------------
    function redeem(uint256 amount) external {
        require(amount > 0, "Zero amount");

        uint256 total = totalSupply();
        uint256 initialBalance = address(this).balance;
        uint256 plsShare = (initialBalance * amount) / total;

        IUniswapV2Router02 router = IUniswapV2Router02(routerAddress);

        for (uint256 i = 0; i < basketTokens.length; i++) {
            address token = basketTokens[i];
            uint256 tokenBal   = IERC20(token).balanceOf(address(this));
            uint256 tokenShare = (tokenBal * amount) / total;

            if (tokenShare > 0) {
                IERC20(token).approve(address(router), tokenShare);

                address[] memory path = new address[](2);
                path[0] = token;
                path[1] = wplsAddress;

                router.swapExactTokensForETH(
                    tokenShare,
                    0,
                    path,
                    address(this),
                    block.timestamp + 300
                );
            }
        }

        uint256 finalBalance   = address(this).balance;
        uint256 addedFromSwaps = finalBalance - initialBalance;
        uint256 totalToSend    = plsShare + addedFromSwaps;

        _burn(msg.sender, amount);
        payable(msg.sender).transfer(totalToSend);
    }

    // -----------------------------------------------------
    // Internal math
    // -----------------------------------------------------
    function _calculateSwapAmount(
        uint256 reservePLS,
        uint256 reservePINDEX,
        uint256 amountIn
    ) private pure returns (uint256) {
        // Simple constant-product approximation with 0.3% fee
        uint256 fee = 997;
        uint256 num = amountIn * fee * reservePINDEX;
        uint256 den = reservePLS * 1000 + amountIn * fee;
        return num / den;
    }
}