Skip to main content
PulseScanner.io

Address

0xa6d97d5d3ff74a2ed70abe2823468e347ff0bf55
Current Holdings
$0.00
TXs sent
not counted
First Active
2025-11-19
block 25,061,165
Last Active
299 days ago
block 25,069,456
Funded By
not identified

Net worth historyi

9 snapshots · to block 25,068,799
exact matchFlareXPresalesolc 0.8.29+commit.ab55807cruntime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.29;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

/**
 * @title FlareX Presale Contract
 * @notice Presale contract for FlareX (FLX) token accepting USDC payments
 * @dev Supports instant token claims with configurable pause mechanism
 * 
 * Features:
 * - Accept USDC payments (6 decimals on PulseChain)
 * - Price: $0.0014 per FLX token (1 USDC = 714.2857 FLX)
 * - Presale allocation: 5,000,000 FLX tokens
 * - Minimum purchase: $10 USDC
 * - Instant token delivery on purchase
 * - Owner can withdraw USDC and unsold tokens
 * - Pausable presale mechanism
 */
contract FlareXPresale is Ownable, ReentrancyGuard {
    using SafeERC20 for IERC20;
    
    // Token contracts
    IERC20 public immutable flxToken;
    IERC20 public immutable usdcToken;
    
    // Presale configuration
    uint256 public constant PRESALE_ALLOCATION = 5_000_000 * 10**18; // 5 million FLX
    uint256 public constant TOKEN_PRICE_NUMERATOR = 7142857; // 714.2857 tokens per USDC (scaled by 10000)
    uint256 public constant TOKEN_PRICE_DENOMINATOR = 10000;
    uint256 public constant MIN_PURCHASE_USDC = 10 * 10**6; // $10 USDC (6 decimals)
    uint256 public constant USDC_DECIMALS = 6;
    uint256 public constant FLX_DECIMALS = 18;
    
    // Presale state
    bool public presaleActive = true;
    uint256 public totalUsdcRaised;
    uint256 public totalTokensSold;
    
    // User purchases tracking
    mapping(address => uint256) public userPurchases;
    mapping(address => uint256) public userTokensClaimed;
    
    // Events
    event Purchase(
        address indexed buyer,
        uint256 usdcAmount,
        uint256 flxAmount,
        uint256 timestamp
    );
    event UsdcWithdrawn(address indexed owner, uint256 amount);
    event TokensWithdrawn(address indexed owner, uint256 amount);
    event PresaleStatusUpdated(bool active);
    event TokensClaimed(address indexed buyer, uint256 amount);
    
    /**
     * @notice Constructor - Initialize presale contract
     * @param _flxToken FlareX token contract address
     * @param _usdcToken USDC token contract address (PulseChain)
     */
    constructor(
        address _flxToken,
        address _usdcToken
    ) Ownable(msg.sender) {
        require(_flxToken != address(0), "Invalid FLX token address");
        require(_usdcToken != address(0), "Invalid USDC token address");
        
        flxToken = IERC20(_flxToken);
        usdcToken = IERC20(_usdcToken);
    }
    
    /**
     * @notice Purchase FLX tokens with USDC
     * @param usdcAmount Amount of USDC to spend (6 decimals)
     * @dev Automatically transfers tokens to buyer (instant claim)
     */
    function buyTokens(uint256 usdcAmount) external nonReentrant {
        require(presaleActive, "Presale is not active");
        require(usdcAmount >= MIN_PURCHASE_USDC, "Below minimum purchase amount");
        
        // Calculate FLX tokens to receive
        // Formula: flxAmount = (usdcAmount * TOKEN_PRICE_NUMERATOR / TOKEN_PRICE_DENOMINATOR) * 10^12
        // The 10^12 factor converts from USDC decimals (6) to FLX decimals (18)
        uint256 flxAmount = (usdcAmount * TOKEN_PRICE_NUMERATOR * 10**12) / TOKEN_PRICE_DENOMINATOR;
        
        require(flxAmount > 0, "Invalid token amount");
        require(totalTokensSold + flxAmount <= PRESALE_ALLOCATION, "Exceeds presale allocation");
        
        // Check contract has enough tokens
        uint256 contractBalance = flxToken.balanceOf(address(this));
        require(contractBalance >= flxAmount, "Insufficient tokens in presale contract");
        
        // Transfer USDC from buyer to contract
        usdcToken.safeTransferFrom(msg.sender, address(this), usdcAmount);
        
        // Update state
        totalUsdcRaised += usdcAmount;
        totalTokensSold += flxAmount;
        userPurchases[msg.sender] += usdcAmount;
        userTokensClaimed[msg.sender] += flxAmount;
        
        // Instant token transfer to buyer
        flxToken.safeTransfer(msg.sender, flxAmount);
        
        emit Purchase(msg.sender, usdcAmount, flxAmount, block.timestamp);
        emit TokensClaimed(msg.sender, flxAmount);
    }
    
    /**
     * @notice Calculate FLX tokens for given USDC amount
     * @param usdcAmount Amount of USDC (6 decimals)
     * @return flxAmount Amount of FLX tokens (18 decimals)
     */
    function calculateTokenAmount(uint256 usdcAmount) external pure returns (uint256 flxAmount) {
        flxAmount = (usdcAmount * TOKEN_PRICE_NUMERATOR * 10**12) / TOKEN_PRICE_DENOMINATOR;
    }
    
    /**
     * @notice Get remaining tokens available for presale
     * @return Remaining FLX tokens
     */
    function getRemainingTokens() external view returns (uint256) {
        return PRESALE_ALLOCATION - totalTokensSold;
    }
    
    /**
     * @notice Pause or resume presale
     * @param _active True to activate, false to pause
     */
    function setPresaleStatus(bool _active) external onlyOwner {
        presaleActive = _active;
        emit PresaleStatusUpdated(_active);
    }
    
    /**
     * @notice Withdraw collected USDC to owner
     * @dev Only owner can withdraw raised funds
     */
    function withdrawUsdc() external onlyOwner nonReentrant {
        uint256 balance = usdcToken.balanceOf(address(this));
        require(balance > 0, "No USDC to withdraw");
        
        usdcToken.safeTransfer(msg.sender, balance);
        emit UsdcWithdrawn(msg.sender, balance);
    }
    
    /**
     * @notice Emergency withdraw unsold FLX tokens
     * @dev Only owner can withdraw unsold tokens
     */
    function withdrawUnsoldTokens() external onlyOwner nonReentrant {
        uint256 balance = flxToken.balanceOf(address(this));
        require(balance > 0, "No tokens to withdraw");
        
        flxToken.safeTransfer(msg.sender, balance);
        emit TokensWithdrawn(msg.sender, balance);
    }
    
    /**
     * @notice Get presale statistics
     * @return _presaleActive Current presale status
     * @return _totalUsdcRaised Total USDC raised
     * @return _totalTokensSold Total FLX tokens sold
     * @return _remainingTokens Remaining tokens for sale
     */
    function getPresaleStats() external view returns (
        bool _presaleActive,
        uint256 _totalUsdcRaised,
        uint256 _totalTokensSold,
        uint256 _remainingTokens
    ) {
        _presaleActive = presaleActive;
        _totalUsdcRaised = totalUsdcRaised;
        _totalTokensSold = totalTokensSold;
        _remainingTokens = PRESALE_ALLOCATION - totalTokensSold;
    }
    
    /**
     * @notice Get user purchase information
     * @param user User address
     * @return usdcSpent Total USDC spent by user
     * @return tokensClaimed Total FLX tokens claimed by user
     */
    function getUserInfo(address user) external view returns (
        uint256 usdcSpent,
        uint256 tokensClaimed
    ) {
        usdcSpent = userPurchases[user];
        tokensClaimed = userTokensClaimed[user];
    }
}