Address
0xd8fbf204c729a693b5441fc0287a00ea9fb474aaCurrent Holdings
$0.00
TXs sent
not counted
First Active
2025-11-07
block 24,960,782
Last Active
315 days ago
block 24,960,782
Funded By
not identified
Net worth historyi
No net-worth snapshots recorded yet
exact matchPulseRaceRewardsolc 0.8.29+commit.ab55807cruntime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.29;
/**
* @title PulseRaceReward - Ready for Remix Deployment
* @notice First-come-first-served competition system for PulseChain
* @dev Users send PLS (min 10K), contract swaps to PX402, then gives 1.5x of swapped amount (50% profit)
*
* DEPLOYMENT INSTRUCTIONS:
* 1. Open Remix IDE (remix.ethereum.org)
* 2. Create new file: PulseRaceReward.sol
* 3. Paste this entire contract code
* 4. Compile with Solidity 0.8.29
* 5. Deploy to PulseChain mainnet (Chain ID: 369)
* 6. After deployment, owner must:
* - Approve PX402 tokens to contract
* - Call depositPX402() to fund reward pool
*
* OWNER FUNCTIONS:
* - depositPLS() - Add PLS to pool (payable)
* - depositPX402(amount) - Add PX402 to reward pool (must approve first)
* - withdraw() - Withdraw all PLS and PX402 from contract
* - emergencyWithdrawToken(tokenAddress) - Emergency withdraw any token
*
* CONTRACT ADDRESSES (PulseChain Mainnet):
* - PX402: 0x675aC865AEBcfc1D22F819bA0Fe7a60Bf17Cb60d
* - WPLS: 0xA1077a294dDE1B09bB078844df40758a5D0f9a27
* - PulseX Router: 0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02
* - PulseX Factory: 0x1715a3E4A142d8b698131108995174F37aEBA10D
*/
// OpenZeppelin Contracts - Ownable
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
}
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
}
// OpenZeppelin Contracts - ReentrancyGuard
abstract contract ReentrancyGuard {
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
_status = ENTERED;
}
function _nonReentrantAfter() private {
_status = NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
// Minimal ERC20 Interface
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
// PulseX V2 Router Interface
interface IPulseXRouter {
function swapExactETHForTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable returns (uint[] memory amounts);
}
// PulseX V2 Factory Interface
interface IPulseXFactory {
function getPair(address tokenA, address tokenB) external view returns (address pair);
}
// PulseX V2 Pair Interface
interface IPulseXPair {
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function token0() external view returns (address);
function token1() external view returns (address);
}
/**
* @title PulseRaceReward
* @notice Competition contract that swaps PLS to PX402 and rewards 1.5x
*/
contract PulseRaceReward is Ownable, ReentrancyGuard {
// Constants
uint256 public constant MIN_PLS_AMOUNT = 10_000 ether; // Minimum 10,000 PLS
uint256 public constant REWARD_MULTIPLIER = 150; // 1.5x = 150%
uint256 public constant MULTIPLIER_DENOMINATOR = 100;
uint256 public constant SLIPPAGE_TOLERANCE = 50; // 50% slippage tolerance
uint256 public constant SLIPPAGE_DENOMINATOR = 100;
// PulseChain Mainnet Addresses
address public constant WPLS = 0xA1077a294dDE1B09bB078844df40758a5D0f9a27;
address public constant PULSEX_ROUTER_ADDRESS = 0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02;
address public constant PULSEX_FACTORY_ADDRESS = 0x1715a3E4A142d8b698131108995174F37aEBA10D;
// Contracts
IERC20 public immutable PX402;
IPulseXRouter public immutable PULSEX_ROUTER;
IPulseXFactory public immutable PULSEX_FACTORY;
// Events
event RewardDistributed(address indexed user, uint256 plsAmount, uint256 px402Reward);
event Deposited(address indexed owner, uint256 amount);
event Withdrawn(address indexed owner, uint256 plsAmount, uint256 px402Amount);
event EmergencyWithdraw(address indexed owner, address indexed token, uint256 amount);
/**
* @notice Constructor
* @param _px402Address PX402 token address
*/
constructor(address _px402Address) Ownable(msg.sender) {
require(_px402Address != address(0), "Invalid PX402 address");
PX402 = IERC20(_px402Address);
PULSEX_ROUTER = IPulseXRouter(PULSEX_ROUTER_ADDRESS);
PULSEX_FACTORY = IPulseXFactory(PULSEX_FACTORY_ADDRESS);
}
/**
* @notice Receive function - accepts PLS and distributes PX402 rewards
* @dev Swaps PLS to PX402, then sends 1.5x of swapped amount to user
*/
receive() external payable nonReentrant {
require(msg.value >= MIN_PLS_AMOUNT, "Below minimum PLS amount");
// Swap PLS to PX402
uint256 px402FromSwap = _swapPLSToPX402(msg.value);
require(px402FromSwap > 0, "Swap failed");
// Calculate reward: 1.5x of swapped amount
uint256 rewardAmount = (px402FromSwap * REWARD_MULTIPLIER) / MULTIPLIER_DENOMINATOR;
// Check if contract has enough PX402
uint256 contractBalance = PX402.balanceOf(address(this));
require(contractBalance >= rewardAmount, "Insufficient PX402 in pool");
// Transfer reward to user
require(PX402.transfer(msg.sender, rewardAmount), "Reward transfer failed");
emit RewardDistributed(msg.sender, msg.value, rewardAmount);
}
/**
* @notice Owner deposits PLS to fill the reward pool
*/
function depositPLS() external payable onlyOwner {
require(msg.value > 0, "Cannot deposit 0");
emit Deposited(msg.sender, msg.value);
}
/**
* @notice Owner deposits PX402 tokens to fill the reward pool
* @param amount Amount of PX402 to deposit
*/
function depositPX402(uint256 amount) external onlyOwner {
require(amount > 0, "Cannot deposit 0");
require(
PX402.transferFrom(msg.sender, address(this), amount),
"Transfer failed"
);
emit Deposited(msg.sender, amount);
}
/**
* @notice Owner withdraws remaining PLS and PX402
*/
function withdraw() external onlyOwner nonReentrant {
uint256 plsBalance = address(this).balance;
uint256 px402Balance = PX402.balanceOf(address(this));
if (plsBalance > 0) {
(bool success, ) = payable(owner()).call{value: plsBalance}("");
require(success, "PLS transfer failed");
}
if (px402Balance > 0) {
require(PX402.transfer(owner(), px402Balance), "PX402 transfer failed");
}
emit Withdrawn(owner(), plsBalance, px402Balance);
}
/**
* @notice Emergency withdraw any ERC20 token
* @param token Token address to withdraw
*/
function emergencyWithdrawToken(address token) external onlyOwner {
require(token != address(0), "Invalid token");
IERC20 tokenContract = IERC20(token);
uint256 balance = tokenContract.balanceOf(address(this));
require(balance > 0, "No balance");
require(tokenContract.transfer(owner(), balance), "Transfer failed");
emit EmergencyWithdraw(owner(), token, balance);
}
/**
* @notice Get remaining PLS pool balance
*/
function getRemainingPLSPool() external view returns (uint256) {
return address(this).balance;
}
/**
* @notice Get remaining PX402 pool balance
*/
function getRemainingPX402Pool() external view returns (uint256) {
return PX402.balanceOf(address(this));
}
/**
* @notice Debug function to check pair and reserves
*/
function debugPairInfo() external view returns (
address pairAddress,
uint256 reserve0,
uint256 reserve1,
address token0,
address token1
) {
pairAddress = PULSEX_FACTORY.getPair(address(PX402), WPLS);
if (pairAddress == address(0)) return (address(0), 0, 0, address(0), address(0));
IPulseXPair pair = IPulseXPair(pairAddress);
(uint112 r0, uint112 r1,) = pair.getReserves();
reserve0 = uint256(r0);
reserve1 = uint256(r1);
token0 = pair.token0();
token1 = pair.token1();
}
/**
* @notice Estimate how many more participants can get rewards
* @param plsAmount PLS amount per participant
* @return Number of participants that can still get rewards
*/
function estimateRemainingParticipants(uint256 plsAmount)
external
view
returns (uint256)
{
if (plsAmount < MIN_PLS_AMOUNT) return 0;
uint256 px402FromSwap = _estimateSwapOutput(plsAmount);
if (px402FromSwap == 0) return 0;
uint256 rewardPerParticipant = (px402FromSwap * REWARD_MULTIPLIER) / MULTIPLIER_DENOMINATOR;
if (rewardPerParticipant == 0) return 0;
uint256 px402Balance = PX402.balanceOf(address(this));
return px402Balance / rewardPerParticipant;
}
/**
* @notice Estimate PX402 reward for a given PLS amount
* @param plsAmount Amount of PLS to send
* @return Expected PX402 reward amount
*/
function estimateReward(uint256 plsAmount) external view returns (uint256) {
if (plsAmount < MIN_PLS_AMOUNT) return 0;
uint256 px402FromSwap = _estimateSwapOutput(plsAmount);
if (px402FromSwap == 0) return 0;
return (px402FromSwap * REWARD_MULTIPLIER) / MULTIPLIER_DENOMINATOR;
}
/**
* @notice Internal function to swap PLS to PX402
* @param plsAmount Amount of PLS to swap
* @return Amount of PX402 received
*/
function _swapPLSToPX402(uint256 plsAmount) internal virtual returns (uint256) {
address[] memory path = new address[](2);
path[0] = WPLS;
path[1] = address(PX402);
// Calculate minimum output with slippage tolerance
uint256 expectedOutput = _estimateSwapOutput(plsAmount);
require(expectedOutput > 0, "Cannot estimate swap output");
uint256 minOutput = (expectedOutput * (SLIPPAGE_DENOMINATOR - SLIPPAGE_TOLERANCE)) / SLIPPAGE_DENOMINATOR;
uint256[] memory amounts = PULSEX_ROUTER.swapExactETHForTokens{value: plsAmount}(
minOutput,
path,
address(this),
block.timestamp + 3600 // 1 hour deadline
);
return amounts[1]; // Return PX402 amount received
}
/**
* @notice Internal function to estimate swap output using pair reserves
* @param plsAmount Amount of PLS to swap
* @return Estimated PX402 output
*/
function _estimateSwapOutput(uint256 plsAmount) internal view virtual returns (uint256) {
// Get pair address - try PX402/WPLS order (not WPLS/PX402)
address pairAddress = PULSEX_FACTORY.getPair(address(PX402), WPLS);
if (pairAddress == address(0)) return 0;
IPulseXPair pair = IPulseXPair(pairAddress);
// Get reserves
(uint112 reserve0, uint112 reserve1,) = pair.getReserves();
// Determine which reserve is WPLS and which is PX402
address token0 = pair.token0();
uint256 reserveIn;
uint256 reserveOut;
if (token0 == WPLS) {
reserveIn = uint256(reserve0);
reserveOut = uint256(reserve1);
} else {
reserveIn = uint256(reserve1);
reserveOut = uint256(reserve0);
}
// Calculate output using UniswapV2 formula: amountOut = (amountIn * 997 * reserveOut) / (reserveIn * 1000 + amountIn * 997)
uint256 amountInWithFee = plsAmount * 997;
uint256 numerator = amountInWithFee * reserveOut;
uint256 denominator = (reserveIn * 1000) + amountInWithFee;
return numerator / denominator;
}
}