/** * Source Code first verified at https://etherscan.io on Sunday, April 14, 2019 (UTC) */ pragma solidity 0.5.7; // ERC20 declare contract IERC20 { function totalSupply() public view returns (uint256); function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); function allowance(address owner, address spender) public view returns (uint256); function transferFrom(address from, address to, uint256 value) public returns (bool); function approve(address spender, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); event Burn(address indexed burner, uint256 value); } // SafeERC20 library SafeERC20 { function safeTransfer( IERC20 _token, address _to, uint256 _value ) internal { require(_token.transfer(_to, _value)); } function safeTransferFrom( ERC20 _token, address _from, address _to, uint256 _value ) internal { require(_token.transferFrom(_from, _to, _value)); } function safeApprove( ERC20 _token, address _spender, uint256 _value ) internal { require(_token.approve(_spender, _value)); } } // Ownable contract Ownable { address public owner; address public admin; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); constructor() public { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner); _; } modifier onlyOwnerOrAdmin() { require(msg.sender != address(0) && (msg.sender == owner || msg.sender == admin)); _; } function transferOwnership(address newOwner) onlyOwner public { require(newOwner != address(0)); require(newOwner != owner); require(newOwner != admin); emit OwnershipTransferred(owner, newOwner); owner = newOwner; } function setAdmin(address newAdmin) onlyOwner public { require(admin != newAdmin); require(owner != newAdmin); admin = newAdmin; } } // ERC20 functions contract ERC20 is IERC20, Ownable { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping(address => bool) internal locks; mapping (address => mapping (address => uint256)) private _allowed; uint256 public Max_supply = 10000000000 * (10 **18); uint256 private _totalSupply; function totalSupply() public view returns (uint256) { return _totalSupply; } function balanceOf(address owner) public view returns (uint256) { return _balances[owner]; } function allowance(address owner, address spender) public view returns (uint256) { return _allowed[owner][spender]; } function transfer(address to, uint256 value) public returns (bool) { _transfer(msg.sender, to, value); return true; } function _transfer(address from, address to, uint256 value) internal { require(to != address(0)); require(locks[msg.sender] == false); _balances[from] = _balances[from].sub(value); _balances[to] = _balances[to].add(value); emit Transfer(from, to, value); } function approve(address spender, uint256 value) public returns (bool) { _approve(msg.sender, spender, value); return true; } function _approve(address owner, address spender, uint256 value) internal { require(spender != address(0)); require(owner != address(0)); _allowed[owner][spender] = value; emit Approval(owner, spender, value); } function transferFrom(address from, address to, uint256 value) public returns (bool) { _transfer(from, to, value); _approve(from, msg.sender, _allowed[from][msg.sender].sub(value)); return true; } function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue)); return true; } function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue)); return true; } function _mint(address account, uint256 value) internal { require(account != address(0)); require(Max_supply > _totalSupply); _totalSupply = _totalSupply.add(value); _balances[account] = _balances[account].add(value); emit Transfer(address(0), account, value); } function burn(address from, uint256 value) public { _burn(from, value); } function _burn(address account, uint256 value) internal { require(account != address(0)); _totalSupply = _totalSupply.sub(value); _balances[account] = _balances[account].sub(value); emit Transfer(account, address(0), value); } function lock(address _owner) public onlyOwner returns (bool) { require(locks[_owner] == false); locks[_owner] = true; return true; } function unlock(address _owner) public onlyOwner returns (bool) { require(locks[_owner] == true); locks[_owner] = false; return true; } function showLockState(address _owner) public view returns (bool) { return locks[_owner]; } } // Pause, Mint base library Roles { struct Role { mapping (address => bool) bearer; } function add(Role storage role, address account) internal { require(account != address(0)); require(!has(role, account)); role.bearer[account] = true; } function remove(Role storage role, address account) internal { require(account != address(0)); require(has(role, account)); role.bearer[account] = false; } function has(Role storage role, address account) internal view returns (bool) { require(account != address(0)); return role.bearer[account]; } } // ERC20Detailed contract ERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; constructor (string memory name, string memory symbol, uint8 decimals) public { _name = name; _symbol = symbol; _decimals = decimals; } } // Math library Math { function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } function average(uint256 a, uint256 b) internal pure returns (uint256) { return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } } // SafeMath library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0 || b == 0) { return 0; } uint256 c = a * b; assert(c / a == b); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); // overflow check return c; } } // Pause part contract PauserRole { using Roles for Roles.Role; event PauserAdded(address indexed account); event PauserRemoved(address indexed account); Roles.Role private _pausers; constructor () internal { _addPauser(msg.sender); } modifier onlyPauser() { require(isPauser(msg.sender)); _; } function isPauser(address account) public view returns (bool) { return _pausers.has(account); } function addPauser(address account) public onlyPauser { _addPauser(account); } function renouncePauser() public { _removePauser(msg.sender); } function _addPauser(address account) internal { _pausers.add(account); emit PauserAdded(account); } function _removePauser(address account) internal { _pausers.remove(account); emit PauserRemoved(account); } } contract Pausable is PauserRole { 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); _; } modifier whenPaused() { require(_paused); _; } function pause() public onlyPauser whenNotPaused { _paused = true; emit Paused(msg.sender); } function unpause() public onlyPauser whenPaused { _paused = false; emit Unpaused(msg.sender); } } contract ERC20Pausable is ERC20, Pausable { function transfer(address to, uint256 value) public whenNotPaused returns (bool) { return super.transfer(to, value); } function transferFrom(address from, address to, uint256 value) public whenNotPaused returns (bool) { return super.transferFrom(from, to, value); } function approve(address spender, uint256 value) public whenNotPaused returns (bool) { return super.approve(spender, value); } function increaseAllowance(address spender, uint addedValue) public whenNotPaused returns (bool) { return super.increaseAllowance(spender, addedValue); } function decreaseAllowance(address spender, uint subtractedValue) public whenNotPaused returns (bool) { return super.decreaseAllowance(spender, subtractedValue); } } // Snapshot part library Arrays { function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { if (array.length == 0) { return 0; } uint256 low = 0; uint256 high = array.length; while (low < high) { uint256 mid = Math.average(low, high); if (array[mid] > element) { high = mid; } else { low = mid + 1; } } if (low > 0 && array[low - 1] == element) { return low - 1; } else { return low; } } } library Counters { using SafeMath for uint256; struct Counter { uint256 _value; } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { counter._value += 1; } function decrement(Counter storage counter) internal { counter._value = counter._value.sub(1); } } contract ERC20Snapshot is ERC20 { using SafeMath for uint256; using Arrays for uint256[]; using Counters for Counters.Counter; struct Snapshots { uint256[] ids; uint256[] values; } mapping (address => Snapshots) private _accountBalanceSnapshots; Snapshots private _totalSupplySnaphots; Counters.Counter private _currentSnapshotId; event Snapshot(uint256 id); function snapshot() public returns (uint256) { _currentSnapshotId.increment(); uint256 currentId = _currentSnapshotId.current(); emit Snapshot(currentId); return currentId; } function balanceOfAt(address account, uint256 snapshotId) public view returns (uint256) { (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]); return snapshotted ? value : balanceOf(account); } function totalSupplyAt(uint256 snapshotId) public view returns(uint256) { (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnaphots); return snapshotted ? value : totalSupply(); } function _transfer(address from, address to, uint256 value) internal { _updateAccountSnapshot(from); _updateAccountSnapshot(to); super._transfer(from, to, value); } function _mint(address account, uint256 value) internal { _updateAccountSnapshot(account); _updateTotalSupplySnapshot(); super._mint(account, value); } function _burn(address account, uint256 value) internal { _updateAccountSnapshot(account); _updateTotalSupplySnapshot(); super._burn(account, value); } function _valueAt(uint256 snapshotId, Snapshots storage snapshots) private view returns (bool, uint256) { require(snapshotId > 0); require(snapshotId <= _currentSnapshotId.current()); uint256 index = snapshots.ids.findUpperBound(snapshotId); if (index == snapshots.ids.length) { return (false, 0); } else { return (true, snapshots.values[index]); } } function _updateAccountSnapshot(address account) private { _updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account)); } function _updateTotalSupplySnapshot() private { _updateSnapshot(_totalSupplySnaphots, totalSupply()); } function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private { uint256 currentId = _currentSnapshotId.current(); if (_lastSnapshotId(snapshots.ids) < currentId) { snapshots.ids.push(currentId); snapshots.values.push(currentValue); } } function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) { if (ids.length == 0) { return 0; } else { return ids[ids.length - 1]; } } } // Mintable part 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)); _; } function isMinter(address account) public view returns (bool) { return _minters.has(account); } function addMinter(address account) public onlyMinter { _addMinter(account); } function renounceMinter() public { _removeMinter(msg.sender); } function _addMinter(address account) internal { _minters.add(account); emit MinterAdded(account); } function _removeMinter(address account) internal { _minters.remove(account); emit MinterRemoved(account); } } contract ERC20Mintable is ERC20, MinterRole { function mint(address to, uint256 value) public onlyMinter returns (bool) { _mint(to, value); return true; } } contract test is ERC20, ERC20Detailed, ERC20Snapshot, ERC20Pausable, ERC20Mintable { uint8 public constant DECIMALS = 18; uint256 public constant INITIAL_SUPPLY = 0 * (10 ** uint256(DECIMALS)); constructor () public ERC20Detailed("test", "test", DECIMALS) { _mint(msg.sender, INITIAL_SUPPLY); } }