账户
0xd4...23a0
0xD4...23a0

0xD4...23a0

US$0.00
此合同的源代码已经过验证!
合同元数据
编译器
0.8.19+commit.7dd6d404
语言
Solidity
合同源代码
文件 1 的 1:Presale.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface IERC20 {
    function transfer(address to, uint256 amount) external returns (bool);
    function balanceOf(address tokenOwner) external view returns (uint256 balance);
}

contract Presale {
    address public owner;
    IERC20 public token; 
    uint256 public totalETHRaised;
    uint256 public presaleStartTime; 
    uint256 public presaleEndTime;
    uint256 public tokenPricePerETH; // Number of tokens per 1 ETH
    bool public presaleActive = false;

    mapping(address => uint256) public ETHContributions;
    mapping(address => uint256) public tokenBalances;
    bool public withdrawalAllowed = false;

    event PresaleStarted(uint256 startTime, uint256 endTime);
    event PresaleStopped();
    event PriceChanged(uint256 newPrice);
    event ETHContributed(address indexed contributor, uint256 amount);
    event TokensClaimed(address indexed claimer, uint256 amount);

    mapping(address => uint256) public lastClaimTime;
    mapping(address => uint256) public claimedAmount;
    uint256 public constant minDaysBetweenClaims = 7 days;

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    constructor(address tokenAddress, uint256 _tokenPricePerETH) {
        owner = msg.sender;
        token = IERC20(tokenAddress);
        tokenPricePerETH = _tokenPricePerETH;
    }

    function startPresale(uint256 duration) public onlyOwner {
        presaleStartTime = block.timestamp;
        presaleEndTime = presaleStartTime + duration;
        presaleActive = true;
        emit PresaleStarted(presaleStartTime, presaleEndTime);
    }

    function stopPresale() public onlyOwner {
        presaleActive = false;
        presaleEndTime = block.timestamp;
        emit PresaleStopped();
    }

    function setTokenPricePerETH(uint256 newPrice) public onlyOwner {
        require(presaleActive, "Presale is not active");
        require(block.timestamp < presaleEndTime, "Cannot change price after presale ended");
        tokenPricePerETH = newPrice;
        emit PriceChanged(newPrice);
    }

    function contribute() public payable {
        require(presaleActive, "Presale is not active");
        require(block.timestamp < presaleEndTime, "Presale ended");
        payable(owner).transfer(msg.value);
        
        totalETHRaised += msg.value;
        uint256 tokenAmount = msg.value * tokenPricePerETH;
        
       tokenBalances[msg.sender] += tokenAmount;

        ETHContributions[msg.sender] += msg.value;
        emit ETHContributed(msg.sender, msg.value);
    }

    function claimTokens() public {
        require(!presaleActive, "Presale is active");
        require(withdrawalAllowed, "Withdrawals not Enabled yet");
        require(block.timestamp > presaleEndTime, "Presale not ended");
        require(ETHContributions[msg.sender] > 0, "No contribution made");
        
        uint256 tokenAmount = tokenBalances[msg.sender];
        
        // Calculate the number of days since the last claim
        uint256 daysSinceLastClaim = block.timestamp - lastClaimTime[msg.sender];
        
        // Ensure the user has waited at least minDaysBetweenClaims
        require(daysSinceLastClaim >= minDaysBetweenClaims, "Minimum time between claims not met");
        
        // Calculate the amount to claim (25% of tokens)
        uint256 amountToClaim = (tokenAmount * 25) / 100;
        
        // Ensure the total claimed amount doesn't exceed 100%
        require(claimedAmount[msg.sender] + amountToClaim <= tokenAmount, "Total claimed exceeds 100%");
        
        // Update the last claim time and claimed amount
        lastClaimTime[msg.sender] = block.timestamp;
        claimedAmount[msg.sender] += amountToClaim;

         // Transfer tokens to the sender
        require(token.transfer(msg.sender, amountToClaim), "Token transfer failed");
        
        emit TokensClaimed(msg.sender, amountToClaim);
    }

    receive() external payable {
        contribute();
    }

    function AmountTobeClaimed(address _investor) public view returns(uint256){
        return tokenBalances[_investor];
    }

    function RemainingAmountTobeClaimed(address _investor) public view returns(uint256){
        return tokenBalances[_investor] - claimedAmount[_investor];
    }

    function saveRemainingTokens(address tokenAddress) external onlyOwner {
        IERC20 token1 = IERC20(tokenAddress);
        uint256 tokenBalance = token1.balanceOf(address(this));
        token1.transfer(owner, tokenBalance);
    }

    function toggleWithdrawals() public onlyOwner {
        withdrawalAllowed = !withdrawalAllowed;
    }

}
设置
{
  "compilationTarget": {
    "Presale.sol": "Presale"
  },
  "evmVersion": "paris",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenPricePerETH","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contributor","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHContributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"PresaleStarted","type":"event"},{"anonymous":false,"inputs":[],"name":"PresaleStopped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"PriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensClaimed","type":"event"},{"inputs":[{"internalType":"address","name":"_investor","type":"address"}],"name":"AmountTobeClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"ETHContributions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_investor","type":"address"}],"name":"RemainingAmountTobeClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contribute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastClaimTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minDaysBetweenClaims","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"saveRemainingTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setTokenPricePerETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"startPresale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopPresale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenPricePerETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalETHRaised","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]