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");
}
}