pragma solidity ^0.4.21;
// File: contracts/ownership/MultiOwnable.sol
/**
* @title MultiOwnable
* @dev The MultiOwnable contract has owners addresses and provides basic authorization control
* functions, this simplifies the implementation of "users permissions".
*/
contract MultiOwnable {
address public manager; // address used to set owners
address[] public owners;
mapping(address => bool) public ownerByAddress;
event SetOwners(address[] owners);
modifier onlyOwner() {
require(ownerByAddress[msg.sender] == true);
_;
}
/**
* @dev MultiOwnable constructor sets the manager
*/
function MultiOwnable() public {
manager = msg.sender;
}
/**
* @dev Function to set owners addresses
*/
function setOwners(address[] _owners) public {
require(msg.sender == manager);
_setOwners(_owners);
}
function _setOwners(address[] _owners) internal {
for(uint256 i = 0; i < owners.length; i++) {
ownerByAddress[owners[i]] = false;
}
for(uint256 j = 0; j < _owners.length; j++) {
ownerByAddress[_owners[j]] = true;
}
owners = _owners;
SetOwners(_owners);
}
function getOwners() public constant returns (address[]) {
return owners;
}
}
// File: contracts/math/SafeMath.sol
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
contract SafeMath {
/**
* @dev constructor
*/
function SafeMath() public {
}
function safeMul(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function safeDiv(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a / b;
return c;
}
function safeSub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(a >= b);
return a - b;
}
function safeAdd(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
// File: contracts/token/IERC20Token.sol
/**
* @title IERC20Token - ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
contract IERC20Token {
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
function balanceOf(address _owner) public constant returns (uint256 balance);
function transfer(address _to, uint256 _value) public returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public returns (bool success);
function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
// File: contracts/token/ERC20Token.sol
/**
* @title ERC20Token - ERC20 base implementation
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
contract ERC20Token is IERC20Token, SafeMath {
mapping (address => uint256) public balances;
mapping (address => mapping (address => uint256)) public allowed;
function transfer(address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(balances[msg.sender] >= _value);
balances[msg.sender] = safeSub(balances[msg.sender], _value);
balances[_to] = safeAdd(balances[_to], _value);
Transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value);
balances[_to] = safeAdd(balances[_to], _value);
balances[_from] = safeSub(balances[_from], _value);
allowed[_from][msg.sender] = safeSub(allowed[_from][msg.sender], _value);
Transfer(_from, _to, _value);
return true;
}
function balanceOf(address _owner) public constant returns (uint256) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) public returns (bool) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public constant returns (uint256) {
return allowed[_owner][_spender];
}
}
// File: contracts/token/ITokenEventListener.sol
/**
* @title ITokenEventListener
* @dev Interface which should be implemented by token listener
*/
interface ITokenEventListener {
/**
* @dev Function is called after token transfer/transferFrom
* @param _from Sender address
* @param _to Receiver address
* @param _value Amount of tokens
*/
function onTokenTransfer(address _from, address _to, uint256 _value) external;
}
// File: contracts/token/ManagedToken.sol
/**
* @title ManagedToken
* @dev ERC20 compatible token with issue and destroy facilities
* @dev All transfers can be monitored by token event listener
*/
contract ManagedToken is ERC20Token, MultiOwnable {
bool public allowTransfers = false;
bool public issuanceFinished = false;
ITokenEventListener public eventListener;
event AllowTransfersChanged(bool _newState);
event Issue(address indexed _to, uint256 _value);
event Destroy(address indexed _from, uint256 _value);
event IssuanceFinished();
modifier transfersAllowed() {
require(allowTransfers);
_;
}
modifier canIssue() {
require(!issuanceFinished);
_;
}
/**
* @dev ManagedToken constructor
* @param _listener Token listener(address can be 0x0)
* @param _owners Owners list
*/
function ManagedToken(address _listener, address[] _owners) public {
if(_listener != address(0)) {
eventListener = ITokenEventListener(_listener);
}
_setOwners(_owners);
}
/**
* @dev Enable/disable token transfers. Can be called only by owners
* @param _allowTransfers True - allow False - disable
*/
function setAllowTransfers(bool _allowTransfers) external onlyOwner {
allowTransfers = _allowTransfers;
AllowTransfersChanged(_allowTransfers);
}
/**
* @dev Set/remove token event listener
* @param _listener Listener address (Contract must implement ITokenEventListener interface)
*/
function setListener(address _listener) public onlyOwner {
if(_listener != address(0)) {
eventListener = ITokenEventListener(_listener);
} else {
delete eventListener;
}
}
function transfer(address _to, uint256 _value) public transfersAllowed returns (bool) {
bool success = super.transfer(_to, _value);
if(hasListener() && success) {
eventListener.onTokenTransfer(msg.sender, _to, _value);
}
return success;
}
function transferFrom(address _from, address _to, uint256 _value) public transfersAllowed returns (bool) {
bool success = super.transferFrom(_from, _to, _value);
if(hasListener() && success) {
eventListener.onTokenTransfer(_from, _to, _value);
}
return success;
}
function hasListener() internal view returns(bool) {
if(eventListener == address(0)) {
return false;
}
return true;
}
/**
* @dev Issue tokens to specified wallet
* @param _to Wallet address
* @param _value Amount of tokens
*/
function issue(address _to, uint256 _value) external onlyOwner canIssue {
totalSupply = safeAdd(totalSupply, _value);
balances[_to] = safeAdd(balances[_to], _value);
Issue(_to, _value);
Transfer(address(0), _to, _value);
}
/**
* @dev Destroy tokens on specified address (Called by owner or token holder)
* @dev Fund contract address must be in the list of owners to burn token during refund
* @param _from Wallet address
* @param _value Amount of tokens to destroy
*/
function destroy(address _from, uint256 _value) external {
require(ownerByAddress[msg.sender] || msg.sender == _from);
require(balances[_from] >= _value);
totalSupply = safeSub(totalSupply, _value);
balances[_from] = safeSub(balances[_from], _value);
Transfer(_from, address(0), _value);
Destroy(_from, _value);
}
/**
* @dev Increase the amount of tokens that an owner allowed to a spender.
*
* approve should be called when allowed[_spender] == 0. To increment
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From OpenZeppelin StandardToken.sol
* @param _spender The address which will spend the funds.
* @param _addedValue The amount of tokens to increase the allowance by.
*/
function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
allowed[msg.sender][_spender] = safeAdd(allowed[msg.sender][_spender], _addedValue);
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
/**
* @dev Decrease the amount of tokens that an owner allowed to a spender.
*
* approve should be called when allowed[_spender] == 0. To decrement
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From OpenZeppelin StandardToken.sol
* @param _spender The address which will spend the funds.
* @param _subtractedValue The amount of tokens to decrease the allowance by.
*/
function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
uint oldValue = allowed[msg.sender][_spender];
if (_subtractedValue > oldValue) {
allowed[msg.sender][_spender] = 0;
} else {
allowed[msg.sender][_spender] = safeSub(oldValue, _subtractedValue);
}
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
/**
* @dev Finish token issuance
* @return True if success
*/
function finishIssuance() public onlyOwner returns (bool) {
issuanceFinished = true;
IssuanceFinished();
return true;
}
}
// File: contracts/token/TransferLimitedToken.sol
/**
* @title TransferLimitedToken
* @dev Token with ability to limit transfers within wallets included in limitedWallets list for certain period of time
*/
contract TransferLimitedToken is ManagedToken {
uint256 public constant LIMIT_TRANSFERS_PERIOD = 365 days;
mapping(address => bool) public limitedWallets;
uint256 public limitEndDate;
address public limitedWalletsManager;
bool public isLimitEnabled;
modifier onlyManager() {
require(msg.sender == limitedWalletsManager);
_;
}
/**
* @dev Check if transfer between addresses is available
* @param _from From address
* @param _to To address
*/
modifier canTransfer(address _from, address _to) {
require(now >= limitEndDate || !isLimitEnabled || (!limitedWallets[_from] && !limitedWallets[_to]));
_;
}
/**
* @dev TransferLimitedToken constructor
* @param _limitStartDate Limit start date
* @param _listener Token listener(address can be 0x0)
* @param _owners Owners list
* @param _limitedWalletsManager Address used to add/del wallets from limitedWallets
*/
function TransferLimitedToken(
uint256 _limitStartDate,
address _listener,
address[] _owners,
address _limitedWalletsManager
) public ManagedToken(_listener, _owners)
{
limitEndDate = _limitStartDate + LIMIT_TRANSFERS_PERIOD;
isLimitEnabled = true;
limitedWalletsManager = _limitedWalletsManager;
}
/**
* @dev Add address to limitedWallets
* @dev Can be called only by manager
*/
function addLimitedWalletAddress(address _wallet) public {
require(msg.sender == limitedWalletsManager || ownerByAddress[msg.sender]);
limitedWallets[_wallet] = true;
}
/**
* @dev Del address from limitedWallets
* @dev Can be called only by manager
*/
function delLimitedWalletAddress(address _wallet) public onlyManager {
limitedWallets[_wallet] = false;
}
/**
* @dev Disable transfer limit manually. Can be called only by manager
*/
function disableLimit() public onlyManager {
isLimitEnabled = false;
}
function transfer(address _to, uint256 _value) public canTransfer(msg.sender, _to) returns (bool) {
return super.transfer(_to, _value);
}
function transferFrom(address _from, address _to, uint256 _value) public canTransfer(_from, _to) returns (bool) {
return super.transferFrom(_from, _to, _value);
}
function approve(address _spender, uint256 _value) public canTransfer(msg.sender, _spender) returns (bool) {
return super.approve(_spender,_value);
}
}
// File: contracts/AbyssToken.sol
contract AbyssToken is TransferLimitedToken {
uint256 public constant SALE_END_TIME = 1526479200; // 16.05.2018 14:00:00 UTC
function AbyssToken(address _listener, address[] _owners, address manager) public
TransferLimitedToken(SALE_END_TIME, _listener, _owners, manager)
{
name = "ABYSS";
symbol = "ABYSS";
decimals = 18;
}
}
{
"compilationTarget": {
"AbyssToken.sol": "AbyssToken"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"owners","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"disableLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"SALE_END_TIME","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"allowTransfers","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"limitedWallets","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"limitedWalletsManager","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"issuanceFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"manager","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowed","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"LIMIT_TRANSFERS_PERIOD","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"}],"name":"delLimitedWalletAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"issue","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"limitEndDate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOwners","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_value","type":"uint256"}],"name":"destroy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_listener","type":"address"}],"name":"setListener","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"finishIssuance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"eventListener","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isLimitEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_allowTransfers","type":"bool"}],"name":"setAllowTransfers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"ownerByAddress","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"}],"name":"addLimitedWalletAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_owners","type":"address[]"}],"name":"setOwners","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_listener","type":"address"},{"name":"_owners","type":"address[]"},{"name":"manager","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_newState","type":"bool"}],"name":"AllowTransfersChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Issue","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Destroy","type":"event"},{"anonymous":false,"inputs":[],"name":"IssuanceFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owners","type":"address[]"}],"name":"SetOwners","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]