// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; /** * @title TestUSDT * @dev 用于测试环境的 USDT 代币合约 * * 特性: * - 6 位小数 (与真实 USDT 一致) * - 部署者可以自由 mint * - 任何人都可以调用 faucet 获取测试代币 * * 部署到: * - BSC Testnet (Chain ID: 97) * - KAVA Testnet (Chain ID: 2221) */ contract TestUSDT is ERC20, Ownable { uint256 public constant FAUCET_AMOUNT = 1000 * 10**6; // 1000 USDT uint256 public constant FAUCET_COOLDOWN = 1 hours; mapping(address => uint256) public lastFaucetTime; constructor() ERC20("Test USDT", "tUSDT") Ownable(msg.sender) { // 初始铸造 1,000,000 USDT 给部署者 _mint(msg.sender, 1_000_000 * 10**6); } /** * @dev 返回 6 位小数 (与真实 USDT 一致) */ function decimals() public pure override returns (uint8) { return 6; } /** * @dev Owner 可以铸造任意数量的代币 */ function mint(address to, uint256 amount) external onlyOwner { _mint(to, amount); } /** * @dev 水龙头: 任何人都可以每小时领取 1000 tUSDT */ function faucet() external { require( block.timestamp >= lastFaucetTime[msg.sender] + FAUCET_COOLDOWN, "Faucet: Please wait 1 hour between requests" ); lastFaucetTime[msg.sender] = block.timestamp; _mint(msg.sender, FAUCET_AMOUNT); } /** * @dev 批量空投 (Owner only) */ function airdrop(address[] calldata recipients, uint256 amount) external onlyOwner { for (uint256 i = 0; i < recipients.length; i++) { _mint(recipients[i], amount); } } }