TIMBER2024 / TimberTime

Project ♠️♾️TimberTime🧬
Apache License 2.0
0 stars 0 forks source link

$TTcoin🔺contract 2024oct26 #3

Open TIMBER2024 opened 1 month ago

TIMBER2024 commented 1 month ago

TimberTime coin contract 🔺per grok

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

import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/access/Ownable2Step.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol";

contract TimberTimeToken is ERC20, ERC20Burnable, Ownable2Step, Pausable, ReentrancyGuard { using SafeMath for uint256; string public constant NAME = "TimberTime"; string public constant SYMBOL = "TT";

address public immutable timHagedorn = 0x19a0f118F028Edbe6e42B7E8986a8f696E6c4920; // Address of Tim Hagedorn, the contract owner

uint8 private constant _decimals = 18;
uint256 private constant _initialSupply = 1000000000 * (10 ** uint256(_decimals)); // 1 billion tokens
uint256 public constant MAX_SUPPLY = 1000000000 * (10 ** uint256(_decimals)); // Cap at 1 billion tokens
uint256 public transferFeeRate = 5; // 0.05% fee rate

// Whitelist to control who can interact with the token
mapping(address => bool) public whitelist;

// Events
event FeeRateChanged(uint256 oldFeeRate, uint256 newFeeRate);
event AddressWhitelisted(address indexed user, bool status);
event TokensLocked(address indexed beneficiary, uint256 amount, uint256 unlockDate);
event Staked(address indexed user, uint256 amount);
event Unstaked(address indexed user, uint256 amount, uint256 reward);

// Staking
mapping(address => uint256) public stakedAmounts;
mapping(address => uint256) public stakeStartTime;
uint256 public constant STAKING_REWARD_RATE = 1; // 1% per year

constructor() ERC20(NAME, SYMBOL) {
    _mint(msg.sender, _initialSupply);
    whitelist[msg.sender] = true; // Initial deployer should be whitelisted
}

// Minting can only be done by the contract owner
function mint(address account, uint256 amount) public onlyOwner whenNotPaused {
    require(totalSupply() + amount <= MAX_SUPPLY, "Cannot mint beyond maximum supply");
    _mint(account, amount);
}

// Override transfer function to include a fee mechanism and whitelist check
function _transfer(address sender, address recipient, uint256 amount) internal virtual override whenNotPaused {
    require(sender != address(0), "ERC20: transfer from the zero address");
    require(recipient != address(0), "ERC20: transfer to the zero address");
    require(whitelist[sender] || whitelist[recipient], "One of the addresses must be whitelisted");

    uint256 feeAmount = amount.mul(transferFeeRate).div(10000); // Assuming 4 decimal places for percentage
    uint256 transferAmount = amount.sub(feeAmount);

    super._transfer(sender, recipient, transferAmount);
    if (feeAmount > 0) {
        _burn(sender, feeAmount); // Burn the fee
    }

    emit Transfer(sender, recipient, amount);
}

// Function to change fee rate
function setTransferFeeRate(uint256 _transferFeeRate) public onlyOwner {
    require(_transferFeeRate <= 100, "Fee must not exceed 1%");
    emit FeeRateChanged(transferFeeRate, _transferFeeRate);
    transferFeeRate = _transferFeeRate;
}

// Governance functions
function pause() public onlyOwner {
    _pause();
}

function unpause() public onlyOwner {
    _unpause();
}

// Whitelist management
function addToWhitelist(address _address) public onlyOwner {
    whitelist[_address] = true;
    emit AddressWhitelisted(_address, true);
}

function removeFromWhitelist(address _address) public onlyOwner {
    whitelist[_address] = false;
    emit AddressWhitelisted(_address, false);
}

// Staking functionality
function stake(uint256 amount) external whenNotPaused {
    require(amount > 0, "Cannot stake 0");
    stakedAmounts[msg.sender] = stakedAmounts[msg.sender].add(amount);
    stakeStartTime[msg.sender] = block.timestamp;
    _transfer(msg.sender, address(this), amount); // Stake by transferring to contract
    emit Staked(msg.sender, amount);
}

function unstake(uint256 amount) external whenNotPaused nonReentrant {
    require(stakedAmounts[msg.sender] >= amount, "Not enough staked");
    uint256 reward = calculateReward(msg.sender, amount);
    stakedAmounts[msg.sender] = stakedAmounts[msg.sender].sub(amount);
    _transfer(address(this), msg.sender, amount.add(reward)); // Unstake and send reward
    emit Unstaked(msg.sender, amount, reward);
}

function calculateReward(address account, uint256 amount) public view returns (uint256) {
    uint256 timeStaked = block.timestamp.sub(stakeStartTime[account]);
    uint256 dailyRewardRate = STAKING_REWARD_RATE.mul(1e18).div(365 days); // Convert annual rate to daily rate
    uint256 reward = amount.mul(timeStaked).mul(dailyRewardRate).div(1e18); // Avoid precision loss with 1e18
    return reward;
}

// Lock tokens functionality with events
mapping(address => LockInfo) private _locked;

struct LockInfo {
    uint256 amount;
    uint256 releaseTime;
}

function lockTokens(address _beneficiary, uint256 _amount, uint256 _unlockDate) public onlyOwner whenNotPaused {
    require(_unlockDate > block.timestamp, "Unlock time should be in the future");
    require(_amount <= balanceOf(owner()), "Not enough tokens to lock");
    _transfer(owner(), address(this), _amount);
    _locked[_beneficiary] = LockInfo(_amount, _unlockDate);
    emit TokensLocked(_beneficiary, _amount, _unlockDate);
}

function unlockTokens() public whenNotPaused {
    LockInfo storage lockInfo = _locked[msg.sender];
    require(block.timestamp >= lockInfo.releaseTime, "Tokens are still locked");
    require(lockInfo.amount > 0, "No tokens locked for this address");

    uint256 amount = lockInfo.amount;
    _locked[msg.sender] = LockInfo(0, block.timestamp); // Reset lock info

    _transfer(address(this), msg.sender, amount);
}

} 

TIMBER2024 commented 1 month ago