// SPDX-License-Identifier: MIT pragma solidity 0.8.19; import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; /** * @title CECDistributor * @dev CECDistributor is a contract for distributing CEC token with unlock time * after all data is set, transfer owner to timelock contract */ contract CECDistributor is ReentrancyGuard, Pausable, Ownable { using SafeERC20 for IERC20; mapping(address account => uint256 amount) public balanceMap; // unlock time for this distributor uint256 public unlockTime; IERC20 public immutable cecToken; event EventBalanceUpdated(address indexed account, uint256 amount); event EventUnlockTimeUpdated(uint256 unlockTime); event EventCECClaimed(address indexed user, address indexed to, uint256 amount); constructor(address _cecToken, uint256 _unlockTime) { cecToken = IERC20(_cecToken); unlockTime = _unlockTime; } /** * @dev update pause state */ function pause() external onlyOwner { _pause(); } /** * @dev update unpause state */ function unpause() external onlyOwner { _unpause(); } function updateBalance(address account, uint256 amount) external onlyOwner { balanceMap[account] = amount; emit EventBalanceUpdated(account, amount); } function updateBalances(address[] calldata accounts, uint256[] calldata amounts) external onlyOwner { require(accounts.length == amounts.length, "CECDistributor: invalid input"); for (uint256 i = 0; i < accounts.length; i++) { balanceMap[accounts[i]] = amounts[i]; emit EventBalanceUpdated(accounts[i], amounts[i]); } } function updateUnlockTime(uint256 _unlockTime) external onlyOwner { unlockTime = _unlockTime; emit EventUnlockTimeUpdated(_unlockTime); } function withdrawToken(address to, uint256 amount) external onlyOwner { require(to != address(0), "CECDistributor: invalid address"); cecToken.safeTransfer(to, amount); } function claim( address to ) external nonReentrant whenNotPaused { require(block.timestamp > unlockTime, "CECDistributor: not unlock time"); require(to != address(0), "CECDistributor: invalid address"); address _user = _msgSender(); uint256 amount = balanceMap[_user]; require(amount > 0, "CECDistributor: no balance"); balanceMap[_user] = 0; cecToken.safeTransfer(to, amount); emit EventCECClaimed(_user, to, amount); } }