torn-token/contracts/Voucher.sol

67 lines
2.0 KiB
Solidity

/**
* This is tornado.cash airdrop for early adopters. In order to claim your TORN token please follow https://tornado.cash/airdrop
*/
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "./ENS.sol";
contract Voucher is ERC20("TornadoCash voucher for early adopters", "vTORN"), EnsResolve {
using SafeERC20 for IERC20;
IERC20 public immutable torn;
uint256 public immutable expiresAt;
address public immutable governance;
mapping(address => bool) public allowedTransferee;
struct Recipient {
address to;
uint256 amount;
}
constructor(
bytes32 _torn,
bytes32 _governance,
uint256 _duration,
Recipient[] memory _airdrops
) public {
torn = IERC20(resolve(_torn));
governance = resolve(_governance);
expiresAt = blockTimestamp().add(_duration);
for (uint256 i = 0; i < _airdrops.length; i++) {
_mint(_airdrops[i].to, _airdrops[i].amount);
allowedTransferee[_airdrops[i].to] = true;
}
}
function redeem() external {
require(blockTimestamp() < expiresAt, "Airdrop redeem period has ended");
uint256 amount = balanceOf(msg.sender);
_burn(msg.sender, amount);
torn.safeTransfer(msg.sender, amount);
}
function rescueExpiredTokens() external {
require(blockTimestamp() >= expiresAt, "Airdrop redeem period has not ended yet");
torn.safeTransfer(governance, torn.balanceOf(address(this)));
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal override {
super._beforeTokenTransfer(from, to, amount);
require(to == address(0) || from == address(0) || allowedTransferee[from], "ERC20: transfer is not allowed");
}
function blockTimestamp() public view virtual returns (uint256) {
return block.timestamp;
}
}