FRP_Presale

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": {
    "contracts/Eth Presale.sol": {
      "content": "//SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

abstract contract ReentrancyGuard {
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        _status = _NOT_ENTERED;
    }
}

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

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );

    constructor() {
        _transferOwnership(_msgSender());
    }

    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(
            newOwner != address(0),
            "Ownable: new owner is the zero address"
        );
        _transferOwnership(newOwner);
    }

    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

interface IERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address to, uint256 amount) external returns (bool);

    function allowance(
        address owner,
        address spender
    ) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

interface Aggregator {
    function latestRoundData()
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );
}

contract FRP_Presale is ReentrancyGuard, Ownable {
    Aggregator internal aggregatorInterface;
    address[] public allUsers;
    address public fundReceiver;
    address public refDistributor;
    address public usdt;

    uint256 public uniqueBuyers;
    uint256 public overalllRaised;
    uint256 public stageIdCount;
    uint256 public currentStage;
    uint256 public minTokenTobuy;
    uint256 public minInvestRef;
    uint256 public minClaimRef;
    uint256 public usdMultiplier;
    uint256 public ethMultiplier;
    uint256 public tokenMultiplier;

    uint256[9] public purchaseBonusAmount = [
        150,
        250,
        500,
        900,
        1500,
        2500,
        5000,
        10000,
        100000
    ];
    uint8[8] public purchaseBonusPercentage = [3, 4, 5, 6, 7, 8, 9, 10];
    uint256[7] public refBonusAmount = [
        100,
        400,
        1000,
        2500,
        5000,
        10000,
        100000
    ];
    uint8[6] public refBonusPercentage = [3, 4, 5, 6, 7, 8];

    struct PresaleData {
        bool Active;
        uint256 startTime;
        uint256 endTime;
        uint256 price;
        uint256 nextStagePrice;
        uint256 soldTokens;
        uint256 tokensToSell;
        uint256 usdHardcap;
        uint256 amountRaisedUsd;
    }

    struct stageData {
        uint256 investedAmount;
        uint256 tokensBought;
    }

    struct PurchaseHistory {
        string paymentToken;
        uint256 investedUsd;
        uint256 purchasedTokens;
        uint256 bonusTokens;
    }

    struct UserData {
        bool isExist;
        address referrer;
        uint256 purchaseCount;
        uint256 totalInvestedUsd;
        uint256 totalClaimableTokens;
        uint256 purchasedTokens;
        uint256 refBonusUsd;
        uint256 ClaimedRefBonusUsd;
        uint256 refBonusTokens;
        uint256 purchaseBonusTokens;
        address[] referrals;
    }

    mapping(address => UserData) public users;
    mapping(address => mapping(uint256 => stageData)) public userStageData;
    mapping(address => mapping(uint256 => PurchaseHistory)) public userHistory;
    mapping(uint256 => PresaleData) public presale;
    mapping(address => bool) public isPaymentToken;
    mapping(uint256 => bool) public paused;

    event TokensBought(
        address indexed user,
        uint256 indexed id,
        address indexed purchaseToken,
        uint256 tokensBought,
        uint256 amountPaid,
        uint256 timestamp
    );

    event PresaleTokenAddressUpdated(
        address indexed prevValue,
        address indexed newValue,
        uint256 timestamp
    );

    event PresalePaused(uint256 indexed id, uint256 timestamp);
    event PresaleUnpaused(uint256 indexed id, uint256 timestamp);

    constructor() {
        fundReceiver = 0x744412446Fa08D213FbFdDC5B3085e6caD8753Bd;
        refDistributor = 0xA882D3bb9087140518EC67a75FEC68775AFdA25D;
        usdt = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
        aggregatorInterface = Aggregator(
            0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419 //0x694AA1769357215DE4FAC081bf1f309aDC325306 test
        );
        isPaymentToken[0xdAC17F958D2ee523a2206206994597C13D831ec7] = true;
        isPaymentToken[0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48] = true;
        isPaymentToken[0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409] = true;
        usdMultiplier = (10 ** 6);
        tokenMultiplier = (10 ** 9);
        ethMultiplier = (10 ** 18);
        minTokenTobuy = (2000 * tokenMultiplier);
    }

    function createStage(
        uint256 _price,
        uint256 _nextStagePrice,
        uint256 _tokensToSell,
        uint256 _usdHardcap,
        uint256 _startTime,
        uint256 _endTime
    ) external onlyOwner {
        require(_price > 0, "Zero price");
        require(_tokensToSell > 0, "Zero tokens to sell");

        stageIdCount++;

        presale[stageIdCount] = PresaleData(
            false,
            _startTime,
            _endTime,
            _price,
            _nextStagePrice,
            0,
            _tokensToSell,
            _usdHardcap,
            0
        );
    }

    function setStage(uint256 _id) public onlyOwner {
        require(presale[_id].tokensToSell > 0, "Presale don't exist");
        if (currentStage != 0) {
            presale[currentStage].endTime = block.timestamp;
            presale[currentStage].Active = false;
        }
        presale[_id].startTime = block.timestamp;
        presale[_id].Active = true;
        currentStage = _id;
    }

    function updateStageData(
        uint256 _id,
        uint256 _price,
        uint256 _nextStagePrice,
        uint256 _tokensToSell,
        uint256 _Hardcap,
        uint256 _startTime,
        uint256 _endTime
    ) external onlyOwner {
        require(_price > 0, "Zero price");
        require(_tokensToSell > 0, "Zero tokens to sell");
        require(_Hardcap > 0, "Zero harcap");
        presale[_id].price = _price;
        presale[_id].nextStagePrice = _nextStagePrice;
        presale[_id].tokensToSell = _tokensToSell;
        presale[_id].usdHardcap = _Hardcap;
        presale[_id].startTime = _startTime;
        presale[_id].endTime = _endTime;
    }

    function changeFundWallet(address _wallet) external onlyOwner {
        require(_wallet != address(0), "Invalid parameters");
        fundReceiver = _wallet;
    }

    function changeRefWallet(address _wallet) external onlyOwner {
        require(_wallet != address(0), "Invalid parameters");
        refDistributor = _wallet;
    }

    function addPaymentToken(address _newAddress) external onlyOwner {
        require(!isPaymentToken[_newAddress], "Already exist");
        isPaymentToken[_newAddress] = true;
    }

    function removePaymentToken(address _newAddress) external onlyOwner {
        require(isPaymentToken[_newAddress], "Not available");
        isPaymentToken[_newAddress] = false;
    }

    function WithdrawTokens(address _token, uint256 amount) external onlyOwner {
        IERC20(_token).transfer(fundReceiver, amount);
    }

    function WithdrawContractFunds(uint256 amount) external onlyOwner {
        payable(fundReceiver).transfer(amount);
    }

    function ChangeMinTokenToBuy(uint256 _amount) public onlyOwner {
        minTokenTobuy = _amount;
    }

    function ChangeOracleAddress(address _oracle) public onlyOwner {
        aggregatorInterface = Aggregator(_oracle);
    }

    function ChangePurchaseBonusAmount(
        uint256[9] memory _new
    ) public onlyOwner {
        purchaseBonusAmount = _new;
    }

    function ChangePurchaseBonusPercent(uint8[8] memory _new) public onlyOwner {
        purchaseBonusPercentage = _new;
    }

    function ChangeRefBonusAmount(uint256[7] memory _new) public onlyOwner {
        refBonusAmount = _new;
    }

    function ChangeRefBonusPercent(uint8[6] memory _new) public onlyOwner {
        refBonusPercentage = _new;
    }

    function ChangeRefValues(
        uint256 _minInvest,
        uint256 _minClaim
    ) public onlyOwner {
        minInvestRef = _minInvest;
        minClaimRef = _minClaim;
    }

    function pausePresale(uint256 _id) external checkPresaleId(_id) onlyOwner {
        require(!paused[_id], "Already paused");
        paused[_id] = true;
        emit PresalePaused(_id, block.timestamp);
    }

    function unPausePresale(
        uint256 _id
    ) external checkPresaleId(_id) onlyOwner {
        require(paused[_id], "Not paused");
        paused[_id] = false;
        emit PresaleUnpaused(_id, block.timestamp);
    }

    function getLatestPrice() public view returns (uint256) {
        (, int256 price, , , ) = aggregatorInterface.latestRoundData();
        price = (price * (10 ** 10));
        return uint256(price);
    }

    modifier checkPresaleId(uint256 _id) {
        require(_id > 0 && _id == currentStage, "Invalid presale id");
        _;
    }

    modifier checkSaleState(uint256 _id, uint256 amount) {
        require(presale[_id].Active == true, "preSAle not Active");
        require(
            amount > 0 &&
                amount <= presale[_id].tokensToSell - presale[_id].soldTokens,
            "Invalid sale amount"
        );
        _;
    }

    function buyWithUsd(
        address _referrer,
        address _paymentToken,
        uint256 usdAmount
    )
        external
        checkPresaleId(currentStage)
        checkSaleState(currentStage, usdtToTokens(currentStage, usdAmount))
        nonReentrant
        returns (bool)
    {
        require(isPaymentToken[_paymentToken], "Invalid payment token");
        require(_referrer != _msgSender(), "Invalid referrer");
        require(!paused[currentStage], "Presale paused");
        require(
            presale[currentStage].Active == true,
            "Presale is not active yet"
        );
        require(
            presale[currentStage].amountRaisedUsd + usdAmount <=
                presale[currentStage].usdHardcap,
            "Amount should be less than leftHardcap"
        );
        UserData storage user = users[_msgSender()];
        if (
            user.referrer == address(0) &&
            users[_referrer].totalInvestedUsd >= minInvestRef
        ) {
            user.referrer = _referrer;
        }
        if (!user.isExist) {
            user.isExist = true;
            allUsers.push(_msgSender());
            if (user.referrer != address(0)) {
                users[user.referrer].referrals.push(_msgSender());
            }
            uniqueBuyers++;
        }

        user.totalInvestedUsd += usdAmount;
        uint256 tokens = usdtToTokens(currentStage, usdAmount);
        user.purchasedTokens += tokens;
        require(tokens >= minTokenTobuy, "Less than min amount");
        uint256 refTokens;
        if (usdAmount >= refBonusPercentage[0] && user.referrer != address(0)) {
            uint256 refUsd = (usdAmount *
                checkRefBonus(usdAmount / usdMultiplier)) / 100;
            users[user.referrer].refBonusUsd += refUsd;
            refTokens =
                (tokens * checkRefBonus(usdAmount / usdMultiplier)) /
                100;
            user.refBonusTokens += refTokens;
        }
        uint256 bonusTokens = (tokens *
            checkPurchaseBonus(usdAmount / usdMultiplier)) / 100;
        if (bonusTokens > 0) {
            user.purchaseBonusTokens += bonusTokens;
        }
        user.totalClaimableTokens += (tokens + bonusTokens + refTokens);
        user.purchaseCount++;
        presale[currentStage].soldTokens += tokens;
        presale[currentStage].amountRaisedUsd += usdAmount;
        overalllRaised += usdAmount;
        userStageData[_msgSender()][currentStage].tokensBought += tokens;
        userStageData[_msgSender()][currentStage].investedAmount += usdAmount;
        userHistory[_msgSender()][user.purchaseCount] = PurchaseHistory(
            IERC20(_paymentToken).symbol(),
            usdAmount,
            tokens,
            bonusTokens
        );

        IERC20(_paymentToken).transferFrom(
            _msgSender(),
            fundReceiver,
            usdAmount
        );
        emit TokensBought(
            _msgSender(),
            currentStage,
            _paymentToken,
            tokens,
            usdAmount,
            block.timestamp
        );
        return true;
    }

    function buyWithEth(
        address _referrer
    )
        external
        payable
        checkPresaleId(currentStage)
        checkSaleState(currentStage, ethToTokens(currentStage, msg.value))
        nonReentrant
        returns (bool)
    {
        require(_referrer != _msgSender(), "Invalid referrer");
        uint256 usdAmount = (msg.value * getLatestPrice() * usdMultiplier) /
            (ethMultiplier * ethMultiplier);
        require(
            presale[currentStage].amountRaisedUsd + usdAmount <=
                presale[currentStage].usdHardcap,
            "Amount should be less than leftHardcap"
        );
        require(!paused[currentStage], "Presale paused");
        require(
            presale[currentStage].Active == true,
            "Presale is not active yet"
        );
        UserData storage user = users[_msgSender()];
        if (user.referrer == address(0)) {
            user.referrer = _referrer;
        }
        if (!user.isExist) {
            user.isExist = true;
            allUsers.push(_msgSender());
            if (user.referrer != address(0)) {
                users[user.referrer].referrals.push(_msgSender());
            }
            uniqueBuyers++;
        }

        user.totalInvestedUsd += usdAmount;
        uint256 tokens = usdtToTokens(currentStage, usdAmount);
        user.purchasedTokens += tokens;
        require(tokens >= minTokenTobuy, "Insufficient amount!");
        uint256 refTokens;
        if (usdAmount >= refBonusPercentage[0] && user.referrer != address(0)) {
            uint256 refUsd = (usdAmount *
                checkRefBonus(usdAmount / usdMultiplier)) / 100;
            users[user.referrer].refBonusUsd += refUsd;
            refTokens =
                (tokens * checkRefBonus(usdAmount / usdMultiplier)) /
                100;
            user.refBonusTokens += refTokens;
        }
        uint256 bonusTokens = (tokens *
            checkPurchaseBonus(usdAmount / usdMultiplier)) / 100;
        if (bonusTokens > 0) {
            user.purchaseBonusTokens += bonusTokens;
        }
        user.totalClaimableTokens += (tokens + bonusTokens + refTokens);
        user.purchaseCount++;
        presale[currentStage].soldTokens += tokens;
        presale[currentStage].amountRaisedUsd += usdAmount;
        overalllRaised += usdAmount;
        userStageData[_msgSender()][currentStage].tokensBought += tokens;
        userStageData[_msgSender()][currentStage].investedAmount += usdAmount;
        userHistory[_msgSender()][user.purchaseCount] = PurchaseHistory(
            "ETH",
            usdAmount,
            tokens,
            bonusTokens
        );

        payable(fundReceiver).transfer(msg.value);
        emit TokensBought(
            _msgSender(),
            currentStage,
            address(0),
            tokens,
            msg.value,
            block.timestamp
        );
        return true;
    }

    function claimRefBonus() external nonReentrant {
        UserData storage user = users[_msgSender()];
        require(
            user.refBonusUsd >= minClaimRef,
            "Can't claim less than min amount"
        );
        IERC20(usdt).transferFrom(
            refDistributor,
            _msgSender(),
            user.refBonusUsd
        );
        user.ClaimedRefBonusUsd += user.refBonusUsd;
        user.refBonusUsd = 0;
    }

    function ethBuyHelper(
        uint256 _id,
        uint256 amount
    ) external view returns (uint256 ethAmount) {
        uint256 usdPrice = (amount * presale[_id].price);
        ethAmount =
            (usdPrice * ethMultiplier) /
            (getLatestPrice() * tokenMultiplier);
    }

    function ethToTokens(
        uint256 _id,
        uint256 amount
    ) public view returns (uint256 _tokens) {
        uint256 usdAmount = (amount * getLatestPrice() * usdMultiplier) /
            (ethMultiplier * ethMultiplier);
        _tokens = usdtToTokens(_id, usdAmount);
    }

    function usdtBuyHelper(
        uint256 _id,
        uint256 amount
    ) external view returns (uint256 usdPrice) {
        usdPrice = (amount * presale[_id].price) / tokenMultiplier;
    }

    function usdtToTokens(
        uint256 _id,
        uint256 amount
    ) public view returns (uint256 _tokens) {
        _tokens = (amount * presale[_id].price) / usdMultiplier;
    }

    function checkPurchaseBonus(
        uint256 _usdAmount
    ) public view returns (uint8 _percent) {
        if (_usdAmount < purchaseBonusAmount[0]) return 0;
        for (uint8 i = 0; i < refBonusPercentage.length; i++) {
            if (
                _usdAmount >= purchaseBonusAmount[i] &&
                _usdAmount < purchaseBonusAmount[i + 1]
            ) {
                _percent = refBonusPercentage[i];
            }
        }
    }

    function checkRefBonus(
        uint256 _usdAmount
    ) public view returns (uint8 _percent) {
        if (_usdAmount < refBonusAmount[0]) return 0;
        for (uint8 i = 0; i <= refBonusPercentage.length; i++) {
            if (
                _usdAmount >= refBonusAmount[i] &&
                _usdAmount < refBonusAmount[i + 1]
            ) {
                _percent = refBonusPercentage[i];
            }
        }
    }

    function getUserAllReferrals(
        address _user
    ) external view returns (address[] memory) {
        return users[_user].referrals;
    }

    function getUserReferralsCount(
        address _user
    ) external view returns (uint256) {
        return users[_user].referrals.length;
    }

    function blockTimeStamp() public view returns (uint256) {
        return block.timestamp;
    }
}
"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "evmVersion": "paris",
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    }
  }
}}

Tags:
ERC20, Token, Factory|addr:0x2d3d2219e2af2311544287b742eb5c3ee5d42126|verified:true|block:23685025|tx:0x2387a8a3b6a762bb42795440f3403a2b1850a3afe79c862fbcfdc882ed17e998|first_check:1761766106

Submitted on: 2025-10-29 20:28:26

Comments

Log in to comment.

No comments yet.