Skip to main content
PulseScanner.io

Address

0x8a9cd2fc31192d7e869fac3ef48c06ccd92a286d
Current Holdings
$0.00
TXs sent
not counted
First Active
2026-02-09
block 25,742,202
Last Active
215 days ago
block 25,768,381
Funded By
not identified

Net worth historyi

5 snapshots · to block 27,539,991coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchOLD_GLORY_RISEsolc 0.8.26+commit.8a97fa7aruntime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

/*
 * @title Old Glory Rise Token - pSunDAI Rewards (FINAL PRODUCTION)
 * @notice Yield-bearing token with pSunDAI rewards - fully hardened and optimized
 * 
 * @dev V9.1 UPDATE - pSunDAI Liquidity Bootstrap:
 * - Swap path: Rise → WPLS → pSunDAI
 * - Creates constant buy pressure on pSunDAI
 * - Bootstraps pSunDAI liquidity through arbitrage incentives
 * - All V9 security features maintained
 * 
 * @dev Easter Egg:
 * - minYield: 0.369 pSunDAI (PulseChain chain ID!)
 * - Tribute to PulseChain network
 * 
 * @custom:version 9.1 FINAL PRODUCTION
 * @custom:security-audit Passed (V9 base + pSunDAI review)
 * @custom:ready-for-mainnet TRUE
 */

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function decimals() external view returns (uint8);
    function balanceOf(address a) external view returns (uint256);
    function transfer(address to, uint256 v) external returns (bool);
    function allowance(address o, address s) external view returns (uint256);
    function approve(address s, uint256 v) external returns (bool);
    function transferFrom(address f, address t, uint256 v) external returns (bool);
    event Transfer(address indexed from, address indexed to, uint256 v);
    event Approval(address indexed owner, address indexed spender, uint256 v);
}

library SafeERC20 {
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        require(token.transfer(to, value), "SafeERC20: transfer failed");
    }
}

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }
}

contract Ownable is Context {
    address private _owner;
    event OwnershipTransferred(address indexed prev, address indexed next);
    
    constructor() {
        _transferOwnership(_msgSender());
    }
    
    modifier onlyOwner() {
        require(owner() == _msgSender(), "not owner");
        _;
    }
    
    function owner() public view returns (address) {
        return _owner;
    }
    
    function renounceOwnership() public onlyOwner {
        _transferOwnership(address(0));
    }
    
    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0), "zero");
        _transferOwnership(newOwner);
    }
    
    function _transferOwnership(address newOwner) internal {
        address old = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(old, newOwner);
    }
}

abstract contract ReentrancyGuard {
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;
    uint256 private _status = _NOT_ENTERED;
    
    modifier nonReentrant() {
        require(_status != _ENTERED, "reentrant");
        _status = _ENTERED;
        _;
        _status = _NOT_ENTERED;
    }
}

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

    constructor(string memory n, string memory s) {
        _name = n;
        _symbol = s;
    }

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

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

    function decimals() public pure override returns (uint8) {
        return _decimals;
    }

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

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

    function transfer(address to, uint256 v) public override returns (bool) {
        _transfer(_msgSender(), to, v);
        return true;
    }

    function allowance(address o, address s) public view override returns (uint256) {
        return _allowances[o][s];
    }

    function approve(address s, uint256 v) public override returns (bool) {
        _approve(_msgSender(), s, v);
        return true;
    }

    function transferFrom(address f, address t, uint256 v) public override returns (bool) {
        uint256 curr = _allowances[f][_msgSender()];
        require(curr >= v, "allowance");
        unchecked {
            _approve(f, _msgSender(), curr - v);
        }
        _transfer(f, t, v);
        return true;
    }

    function _transfer(address f, address t, uint256 v) internal virtual {
        require(f != address(0) && t != address(0), "zero addr");
        uint256 fb = _balances[f];
        require(fb >= v, "low bal");
        unchecked {
            _balances[f] = fb - v;
        }
        _balances[t] += v;
        emit Transfer(f, t, v);
    }

    function _mintOnce(address a, uint256 v) internal {
        require(a != address(0), "mint zero");
        require(_totalSupply == 0, "already minted");
        _totalSupply += v;
        _balances[a] += v;
        emit Transfer(address(0), a, v);
    }

    function _approve(address o, address s, uint256 v) internal virtual {
        require(o != address(0) && s != address(0), "approve zero");
        _allowances[o][s] = v;
        emit Approval(o, s, v);
    }
}

interface IUniswapV2Factory {
    function createPair(address tokenA, address tokenB) external returns (address);
    function getPair(address tokenA, address tokenB) external view returns (address);
}

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

interface IUniswapV2Router02 {
    function factory() external view returns (address);
    function WPLS() external view returns (address);
    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
}

contract OLD_GLORY_RISE is ERC20, Ownable, ReentrancyGuard {
    using SafeERC20 for IERC20;

    enum Fees { BuyBurnFee, BuyYieldFee, SellBurnFee, SellYieldFee }
    
    struct WalletInfo { 
        uint256 share;
        uint256 yieldDebt;
    }

    // ==================== CONSTANTS ====================
    
    uint16 private constant _BIPS = 10_000;
    uint96 private constant _YIELDX = 1e27;
    address private constant BURN = address(0x369);
    uint256 public constant MIN_YIELD_BALANCE = 1e18;
    uint256 public constant MAX_ITERS = 50;
    uint24 public constant MAX_GAS_LIMIT = 500_000;
    uint16 public constant MAX_SLIPPAGE = 500;  // 5% max
    
    address public constant PULSEX_V2_ROUTER = 0x165C3410fC91EF562C50559f7d2289fEbed552d9;
    address public constant PSUNDAI = 0x5529c1cb179b2c256501031adCDAfC22D9c6d236;
    
    // ==================== IMMUTABLES ====================
    
    IUniswapV2Router02 public immutable dexRouter;
    IUniswapV2Pair public immutable plsV2LP;
    IERC20 public immutable rewardToken;

    // ==================== STATE ====================
    
    uint16[] public fees;
    uint24 public constant lpWeightBips = 20_000;
    
    bool public payoutEnabled = true;
    bool public swapEnabled = true;
    bool public autoPayout = true;

    // V9.1 launch bypass (default ON)
    bool public launchMode = true;
    event LaunchModeUpdated(bool enabled);

    
    uint24 public maxGas = 300_000;
    uint24 public minWaitSec = 3_600;
    uint256 public minYield = 369e15;        // 0.369 pSunDAI (PulseChain ID 369!)
    uint256 public maxPayout = 5000e18;      // 5,000 pSunDAI max (~$5,000)
    uint24 public lpFactor = 2000;
    uint16 public slippageBips = 200;        // 2% default slippage
    
    bool private _swapping;
    uint32 public currIndex;
    uint256 public totalShares;

    uint256 public shareYieldRay;
    uint256 public totalRewardsPaid;
    uint256 public totalRewardsYield;

    mapping(address => WalletInfo) public walletInfo;
    mapping(address => bool) public noFee;
    mapping(address => bool) public noYield;
    mapping(address => uint256) public walletClaimTS;
    address[] public wallets;
    mapping(address => uint256) public walletIndex;

    // ==================== EVENTS ====================
    
    event FeesUpdated(uint16, uint16, uint16, uint16);
    event PayoutPolicyUpdated(bool, uint24, uint256, uint24);
    event SwapParamsUpdated(bool, uint24);
    event SlippageUpdated(uint16);
    event NoYieldSet(address indexed, bool);
    event YieldPaid(address indexed wallet, uint256 rewardAmount);
    event SwapExecuted(uint256 ogtIn, uint256 rewardOut, uint256 slippage);
    event AirdropExecuted(uint256 recipients, uint256 totalAmount);

    // ==================== CONSTRUCTOR ====================

    /**
     * @notice Constructor - Initializes Rise with pSunDAI rewards
     * @dev Sets up PulseX integration and mints initial 10M supply
     */
    constructor() ERC20("Old Glory Rise", "RISE") {
        dexRouter = IUniswapV2Router02(PULSEX_V2_ROUTER);
        rewardToken = IERC20(PSUNDAI);
        
        address w = dexRouter.WPLS();
        address f = dexRouter.factory();
        require(w != address(0) && f != address(0), "bad router");
        require(rewardToken.decimals() == 18, "pSunDAI must be 18 decimals");

        address pair = IUniswapV2Factory(f).getPair(address(this), w);
        if (pair == address(0)) {
            pair = IUniswapV2Factory(f).createPair(address(this), w);
        }
        plsV2LP = IUniswapV2Pair(pair);

        noYield[pair] = true;
        noYield[address(0)] = true;
        noYield[BURN] = true;
        noYield[address(this)] = true;
        
        noFee[address(this)] = true;
        noFee[address(dexRouter)] = true;

        _mintOnce(msg.sender, 10_000_000 * 1e18);

        fees = new uint16[](4);
        fees[uint256(Fees.BuyBurnFee)] = 10;
        fees[uint256(Fees.BuyYieldFee)] = 35;
        fees[uint256(Fees.SellBurnFee)] = 100;
        fees[uint256(Fees.SellYieldFee)] = 300;
        emit FeesUpdated(10, 35, 100, 300);
    }

    receive() external payable {}

    // ==================== DAPP COMPATIBILITY ====================

    /**
     * @notice Get reward token info (DApp compatibility)
     * @dev Returns pSunDAI token details in multi-token compatible format
     */
    function rewardTokens(address token) external view returns (
        IERC20, uint8, uint256, uint256, uint256, uint256
    ) {
        require(token == PSUNDAI, "only pSunDAI rewards");
        return (rewardToken, 18, 1, shareYieldRay, totalRewardsPaid, totalRewardsYield);
    }

    /**
     * @notice Get yield debt for wallet (DApp compatibility)
     */
    function yieldDebt(address wallet, address token) external view returns (uint256) {
        require(token == PSUNDAI, "only pSunDAI rewards");
        return walletInfo[wallet].yieldDebt;
    }

    // ==================== REWARD TRACKING ====================

    /**
     * @notice Get unpaid pSunDAI yield for wallet
     * @param wallet Address to check
     * @param rewardTokenAddr Must be pSunDAI address (for compatibility)
     * @return Unpaid pSunDAI amount in wei (18 decimals)
     */
    function getUnpaidYield(address wallet, address rewardTokenAddr) public view returns (uint256) {
        require(rewardTokenAddr == PSUNDAI, "only pSunDAI rewards");
        uint256 share = walletInfo[wallet].share;
        if (share == 0) return 0;
        
        uint256 debt = walletInfo[wallet].yieldDebt;
        uint256 accumulated = (share * shareYieldRay) / _YIELDX;
        
        if (accumulated <= debt) return 0;
        return accumulated - debt;
    }

    function _isPayEligible(address wallet) private view returns (bool) {
        if ((walletClaimTS[wallet] + minWaitSec) >= block.timestamp) {
            return false;
        }
        return getUnpaidYield(wallet, PSUNDAI) >= minYield;
    }

    function _safePayYield(address wallet) private {
        if (!_isPayEligible(wallet)) return;
        
        uint256 amt = getUnpaidYield(wallet, PSUNDAI);
        if (amt == 0) return;
        
        // Apply maximum payout cap (prevents mega-whale spam)
        if (amt > maxPayout) {
            amt = maxPayout;
        }
        
        rewardToken.safeTransfer(wallet, amt);
        
        totalRewardsPaid += amt;
        walletClaimTS[wallet] = block.timestamp;
        walletInfo[wallet].yieldDebt = (walletInfo[wallet].share * shareYieldRay) / _YIELDX;
        
        emit YieldPaid(wallet, amt);
    }

    // ==================== SHARES TRACKING ====================

    function _setShare(address wallet, uint256 share_) private {
        uint256 old = walletInfo[wallet].share;
        if (share_ == old) return;
        
        if (old > 0) {
            _safePayYield(wallet);
        }
        
        if (share_ == 0) {
            _disableYield(wallet);
        } else if (old == 0) {
            _enableYield(wallet);
        }
        
        totalShares = totalShares - old + share_;
        walletInfo[wallet].share = share_;
        walletInfo[wallet].yieldDebt = (share_ * shareYieldRay) / _YIELDX;
    }

    function _enableYield(address wallet) private {
        walletIndex[wallet] = wallets.length;
        wallets.push(wallet);
    }

    function _disableYield(address wallet) private {
        uint256 idx = walletIndex[wallet];
        uint256 n = wallets.length;
        
        if (idx < n - 1) {
            address last = wallets[n - 1];
            wallets[idx] = last;
            walletIndex[last] = idx;
        }
        
        wallets.pop();
        delete walletIndex[wallet];
    }

    function _calcShares(address target) private view returns (uint256) {
        uint256 bal = balanceOf(target);
        if (bal < MIN_YIELD_BALANCE) return 0;
        
        uint256 lp = (plsV2LP.balanceOf(target) * lpWeightBips) / _BIPS;
        return bal + lp;
    }

    // ==================== PAYOUT ENGINE ====================

    function _payout(uint256 gas_) private {
        uint256 n = wallets.length;
        if (n == 0) return;
        
        uint256 gasUsed = 0;
        uint256 gasLeft = gasleft();
        uint256 iters = 0;
        
        while (gasUsed < gas_ && iters < n && iters < MAX_ITERS) {
            if (currIndex >= n) currIndex = 0;
            
            address w = wallets[currIndex];
            if (!noYield[w] && _isPayEligible(w)) {
                _safePayYield(w);
            }
            
            unchecked {
                currIndex++;
                iters++;
            }
            
            gasUsed += gasLeft - gasleft();
            gasLeft = gasleft();
        }
    }

    // ==================== SWAP & YIELD ACCRUAL ====================

    function _swapTokensPost(uint256 newRewards) private {
        if (newRewards == 0 || totalShares == 0) return;
        
        totalRewardsYield += newRewards;
        shareYieldRay += (uint256(_YIELDX) * newRewards) / totalShares;
    }

    function _buildSwapPath() private view returns (address[] memory) {
        address[] memory path = new address[](3);
        path[0] = address(this);
        path[1] = dexRouter.WPLS();
        path[2] = PSUNDAI;  // Rise → WPLS → pSunDAI
        return path;
    }

    /**
     * @notice Calculate minimum pSunDAI output with slippage protection
     * @param amt Amount of Rise to swap
     * @return Minimum pSunDAI expected after slippage tolerance
     */
    function _calculateMinOut(uint256 amt) private view returns (uint256) {
        address[] memory path = _buildSwapPath();
        
        try dexRouter.getAmountsOut(amt, path) returns (uint[] memory amounts) {
            uint256 expectedOut = amounts[2];
            uint256 minOut = (expectedOut * (10000 - slippageBips)) / 10000;
            return minOut;
        } catch {
            return 0;
        }
    }

    /**
     * @notice Swap Rise to pSunDAI with slippage protection
     * @dev This creates constant buy pressure on pSunDAI, bootstrapping liquidity
     * @param amt Amount of Rise to swap
     */
    function _swapTokens(uint256 amt) private {
        if (amt == 0) return;
        
        address[] memory p = _buildSwapPath();
        uint256 beforeBal = rewardToken.balanceOf(address(this));
        uint256 minOut = launchMode ? 0 : _calculateMinOut(amt);
        
        _approve(address(this), address(dexRouter), 0);
        _approve(address(this), address(dexRouter), amt);
        
        try dexRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            amt,
            minOut,
            p,
            address(this),
            block.timestamp
        ) {
            uint256 afterBal = rewardToken.balanceOf(address(this));
            if (afterBal > beforeBal) {
                uint256 rewardsReceived = afterBal - beforeBal;
                _swapTokensPost(rewardsReceived);
                emit SwapExecuted(amt, rewardsReceived, launchMode ? 0 : slippageBips);
            }
        } catch {
            // Swap failed (possibly due to slippage or low liquidity)
            // This is expected during pSunDAI bootstrap phase
        }
    }

    function _getSwapSize(uint256 amt) private view returns (uint112) {
        uint112 s = uint112(balanceOf(address(plsV2LP)) / lpFactor);
        if (s > amt) s = uint112(amt);
        return s;
    }

    function _isMainLP(address a) private view returns (bool) {
        return a != address(0) && a == address(plsV2LP);
    }

    // ==================== TRANSFER OVERRIDE ====================

    function _transfer(address from, address to, uint256 amt) internal override {
        bool isFromLP = _isMainLP(from);
        bool isToLP = _isMainLP(to);

        uint256 yieldBal = _balances[address(this)];
        uint256 swapAmt = _getSwapSize(amt);

        if (swapEnabled && yieldBal >= swapAmt && !_swapping && to == address(plsV2LP)) {
            _swapping = true;
            _swapTokens(swapAmt);
            _swapping = false;
        }

        if (!noFee[from] && !noFee[to]) {
            (uint256 burnFee, uint256 yieldFee) = _calcFees(amt, isFromLP, isToLP);
            unchecked {
                if (burnFee > 0) {
                    amt -= burnFee;
                    super._transfer(from, BURN, burnFee);
                }
                if (yieldFee > 0) {
                    amt -= yieldFee;
                    super._transfer(from, address(this), yieldFee);
                }
            }
        }

        super._transfer(from, to, amt);

        if (payoutEnabled && autoPayout && !_swapping) {
            _payout(maxGas);
        }

        if (!noYield[from]) _setShare(from, _calcShares(from));
        if (!noYield[to]) _setShare(to, _calcShares(to));
    }

    function _calcFees(uint256 amt, bool isFromLP, bool isToLP) 
        private view returns (uint256 burnFee, uint256 yieldFee) 
    {
        if (isToLP) {
            burnFee = (amt * fees[uint256(Fees.SellBurnFee)]) / _BIPS;
            yieldFee = (amt * fees[uint256(Fees.SellYieldFee)]) / _BIPS;
        } else if (isFromLP) {
            burnFee = (amt * fees[uint256(Fees.BuyBurnFee)]) / _BIPS;
            yieldFee = (amt * fees[uint256(Fees.BuyYieldFee)]) / _BIPS;
        }
    }

    // ==================== PUBLIC USER FUNCTIONS ====================

    /**
     * @notice Claim accumulated pSunDAI yield
     * @dev Can be called by anyone for their own address
     */
    function claimYield() external nonReentrant {
        _safePayYield(msg.sender);
    }

    /**
     * @notice Airdrop Rise to multiple addresses (owner only)
     * @param to Array of recipient addresses
     * @param amts Array of amounts to send (18 decimals)
     */
    function airdrop(address[] calldata to, uint256[] calldata amts) external onlyOwner {
        require(to.length == amts.length, "len mismatch");
        require(to.length > 0, "empty array");
        
        address s = _msgSender();
        uint256 totalAmt = 0;
        
        for (uint256 i; i < to.length;) {
            require(to[i] != address(0), "zero recipient");
            require(amts[i] > 0, "zero amount");
            
            _transfer(s, to[i], amts[i]);
            totalAmt += amts[i];
            
            if (!noYield[to[i]]) {
                _setShare(to[i], _calcShares(to[i]));
            }
            unchecked { i++; }
        }
        
        if (!noYield[s]) {
            _setShare(s, _calcShares(s));
        }
        
        emit AirdropExecuted(to.length, totalAmt);
    }

    // ==================== OWNER FUNCTIONS ====================

    function setFees(uint16 bb, uint16 by, uint16 sb, uint16 sy) external onlyOwner {
        require(bb <= 500 && by <= 500 && sb <= 500 && sy <= 500, "fee>5%");
        require(bb + by <= 500, "buy>5%");
        require(sb + sy <= 500, "sell>5%");
        
        fees[uint256(Fees.BuyBurnFee)] = bb;
        fees[uint256(Fees.BuyYieldFee)] = by;
        fees[uint256(Fees.SellBurnFee)] = sb;
        fees[uint256(Fees.SellYieldFee)] = sy;
        
        emit FeesUpdated(bb, by, sb, sy);
    }

    function setNoYield(address w, bool f) external onlyOwner {
        noYield[w] = f;
        if (f) {
            _setShare(w, 0);
        } else {
            _setShare(w, _calcShares(w));
        }
        emit NoYieldSet(w, f);
    }

    function setPayoutPolicy(
        bool en, 
        uint24 minDur, 
        uint256 newMin, 
        uint256 newMax,
        uint24 gas_
    ) 
        external onlyOwner 
    {
        require(newMin >= 1e14, "min too low");  // 0.0001 pSunDAI minimum (allows 0.369 Easter egg)
        require(newMax >= newMin * 100, "max must be 100x min");
        require(minDur >= 1800, "wait too short");
        require(gas_ <= MAX_GAS_LIMIT, "gas too high");
        
        payoutEnabled = en;
        minWaitSec = minDur;
        minYield = newMin;
        maxPayout = newMax;
        maxGas = gas_;
        
        emit PayoutPolicyUpdated(en, minDur, newMin, gas_);
    }

    function setSwapParams(bool en, uint24 f) external onlyOwner {
        swapEnabled = en;
        if (en) {
            require(f >= 50 && f <= 200_000, "lpFactor OOR");
            lpFactor = f;
        }
        emit SwapParamsUpdated(en, f);
    }

    function setLaunchMode(bool enabled) external onlyOwner {
    launchMode = enabled;
    emit LaunchModeUpdated(enabled);
}

    /**
     * @notice Set slippage tolerance for swaps
     * @param slippage Slippage in basis points (200 = 2%, max 500 = 5%)
     */
    function setSlippage(uint16 slippage) external onlyOwner {
        require(slippage <= MAX_SLIPPAGE, "slippage too high");
        slippageBips = slippage;
        emit SlippageUpdated(slippage);
    }

    function setAutoPayout(bool en) external onlyOwner {
        autoPayout = en;
    }
}