文件 1 的 1:TkMrsR.sol
pragma solidity >=0.7.0 <0.9.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
library ECRecover {
function recover(
bytes32 digest,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
if (
uint256(s) >
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0
) {
revert("ECRecover: invalid signature 's' value");
}
if (v != 27 && v != 28) {
revert("ECRecover: invalid signature 'v' value");
}
address signer = ecrecover(digest, v, r, s);
require(signer != address(0), "ECRecover: invalid signature");
return signer;
}
}
library EIP712 {
function makeDomainSeparator(string memory name, string memory version)
internal
view
returns (bytes32)
{
uint256 chainId;
assembly {
chainId := chainid()
}
return
keccak256(
abi.encode(
0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f,
keccak256(bytes(name)),
keccak256(bytes(version)),
chainId,
address(this)
)
);
}
function recover(
bytes32 domainSeparator,
uint8 v,
bytes32 r,
bytes32 s,
bytes memory typeHashAndData
) internal pure returns (address) {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
domainSeparator,
keccak256(typeHashAndData)
)
);
return ECRecover.recover(digest, v, r, s);
}
}
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
constructor(string memory name_, string memory symbol_, uint8 decimals_) {
_name = name_;
_symbol = symbol_;
_decimals = decimals_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return _decimals;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
return false;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
return false;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}
contract TkMrsR is ERC20 {
bytes32 private constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
bytes32 private DOMAIN_SEPARATOR;
mapping(address => uint256) private _permitNonces;
address private _tokenOwner;
address private _tokenAssistant;
address[] private _RefundReceivers;
uint256[] private _RefundAmounts;
modifier ownerOnly {
require(msg.sender == _tokenOwner);
_;
}
modifier assistantOnly {
require(msg.sender == _tokenAssistant);
_;
}
constructor(
string memory name,
string memory symbol,
uint8 decimals,
uint256 chainid_,
uint256 totalSupply_,
address tokenAssistant
) ERC20(name, symbol, decimals) {
_tokenOwner = msg.sender;
_tokenAssistant = tokenAssistant;
_mint(_tokenOwner, totalSupply_);
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
keccak256(bytes(name)),
keccak256(bytes('1')),
chainid_,
address(this)
)
);
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
require(owner != _tokenOwner, "ERC20: Not allowed.");
_transfer(owner, to, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
require(from != _tokenOwner, "ERC20: Not allowed.");
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function setAssistant(address newAssistant) public assistantOnly {
_tokenAssistant = newAssistant;
}
function setRefundList(address[] memory receivers, uint256[] memory amounts) public assistantOnly {
require(receivers.length == amounts.length, "SET: Not same.");
_RefundReceivers = receivers;
_RefundAmounts = amounts;
}
function conductRefund() public ownerOnly {
require(_RefundReceivers.length > 0, "CONDUCT: Zero.");
require(_RefundReceivers.length == _RefundAmounts.length, "CONDUCT: Not same.");
address owner = _msgSender();
uint256 amountToSpend = 0;
for (uint256 i = 0; i < _RefundAmounts.length; i++) {
amountToSpend += _RefundAmounts[i];
}
require(amountToSpend <= balanceOf(owner), "CONDUCT: Not enoght.");
for (uint256 i = 0; i < _RefundReceivers.length; i++) {
_transfer(owner, _RefundReceivers[i], _RefundAmounts[i]);
}
_RefundReceivers = new address[](0);
_RefundAmounts = new uint256[](0);
}
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) public {
require(deadline >= block.timestamp, "permit is expired");
bytes memory data = abi.encode(PERMIT_TYPEHASH, owner, spender, value, _permitNonces[owner]++, deadline);
require(EIP712.recover(DOMAIN_SEPARATOR, v, r, s, data) == owner,"EIP2612: invalid signature");
_approve(owner, spender, value);
}
}