TokenPreSale

Description:

ERC20 token contract with Factory capabilities. Standard implementation for fungible tokens on Ethereum.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "PresaleStake.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.0;\r
\r
interface IERC20 {\r
    function totalSupply() external view returns (uint256);\r
    function balanceOf(address account) external view returns (uint256);\r
    function transfer(address recipient, uint256 amount) external returns (bool);\r
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\r
    function allowance(address owner, address spender) external view returns (uint256);\r
    function approve(address spender, uint256 amount) external returns (bool);\r
    event Transfer(address indexed from, address indexed to, uint256 value);\r
    event Approval(address indexed owner, address indexed spender, uint256 value);\r
}\r
\r
interface AggregatorV3Interface {\r
    function latestRoundData()\r
        external\r
        view\r
        returns (\r
            uint80 roundId,\r
            int256 answer,\r
            uint256 startedAt,\r
            uint256 updatedAt,\r
            uint80 answeredInRound\r
        );\r
}\r
\r
abstract contract Context {\r
    function _msgSender() internal view virtual returns (address) {\r
        return msg.sender;\r
    }\r
    function _msgData() internal view virtual returns (bytes calldata) {\r
        return msg.data;\r
    }\r
}\r
\r
abstract contract Ownable is Context {\r
    address private _owner;\r
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\r
    constructor() {\r
        _owner = _msgSender();\r
        emit OwnershipTransferred(address(0), _owner);\r
    }\r
    function owner() public view virtual returns (address) {\r
        return _owner;\r
    }\r
    modifier onlyOwner() {\r
        require(owner() == _msgSender(), "Ownable: caller is not the owner");\r
        _;\r
    }\r
    function renounceOwnership() public virtual onlyOwner {\r
        emit OwnershipTransferred(_owner, address(0));\r
        _owner = address(0);\r
    }\r
    function transferOwnership(address newOwner) public virtual onlyOwner {\r
        require(newOwner != address(0), "Ownable: new owner is zero address");\r
        emit OwnershipTransferred(_owner, newOwner);\r
        _owner = newOwner;\r
    }\r
}\r
\r
library SafeMath {\r
    function add(uint256 a, uint256 b) internal pure returns (uint256) {\r
        uint256 c = a + b;\r
        require(c >= a, "SafeMath: addition overflow");\r
        return c;\r
    }\r
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\r
        require(b <= a, "SafeMath: subtraction overflow");\r
        return a - b;\r
    }\r
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\r
        if (a == 0) return 0;\r
        uint256 c = a * b;\r
        require(c / a == b, "SafeMath: multiplication overflow");\r
        return c;\r
    }\r
    function div(uint256 a, uint256 b) internal pure returns (uint256) {\r
        require(b > 0, "SafeMath: division by zero");\r
        return a / b;\r
    }\r
}\r
\r
/* Minimal interface to interact with the staking contract */\r
interface IStaking {\r
    function stakeFor(address user, uint256 amount) external;\r
}\r
\r
contract TokenPreSale is Ownable {\r
    using SafeMath for uint256;\r
\r
    IERC20 public token;\r
    IERC20 public usdt;\r
    AggregatorV3Interface public priceFeed;\r
\r
    address public treasuryWallet;\r
    address public stakingContract; // new\r
\r
    // Hard cap and soft cap (both in USD value, 18 decimals)\r
    uint256 public constant HARD_CAP = 7_560_000 * 1e18; // $7,560,000\r
    uint256 public constant SOFT_CAP = HARD_CAP / 100;  // $75,600\r
\r
    uint256 public totalETHRaised;\r
    uint256 public totalUSDTRaised;\r
    uint256 public totalSold;\r
\r
    // Token price set to $0.000005 per token\r
    uint256 public tokenPriceInUSDT = 0.000005 ether;\r
\r
    bool public saleActive = true;\r
    bool public claimEnabled = false;\r
\r
    mapping(address => uint256) public pendingTokens;\r
\r
    event Sell(address indexed buyer, uint256 tokenAmount, uint256 value, string paymentMethod);\r
    event SellAndStake(address indexed buyer, uint256 tokenAmount, uint256 value, string paymentMethod);\r
    event Withdraw(address indexed owner, uint256 amount);\r
    event ClaimStatusChanged(bool newStatus);\r
    event TokenPriceUpdated(uint256 newPrice);\r
    event TokensClaimed(address indexed user, uint256 amount);\r
\r
    constructor(\r
        address _token,\r
        address _usdt,\r
        address _priceFeed,\r
        address _treasuryWallet,\r
        address _stakingContract\r
    ) {\r
        require(_token != address(0), "Invalid token address");\r
        require(_usdt != address(0), "Invalid USDT address");\r
        require(_priceFeed != address(0), "Invalid price feed address");\r
        require(_treasuryWallet != address(0), "Invalid treasury address");\r
        require(_stakingContract != address(0), "Invalid staking address");\r
\r
        token = IERC20(_token);\r
        usdt = IERC20(_usdt);\r
        priceFeed = AggregatorV3Interface(_priceFeed);\r
        treasuryWallet = _treasuryWallet;\r
        stakingContract = _stakingContract;\r
    }\r
\r
    receive() external payable {\r
        buyAndStakeWithETH();\r
    }\r
\r
    // ==================== PRICE HELPERS ====================\r
    function getLatestETHPrice() public view returns (uint256) {\r
        (, int256 price, , , ) = priceFeed.latestRoundData();\r
        return uint256(price).mul(1e10); // convert from 8 to 18 decimals\r
    }\r
\r
    function getTokenPriceInETH() public view returns (uint256) {\r
        uint256 ethPriceInUSD = getLatestETHPrice();\r
        return tokenPriceInUSDT.mul(1e18).div(ethPriceInUSD);\r
    }\r
\r
    function getTotalRaisedInUSD() public view returns (uint256) {\r
        uint256 ethUSD = getLatestETHPrice(); // 1 ETH = X USD (18 decimals)\r
        uint256 totalETHinUSD = totalETHRaised.mul(ethUSD).div(1e18);\r
        uint256 totalUSDTinUSD = totalUSDTRaised; // USDT already 1:1 USD\r
        return totalETHinUSD.add(totalUSDTinUSD);\r
    }\r
\r
    // ==================== BUY WITH ETH ====================\r
    function buyWithETH() public payable {\r
        require(saleActive, "Sale not active");\r
        require(msg.value > 0, "No ETH sent");\r
\r
        uint256 ethAmount = msg.value;\r
        uint256 newRaisedUSD = getTotalRaisedInUSD();\r
        uint256 ethValueUSD = ethAmount.mul(getLatestETHPrice()).div(1e18);\r
        require(newRaisedUSD.add(ethValueUSD) <= HARD_CAP, "Hard cap reached");\r
\r
        uint256 tokenPriceInETH = getTokenPriceInETH();\r
        uint256 tokenAmount = ethAmount.mul(1e18).div(tokenPriceInETH);\r
        require(token.balanceOf(address(this)) >= tokenAmount, "Not enough tokens");\r
\r
        totalETHRaised = totalETHRaised.add(ethAmount);\r
        pendingTokens[msg.sender] = pendingTokens[msg.sender].add(tokenAmount);\r
\r
        (bool success, ) = treasuryWallet.call{value: ethAmount}("");\r
        require(success, "ETH transfer failed");\r
\r
        emit Sell(msg.sender, tokenAmount, ethAmount, "ETH");\r
    }\r
\r
    // ==================== BUY WITH USDT ====================\r
    function buyWithUSDT(uint256 usdtAmount) public {\r
        require(saleActive, "Sale not active");\r
        require(usdtAmount > 0, "Invalid USDT amount");\r
\r
        uint256 newRaisedUSD = getTotalRaisedInUSD();\r
        require(newRaisedUSD.add(usdtAmount) <= HARD_CAP, "Hard cap reached");\r
\r
        uint256 tokenAmount = usdtAmount.mul(1e18).div(tokenPriceInUSDT);\r
        require(token.balanceOf(address(this)) >= tokenAmount, "Not enough tokens");\r
\r
        totalUSDTRaised = totalUSDTRaised.add(usdtAmount);\r
        pendingTokens[msg.sender] = pendingTokens[msg.sender].add(tokenAmount);\r
\r
        require(usdt.transferFrom(msg.sender, treasuryWallet, usdtAmount), "USDT transfer failed");\r
\r
        emit Sell(msg.sender, tokenAmount, usdtAmount, "USDT");\r
    }\r
\r
    // ==================== NEW: BUY AND STAKE WITH ETH ====================\r
    function buyAndStakeWithETH() public payable {\r
        require(saleActive, "Sale not active");\r
        require(msg.value > 0, "No ETH sent");\r
        require(stakingContract != address(0), "Staking not set");\r
\r
        uint256 ethAmount = msg.value;\r
        uint256 newRaisedUSD = getTotalRaisedInUSD();\r
        uint256 ethValueUSD = ethAmount.mul(getLatestETHPrice()).div(1e18);\r
        require(newRaisedUSD.add(ethValueUSD) <= HARD_CAP, "Hard cap reached");\r
\r
        uint256 tokenPriceInETH = getTokenPriceInETH();\r
        uint256 tokenAmount = ethAmount.mul(1e18).div(tokenPriceInETH);\r
        require(token.balanceOf(address(this)) >= tokenAmount, "Not enough tokens in presale");\r
\r
        totalETHRaised = totalETHRaised.add(ethAmount);\r
\r
        // Transfer ETH immediately to treasury\r
        (bool success, ) = treasuryWallet.call{value: ethAmount}("");\r
        require(success, "ETH transfer failed");\r
\r
        // Transfer tokens from presale contract to staking contract\r
        require(token.transfer(stakingContract, tokenAmount), "Token transfer to staking failed");\r
\r
        // Call staking contract to record the stake on behalf of buyer\r
        IStaking(stakingContract).stakeFor(msg.sender, tokenAmount);\r
\r
        emit SellAndStake(msg.sender, tokenAmount, ethAmount, "ETH");\r
    }\r
\r
    // ==================== NEW: BUY AND STAKE WITH USDT ====================\r
    function buyAndStakeWithUSDT(uint256 usdtAmount) public {\r
        require(saleActive, "Sale not active");\r
        require(usdtAmount > 0, "Invalid USDT amount");\r
        require(stakingContract != address(0), "Staking not set");\r
\r
        uint256 newRaisedUSD = getTotalRaisedInUSD();\r
        require(newRaisedUSD.add(usdtAmount) <= HARD_CAP, "Hard cap reached");\r
\r
        uint256 tokenAmount = usdtAmount.mul(1e18).div(tokenPriceInUSDT);\r
        require(token.balanceOf(address(this)) >= tokenAmount, "Not enough tokens in presale");\r
\r
        totalUSDTRaised = totalUSDTRaised.add(usdtAmount);\r
\r
        // Transfer USDT to treasury\r
        require(usdt.transferFrom(msg.sender, treasuryWallet, usdtAmount), "USDT transfer failed");\r
\r
        // Transfer tokens from presale contract to staking contract\r
        require(token.transfer(stakingContract, tokenAmount), "Token transfer to staking failed");\r
\r
        // Call staking contract to record the stake on behalf of buyer\r
        IStaking(stakingContract).stakeFor(msg.sender, tokenAmount);\r
\r
        emit SellAndStake(msg.sender, tokenAmount, usdtAmount, "USDT");\r
    }\r
\r
    // ==================== CLAIM TOKENS ====================\r
    function claimTokens() public {\r
        require(claimEnabled, "Claim not enabled");\r
        uint256 amount = pendingTokens[msg.sender];\r
        require(amount > 0, "No tokens to claim");\r
\r
        pendingTokens[msg.sender] = 0;\r
        require(token.transfer(msg.sender, amount), "Token transfer failed");\r
\r
        emit TokensClaimed(msg.sender, amount);\r
    }\r
\r
    // ==================== ADMIN FUNCTIONS ====================\r
    function setClaimEnabled(bool _enabled) external onlyOwner {\r
        claimEnabled = _enabled;\r
        emit ClaimStatusChanged(_enabled);\r
    }\r
\r
    function withdraw() public onlyOwner {\r
        uint256 balance = address(this).balance;\r
        require(balance > 0, "No ETH to withdraw");\r
        payable(msg.sender).transfer(balance);\r
        emit Withdraw(msg.sender, balance);\r
    }\r
\r
    function setSaleStatus(bool _status) external onlyOwner {\r
        saleActive = _status;\r
    }\r
\r
    function endSale() public onlyOwner {\r
        uint256 remaining = token.balanceOf(address(this));\r
        if (remaining > 0) token.transfer(msg.sender, remaining);\r
        saleActive = false;\r
    }\r
\r
    function updateTokenPriceInUSDT(uint256 _newPrice) external onlyOwner {\r
        require(_newPrice > 0, "Invalid price");\r
        tokenPriceInUSDT = _newPrice;\r
        emit TokenPriceUpdated(_newPrice);\r
    }\r
\r
    function emergencyWithdrawTokens() external onlyOwner {\r
        uint256 remaining = token.balanceOf(address(this));\r
        require(token.transfer(msg.sender, remaining), "Token transfer failed");\r
    }\r
\r
    function setStakingContract(address _staking) external onlyOwner {\r
        require(_staking != address(0), "Invalid staking");\r
        stakingContract = _staking;\r
    }\r
}\r
"
    }
  },
  "settings": {
    "evmVersion": "shanghai",
    "metadata": {
      "bytecodeHash": "ipfs"
    },
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "remappings": [],
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    }
  }
}}

Tags:
ERC20, Token, Factory|addr:0xeefa611c0eb6c8285a0eaee76ad39ca389fc754b|verified:true|block:23720068|tx:0x219dc0929136dc2fc3e1162f718221b4af7dad24895c73d6c8677bd3f879a936|first_check:1762188215

Submitted on: 2025-11-03 17:43:36

Comments

Log in to comment.

No comments yet.