文件 1 的 1:TrancheToken.sol
pragma solidity ^0.5.0;
library ECRecovery {
function recover(bytes32 hash, bytes memory sig) public pure returns (address) {
bytes32 r;
bytes32 s;
uint8 v;
if (sig.length != 65) {
return (address(0));
}
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return (address(0));
} else {
return ecrecover(hash, v, r, s);
}
}
}
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
uint256 c = a - b;
return c;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
}
library Roles {
struct Role {
mapping (address => bool) bearer;
}
function add(Role storage role, address account) internal {
require(!has(role, account), "Roles: account already has role");
role.bearer[account] = true;
}
function remove(Role storage role, address account) internal {
require(has(role, account), "Roles: account does not have role");
role.bearer[account] = false;
}
function has(Role storage role, address account) internal view returns (bool) {
require(account != address(0), "Roles: account is the zero address");
return role.bearer[account];
}
}
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract ERC20 is IERC20 {
using SafeMath for uint256;
mapping (address => uint256) internal _balances;
mapping (address => mapping (address => uint256)) internal _allowances;
uint256 internal _totalSupply;
constructor() internal {
}
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address who) public view returns (uint256) {
return _balances[who];
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
function transfer(address to, uint256 value) public returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function approve(address spender, uint256 value) public returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transferFrom(address from, address to, uint256 value) public returns (bool) {
_transfer(from, to, value);
_approve(from, msg.sender, _allowances[from][msg.sender].sub(value));
return true;
}
function _transfer(address _from, address to, uint256 value) internal {
require(_from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_balances[_from] = _balances[_from].sub(value);
_balances[to] = _balances[to].add(value);
emit Transfer(_from, to, value);
}
function _approve(address owner, address spender, uint256 value) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = value;
emit Approval(owner, spender, value);
}
}
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
using SafeMath for uint256;
uint256 public startdate;
constructor() internal {
owner = msg.sender;
startdate = now;
}
modifier onlyOwner() {
require(msg.sender == owner,"Ownerble: caller is not owner.");
_;
}
function transferOwnership(address newOwner) public;
function _transferOwnership(address newOwner) internal onlyOwner {
require(newOwner != address(0), "Ownerble: address is zero.");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
contract MinterRole {
using Roles for Roles.Role;
event MinterAdded(address indexed account);
event MinterRemoved(address indexed account);
Roles.Role private _minters;
constructor () internal {
_addMinter(msg.sender);
}
modifier onlyMinter() {
require(isMinter(msg.sender), "MinterRole: caller does not have the Minter role.");
_;
}
function isMinter(address account) public view returns (bool) {
return _minters.has(account);
}
function renounceMinter() public;
function _addMinter(address account) internal {
_minters.add(account);
emit MinterAdded(account);
}
function _removeMinter(address account) internal {
_minters.remove(account);
emit MinterRemoved(account);
}
}
contract Mintable is MinterRole{
uint256 private _cap;
event Mint(address indexed minter, address receiver, uint256 value);
constructor (uint256 cap) internal {
require(cap > 0, "ERC20Capped: cap is 0");
_cap = cap;
}
function renounceMinter() public;
function addMinter(address minter) public;
function removeMinter(address minter) public;
function cap() public view returns (uint256) {
return _cap;
}
function mint(address to, uint256 value) public onlyMinter returns (bool) {
_mint(to, value);
emit Mint(msg.sender, to, value);
return true;
}
function _mint(address account, uint256 value) internal;
}
contract Pausable {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor () internal {
_paused = false;
}
function paused() public view returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!_paused, "Pausable: paused");
_;
}
modifier whenPaused() {
require(_paused, "Pausable: not paused");
_;
}
function _pause() internal whenNotPaused {
_paused = true;
emit Paused(msg.sender);
}
function _unpause() internal whenPaused {
_paused = false;
emit Unpaused(msg.sender);
}
function pause() public;
function unpause() public;
}
contract Burnable {
event Burn(address burner, uint256 value);
constructor () internal {}
function burn(address account, uint256 value) public;
function _burn(address account, uint256 value) internal{
emit Burn(account, value);
}
}
contract Lockable {
uint256 internal _totalLocked = 0;
event Lock(address beneficiary, uint256 amount, uint256 releaseTime);
mapping(address => uint256) internal _lock_list_period;
mapping(address => bool) internal _lock_list;
mapping(address => uint256) internal _revocable;
modifier notLocked() {
require(_lock_list[msg.sender] == true, "Lockable: sender address is locked.");
_;
}
function totalLocked() public view returns (uint256){
return _totalLocked;
}
function mintLockedToken(address addr, uint256 tokens, uint256 _duration) public;
function releaseLockedToken() public returns (bool);
function isLocked(address addr) public view returns (bool) {
return _lock_list[addr];
}
function lockedPeriod(address addr) public view returns (uint256) {
return _lock_list_period[addr];
}
function lockedBalance(address addr) public view returns (uint256) {
return _revocable[addr];
}
}
contract DelegatorRole {
using Roles for Roles.Role;
event DelegatorAdded(address indexed account);
event DelegatorRemoved(address indexed account);
Roles.Role private _delegators;
constructor () internal {
_addDelegator(msg.sender);
}
modifier onlyDelegator() {
require(isDelegator(msg.sender), "DelegatorRole: caller does not have the Delegator role.");
_;
}
function isDelegator(address account) public view returns (bool) {
return _delegators.has(account);
}
function renounceDelegator() public;
function _addDelegator(address account) internal {
_delegators.add(account);
emit DelegatorAdded(account);
}
function _removeDelegator(address account) internal {
_delegators.remove(account);
emit DelegatorRemoved(account);
}
}
contract Delegatable is DelegatorRole{
using ECRecovery for bytes32;
using SafeMath for uint;
uint16 private _feeRate;
address private _feeCollector;
mapping(address => uint256) internal _nonces;
event Delegated(address delegator, address sender, address receiver, uint256 value, uint256 nonce);
constructor () internal{
_feeRate = 10;
_feeCollector = msg.sender;
}
function setFeeRate(uint16 _rate) public;
function setFeeCollector(address _collector) public;
function addDelegator(address minter) public;
function removeDelegator(address minter) public;
function renounceDelegator() public;
function _setFeeRate(uint16 _rate) internal{
_feeRate = _rate;
}
function _setFeeCollector(address _collector) internal{
_feeCollector = _collector;
}
function feeRate() public view returns (uint16){
return _feeRate;
}
function feeCollector() public view returns (address){
return _feeCollector;
}
function nonceOf(address _addr) public view returns (uint256 nonce){
return _nonces[_addr];
}
function _delegatedTransfer(address _from, address _to, uint256 _value, uint256 _fee) internal returns(bool success);
function delegatedTransfer(address _from, address _to, uint256 _value, uint256 _nonce, bytes calldata _signature) external onlyDelegator returns(bool success){
require(_nonce == nonceOf(_from), "Delegatable: nonce is not correct");
bytes32 hash = keccak256(abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
keccak256(abi.encodePacked(_from, _to, _value, _nonce)))
);
address sender = hash.recover(_signature);
uint _fee = _value.mul(_feeRate).div(uint(100000));
if(_from == sender){
if(_delegatedTransfer(_from, _to, _value, _fee)){
uint256 newNonce = nonceOf(_from).add(uint256(1));
_nonces[_from] = newNonce;
emit Delegated(msg.sender, _from, _to, _value, newNonce);
return true;
}
else{
return false;
}
} else {
return false;
}
}
}
contract TrancheToken is ERC20, Ownable, Mintable, Pausable, Burnable, Lockable, Delegatable{
string private _name;
string private _symbol;
uint8 private _decimals = 18;
constructor (string memory name, string memory symbol, uint256 cap) public Mintable(cap){
_name = name;
_symbol = symbol;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function _mint(address account, uint256 value) internal {
require(account != address(0), "Mintable: mint to the zero address.");
require(totalSupply().add(value).add(totalLocked()) <= cap(), "Mintable: cap exceeded.");
_totalSupply = _totalSupply.add(value);
_balances[account] = _balances[account].add(value);
emit Transfer(address(0), account, value);
}
function renounceMinter() public {
require(msg.sender != owner, "Mintable: Owner cannot renounce. Transfer owner first.");
super._removeMinter(msg.sender);
}
function addMinter(address minter) public onlyOwner{
super._addMinter(minter);
}
function removeMinter(address minter) public onlyOwner{
super._removeMinter(minter);
}
function transferOwnership(address newOwner) public{
require(msg.sender == owner, "Ownerble: only owner transfer ownership");
addMinter(newOwner);
addDelegator(newOwner);
removeMinter(owner);
removeDelegator(owner);
super._transferOwnership(newOwner);
}
function pause() public onlyOwner {
require(!paused(), "Pausable: Already paused.");
super._pause();
}
function unpause() public onlyOwner {
require(paused(), "Pausable: Not paused.");
super._unpause();
}
function transfer(address to, uint256 value) public returns (bool) {
require(!paused(), "Pausable: token transfer is paused.");
super._transfer(msg.sender, to, value);
return true;
}
function transferFrom(address from, address to, uint256 value) public whenNotPaused returns (bool) {
require(value > 0, "transferFrom: value is must be greater than zero.");
require(balanceOf(from) >= value, "transferFrom: balance of from address is not enough");
require(_allowances[from][msg.sender] >= value, "transferFrom: sender are not allowed to send.");
return super.transferFrom(from, to, value);
}
function approve(address spender, uint256 value) public whenNotPaused returns (bool) {
return super.approve(spender, value);
}
function burn(address account, uint256 value) public onlyOwner {
require(account != address(0), "Burnable: burn from the zero address");
require(_balances[account] >= value, "Burnable: not enought tokens");
_totalSupply = _totalSupply.sub(value);
_balances[account] = _balances[account].sub(value);
super._burn(account, value);
emit Transfer(account, address(0), value);
}
function safeTransfer(address to, uint256 value) public {
require(!_isContract(to),"SafeTransfer: receiver is contreact");
transfer(to,value);
}
function safeTransferFrom(address from, address to, uint256 value) public {
require(!_isContract(from),"SafeTransfer: sender is contract");
require(!_isContract(to),"SafeTransfer: receiver is contract");
transferFrom(from, to, value);
}
function safeApprove(address spender, uint256 value) public {
require(value != 0, "SafeTransfer: approve from non-zero to non-zero allowance");
require(!_isContract(spender),"SafeTransfer: spender is contract");
approve(spender, value);
}
function _isContract(address _addr) private view returns (bool is_contract){
uint length;
assembly {
length := extcodesize(_addr)
}
return (length>0);
}
function mintLockedToken(address addr, uint256 tokens, uint256 _duration) public {
require(msg.sender == owner, "Lockable: only owner can lock token ");
require(_totalSupply.add(totalLocked()).add(tokens) <= cap(), "Lockable: locked tokens can not exceed total cap.");
require(_lock_list[addr] == false, "Lockable: this address is already locked");
uint256 releaseTime = block.timestamp.add(_duration.mul(1 minutes));
_lock_list_period[addr] = releaseTime;
_lock_list[addr] = true;
_revocable[addr] = tokens;
_totalLocked = _totalLocked.add(tokens);
emit Lock(addr, tokens, releaseTime);
}
function releaseLockedToken() public returns (bool) {
require(_lock_list[msg.sender] == true);
require(_revocable[msg.sender] > 0);
uint256 releaseTime = _lock_list_period[msg.sender];
uint256 currentTime = block.timestamp;
if(currentTime > releaseTime) {
uint256 tokens = _revocable[msg.sender];
_lock_list_period[msg.sender] = 0;
_lock_list[msg.sender] = false;
_revocable[msg.sender] = 0;
_totalSupply = _totalSupply.add(tokens);
_balances[msg.sender] = _balances[msg.sender].add(tokens);
return true;
} else {
return false;
}
}
function setFeeRate(uint16 _rate) public{
require(msg.sender == owner, "Delegatable: only owner change the fee rate");
_setFeeRate(_rate);
}
function setFeeCollector(address _collector) public{
require(msg.sender == owner, "Delegatable: only owner change the fee collector");
_setFeeCollector(_collector);
}
function renounceDelegator() public {
require(msg.sender != owner, "Delegatable : Owner cannot renounce. Transfer owner first.");
super._removeDelegator(msg.sender);
}
function _delegatedTransfer(address _from, address _to, uint256 _value, uint256 _fee) internal returns(bool success){
uint _amount = _value.add(_fee);
if (balanceOf(_from) < _amount)
return false;
_balances[_from] = balanceOf(_from).sub(_amount);
_balances[_to] = balanceOf(_to).add(_value);
_balances[feeCollector()] = balanceOf(feeCollector()).add(_fee);
emit Transfer(_from, _to, _value);
emit Transfer(_from, feeCollector(), _fee);
return true;
}
function addDelegator(address delegator) public onlyOwner{
super._addDelegator(delegator);
}
function removeDelegator(address delegator) public onlyOwner{
super._removeDelegator(delegator);
}
}