1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| pragma solidity ^0.8.0;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract THLMStakingToken is ERC20,Ownable { constructor() Ownable(msg.sender) ERC20("THLMStakingToken", "TST"){ }
function mint(address to, uint256 amount) external onlyOwner { _mint(to, amount); }
function burn(address from, uint256 amount) external onlyOwner { _burn(from, amount); } }
contract THLMAirdrop is Ownable, Pausable, ReentrancyGuard {
address public THLMTokenAddress; address public stakeingToken; bool public emergencyUnstakeFlag;
uint256 internal _unStakeTimestamp = block.timestamp + 2 * 365 * 24 * 60 * 60;
event ThlmStake(address user,uint256 oldAmount,uint256 newAmount); event ThlmUnstake(address user, uint256 unstakeAmount);
constructor(address ownerAddress, address _THMLTokenAddress) Ownable(ownerAddress) { THLMTokenAddress = _THMLTokenAddress; emergencyUnstakeFlag = false; bytes memory bytecode = type(THLMStakingToken).creationCode; bytes32 salt = keccak256(abi.encodePacked(address(this))); address _stakingToken; assembly { _stakingToken := create2(0, add(bytecode, 32), mload(bytecode), salt) } stakeingToken = _stakingToken; }
function updateEmergeceUnstakeFlag(bool flag) public onlyOwner { emergencyUnstakeFlag = flag; }
function pause() public onlyOwner { _pause(); }
function unpause() public onlyOwner { _unpause(); }
function queryUnstake(address _address) public view returns (uint256 unstakeAmount) { unstakeAmount = THLMStakingToken(stakeingToken).balanceOf(_address); }
function stake(uint256 amount) public nonReentrant whenNotPaused { uint256 oldAmount = queryUnstake(msg.sender); require(amount > 0, "invalid amount");
IERC20(THLMTokenAddress).transferFrom(msg.sender, address(this), amount); THLMStakingToken(stakeingToken).mint(msg.sender, amount); uint256 newAmount = queryUnstake(msg.sender); emit ThlmStake(msg.sender, oldAmount,newAmount);
}
function unstake() public nonReentrant whenNotPaused { require(block.timestamp > _unStakeTimestamp, "invalid timestamp"); _unstake(); }
function emergencyUnstake() public nonReentrant whenNotPaused { require(emergencyUnstakeFlag, "emergency unstake is not allowed"); _unstake(); }
function _unstake() internal { uint256 unstakeAmount = queryUnstake(msg.sender); require(unstakeAmount > 0, "invalid amount"); IERC20(THLMTokenAddress).transfer(msg.sender, unstakeAmount); THLMStakingToken(stakeingToken).burn(msg.sender, unstakeAmount); emit ThlmUnstake(msg.sender,unstakeAmount); } }
|