Address
0x08e5df3efbfe92fd6eb566f04e4c68ada0bbe9bfCurrent Holdings
$0.00
TXs sent
not counted
First Active
2025-11-20
block 25,072,437
Last Active
258 days ago
block 25,426,894
Funded By
not identified
Net worth historyi
148 snapshots · to block 27,455,299coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchFlareXLotterysolc 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/access/Ownable.sol";
/**
* @title FlareX Holder Lottery
* @notice Hourly lottery system that rewards random FLX holders
* @dev Receives liquidity tax from FlareX token and distributes 30% to random eligible holders
*
* Features:
* - Hourly lottery draws (every 1 hour)
* - Minimum 0.2% supply holding requirement (20,000 FLX)
* - 30% of accumulated tokens distributed to winner
* - Previous winners cannot win again
* - Owner can withdraw remaining tokens
* - Verifiable random winner selection
*/
contract FlareXLottery is Ownable {
// Constants
uint256 private constant TOTAL_SUPPLY = 10_000_000 * 10**18;
uint256 public constant MIN_HOLDER_PERCENT = 20; // 0.2% = 20/10000
uint256 public constant REWARD_PERCENT = 30; // 30% of pool
uint256 public constant LOTTERY_INTERVAL = 1 hours;
// State variables
IERC20 public flxToken;
uint256 public lastLotteryTime;
uint256 public totalDraws;
uint256 public totalRewardsDistributed;
// Track previous winners
mapping(address => bool) public hasWon;
address[] public allWinners;
// Lottery history
struct LotteryDraw {
uint256 drawNumber;
uint256 timestamp;
address winner;
uint256 rewardAmount;
uint256 eligibleHolders;
}
mapping(uint256 => LotteryDraw) public lotteryHistory;
// Events
event LotteryDrawn(
uint256 indexed drawNumber,
address indexed winner,
uint256 rewardAmount,
uint256 eligibleHolders,
uint256 timestamp
);
event TokensWithdrawn(address indexed owner, uint256 amount);
event LotteryIntervalUpdated(uint256 newInterval);
/**
* @notice Constructor - Initialize lottery contract
* @param _flxToken Address of FlareX token contract
*/
constructor(address _flxToken) Ownable(msg.sender) {
require(_flxToken != address(0), "Invalid token address");
flxToken = IERC20(_flxToken);
lastLotteryTime = block.timestamp;
}
/**
* @notice Calculate minimum FLX tokens required to be eligible
* @return Minimum token amount (20,000 FLX = 0.2% of 10M supply)
*/
function getMinimumHolding() public pure returns (uint256) {
return (TOTAL_SUPPLY * MIN_HOLDER_PERCENT) / 10000; // 20,000 FLX
}
/**
* @notice Check if address is eligible for lottery
* @param holder Address to check
* @return True if holder has minimum required balance and has not won before
*/
function isEligible(address holder) public view returns (bool) {
return flxToken.balanceOf(holder) >= getMinimumHolding() && !hasWon[holder];
}
/**
* @notice Check if address has won before
* @param holder Address to check
* @return True if holder has won before
*/
function hasPreviouslyWon(address holder) public view returns (bool) {
return hasWon[holder];
}
/**
* @notice Get total number of unique winners
* @return Number of addresses that have won
*/
function getTotalWinners() public view returns (uint256) {
return allWinners.length;
}
/**
* @notice Get all previous winners
* @return Array of all winner addresses
*/
function getAllWinners() public view returns (address[] memory) {
return allWinners;
}
/**
* @notice Get current lottery pool balance
* @return Current FLX balance in contract
*/
function getPoolBalance() public view returns (uint256) {
return flxToken.balanceOf(address(this));
}
/**
* @notice Calculate reward amount for next draw
* @return 30% of current pool balance
*/
function getNextRewardAmount() public view returns (uint256) {
uint256 poolBalance = getPoolBalance();
return (poolBalance * REWARD_PERCENT) / 100;
}
/**
* @notice Check if lottery can be drawn
* @return True if 1 hour has passed since last draw
*/
function canDrawLottery() public view returns (bool) {
return block.timestamp >= lastLotteryTime + LOTTERY_INTERVAL;
}
/**
* @notice Get time remaining until next lottery
* @return Seconds until next draw is available
*/
function getTimeUntilNextDraw() public view returns (uint256) {
if (canDrawLottery()) return 0;
return (lastLotteryTime + LOTTERY_INTERVAL) - block.timestamp;
}
/**
* @notice Draw lottery and select random winner
* @param eligibleHolders Array of addresses that meet minimum holding requirement
* @dev Anyone can call this function, but must provide eligible holders list
*/
function drawLottery(address[] calldata eligibleHolders) external {
require(canDrawLottery(), "Lottery interval not reached");
require(eligibleHolders.length > 0, "No eligible holders provided");
uint256 poolBalance = getPoolBalance();
require(poolBalance > 0, "No tokens in pool");
// Verify all provided addresses are eligible (have balance AND have not won before)
for (uint256 i = 0; i < eligibleHolders.length; i++) {
require(isEligible(eligibleHolders[i]), "Holder not eligible or already won");
require(eligibleHolders[i] != address(0), "Invalid address");
}
// Select random winner using pseudo-random method
uint256 randomIndex = _generateRandomNumber(eligibleHolders.length);
address winner = eligibleHolders[randomIndex];
// Calculate reward (30% of pool)
uint256 rewardAmount = getNextRewardAmount();
// Transfer reward to winner
require(flxToken.transfer(winner, rewardAmount), "Transfer failed");
// Mark winner as having won
hasWon[winner] = true;
allWinners.push(winner);
// Update state
totalDraws++;
totalRewardsDistributed += rewardAmount;
lastLotteryTime = block.timestamp;
// Record lottery history
lotteryHistory[totalDraws] = LotteryDraw({
drawNumber: totalDraws,
timestamp: block.timestamp,
winner: winner,
rewardAmount: rewardAmount,
eligibleHolders: eligibleHolders.length
});
emit LotteryDrawn(
totalDraws,
winner,
rewardAmount,
eligibleHolders.length,
block.timestamp
);
}
/**
* @notice Generate pseudo-random number for winner selection
* @param max Maximum value (array length)
* @return Random index
* @dev Uses block data for randomness - suitable for low-stakes lottery
*/
function _generateRandomNumber(uint256 max) private view returns (uint256) {
uint256 random = uint256(
keccak256(
abi.encodePacked(
block.timestamp,
block.prevrandao,
msg.sender,
totalDraws,
getPoolBalance()
)
)
);
return random % max;
}
/**
* @notice Owner withdraws tokens from contract
* @param amount Amount to withdraw (0 = withdraw all)
*/
function withdrawTokens(uint256 amount) external onlyOwner {
uint256 balance = getPoolBalance();
require(balance > 0, "No tokens to withdraw");
uint256 withdrawAmount = amount == 0 ? balance : amount;
require(withdrawAmount <= balance, "Insufficient balance");
require(flxToken.transfer(msg.sender, withdrawAmount), "Transfer failed");
emit TokensWithdrawn(msg.sender, withdrawAmount);
}
/**
* @notice Get lottery draw details by draw number
* @param drawNumber Draw number to query
* @return Lottery draw details
*/
function getLotteryDraw(uint256 drawNumber) external view returns (LotteryDraw memory) {
require(drawNumber > 0 && drawNumber <= totalDraws, "Invalid draw number");
return lotteryHistory[drawNumber];
}
/**
* @notice Get recent lottery draws
* @param count Number of recent draws to return
* @return Array of recent lottery draws
*/
function getRecentDraws(uint256 count) external view returns (LotteryDraw[] memory) {
if (totalDraws == 0) {
return new LotteryDraw[](0);
}
uint256 returnCount = count > totalDraws ? totalDraws : count;
LotteryDraw[] memory draws = new LotteryDraw[](returnCount);
for (uint256 i = 0; i < returnCount; i++) {
draws[i] = lotteryHistory[totalDraws - i];
}
return draws;
}
/**
* @notice Get lottery statistics
* @return totalDrawsCount Total number of draws
* @return totalRewards Total rewards distributed
* @return currentPool Current pool balance
* @return nextReward Next reward amount
* @return timeUntilNext Time until next draw
*/
function getLotteryStats() external view returns (
uint256 totalDrawsCount,
uint256 totalRewards,
uint256 currentPool,
uint256 nextReward,
uint256 timeUntilNext
) {
return (
totalDraws,
totalRewardsDistributed,
getPoolBalance(),
getNextRewardAmount(),
getTimeUntilNextDraw()
);
}
}