solidty9/13/2025

with draw eth

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract TokenRelease {
    uint256 public immutable startTime;
    uint256 public constant FIRST_PERIOD_DURATION = 180 days; // Approximately 6 months
    uint256 public constant SECOND_PERIOD_DURATION = 1825 days; // Approximately 5 years
    uint256 public constant FIRST_PERIOD_AMOUNT = 250_000_000 * 10**18; // 250M ETH in wei
    uint256 public constant SECOND_PERIOD_AMOUNT = 250_000_000 * 10**18; // 250M ETH in wei

    mapping(address => uint256) public shares;
    uint256 public totalShares;

    mapping(address => uint256) public claimed;
    uint256 public totalClaimed; // Tracks total ETH claimed by all users
    mapping(address => uint256) public lastClaimTime;

    address public owner;

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

    constructor(uint256 _startTime) {
        startTime = _startTime;
        owner = msg.sender;
    }

    // Allow the contract to receive ETH
    receive() external payable {}

    // Function to add beneficiaries and their shares (only owner)
    function addBeneficiary(address user, uint256 share) external onlyOwner {
        require(user != address(0), "Invalid address");
        require(share > 0, "Share must be positive");
        shares[user] += share;
        totalShares += share;
    }

    // Calculate total released ETH up to now
    function calculateTotalReleased() public view returns (uint256) {
        if (block.timestamp < startTime) {
            return 0;
        }
        
        uint256 elapsed = block.timestamp - startTime;
        
        uint256 firstReleased = 0;
        if (elapsed >= FIRST_PERIOD_DURATION) {
            firstReleased = FIRST_PERIOD_AMOUNT;
        } else {
            firstReleased = (FIRST_PERIOD_AMOUNT * elapsed) / FIRST_PERIOD_DURATION;
        }
        
        uint256 secondElapsed = (elapsed > FIRST_PERIOD_DURATION) ? elapsed - FIRST_PERIOD_DURATION : 0;
        uint256 secondReleased = 0;
        if (secondElapsed >= SECOND_PERIOD_DURATION) {
            secondReleased = SECOND_PERIOD_AMOUNT;
        } else {
            secondReleased = (SECOND_PERIOD_AMOUNT * secondElapsed) / SECOND_PERIOD_DURATION;
        }
        
        return firstReleased + secondReleased;
    }

    // Calculate pending (claimable) amount for a user
    function pending(address user) public view returns (uint256) {
        if (totalShares == 0 || shares[user] == 0) {
            return 0;
        }
        
        uint256 totalReleased = calculateTotalReleased();
        uint256 entitled = (totalReleased * shares[user]) / totalShares;
        return entitled - claimed[user];
    }

    // Claim function: can only be called once per day, claims all pending ETH
    function claim() external {
        require(block.timestamp >= lastClaimTime[msg.sender] + 1 days, "Can only claim once per day");
        uint256 amount = pending(msg.sender);
        require(amount > 0, "Nothing to claim");
        
        claimed[msg.sender] += amount;
        totalClaimed += amount; // Update total claimed amount
        lastClaimTime[msg.sender] = block.timestamp;
        
        // Transfer ETH to the claimant
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success, "ETH transfer failed");
    }

    // View claimable amount (same as pending/unclaimed)
    function getClaimable(address user) external view returns (uint256) {
        return pending(user);
    }

    // View unclaimed amount (same as pending/claimable)
    function getUnclaimed(address user) external view returns (uint256) {
        return pending(user);
    }

    // View total ETH claimed by all users
    function getTotalClaimed() external view returns (uint256) {
        return totalClaimed;
    }

    // Function for owner to withdraw ETH from the contract
    function withdrawETH(address payable to, uint256 amount) external onlyOwner {
        require(to != address(0), "Invalid address");
        require(amount > 0, "Amount must be positive");
        uint256 balance = address(this).balance;
        require(amount <= balance, "Insufficient balance");
        
        // Transfer ETH to the specified address
        (bool success, ) = to.call{value: amount}("");
        require(success, "ETH transfer failed");
    }
}