pragma solidity 0.5.7;
import "./SafeMath.sol";
import "./Utils.sol";
contract ERC20 {
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);
function totalSupply() public view returns (uint256);
function balanceOf(address who) public view returns (uint256);
function transfer(address to, uint256 value) public returns (bool);
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
}
/**
* @title ERC677 transferAndCall token interface
* @dev See https://github.com/ethereum/EIPs/issues/677 for specification and
* discussion.
*
* We deviate from the specification and we don't define a tokenfallback. That means
* tranferAndCall can specify the function to call (bytes4(sha3("setN(uint256)")))
* and its arguments, and the respective function is called.
*
* If an invalid function is called, its default function (if implemented) is called.
*
* We also deviate from ERC865 and added a pre signed transaction for transferAndCall.
*/
/*
Notes on signature malleability: Ethereum took the same
precaution as in bitcoin was used to prevent that:
https://github.com/ethereum/go-ethereum/blob/master/vendor/github.com/btcsuite/btcd/btcec/signature.go#L48
https://github.com/ethereum/go-ethereum/blob/master/crypto/signature_test.go
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md
However, ecrecover still allows ambigous signatures. Thus, recover that wraps ecrecover checks for ambigous
signatures and only allows unique signatures.
*/
contract ERC865Plus677ish {
event TransferAndCall(address indexed _from, address indexed _to, uint256 _value, bytes4 _methodName, bytes _args);
function transferAndCall(address _to, uint256 _value, bytes4 _methodName, bytes memory _args) public returns (bytes memory);
event TransferPreSigned(address indexed _from, address indexed _to, address indexed _delegate,
uint256 _amount, uint256 _fee);
event TransferAndCallPreSigned(address indexed _from, address indexed _to, address indexed _delegate,
uint256 _amount, uint256 _fee, bytes4 _methodName, bytes _args);
function transferPreSigned(bytes memory _signature, address _to, uint256 _value,
uint256 _fee, uint256 _nonce) public returns (bool);
function transferAndCallPreSigned(bytes memory _signature, address _to, uint256 _value,
uint256 _fee, uint256 _nonce, bytes4 _methodName, bytes memory _args) public returns (bytes memory);
}
contract DOS is ERC20, ERC865Plus677ish {
using SafeMath for uint256;
string public constant name = "DOS Token";
string public constant symbol = "DOS";
uint8 public constant decimals = 18;
mapping(address => uint256) private balances;
mapping(address => mapping(address => uint256)) private allowed;
// nonces of transfers performed
mapping(bytes => bool) private signatures;
mapping(address => mapping (uint256 => bool)) private nonces;
mapping(address => bool) private contractWhitelist;
uint256 private totalSupply_;
uint256 public constant maxSupply = 900000000 * (10 ** uint256(decimals));
// token lockups
mapping(address => uint256) private lockups;
// ownership
address public owner;
address public tmpOwner;
address public admin1;
address public admin2;
//3 admins can disable the transfers, however, the balances remain.
//this can be used to migrate to another contract. This flag can only
//be set by 3 admins.
bool public transfersEnabled1 = true;
bool public transfersEnabled2 = true;
bool public transfersEnabled3 = true;
// minting
bool public mintingDone = false;
//vesting variables, check dates with https://www.epochconverter.com/ and https://www.unixtimestamp.com/
uint256 public constant firstFeb19 = 1548979200;
uint256 public constant sixMonth = 6 * 30 days;
event TokensLocked(address indexed _holder, uint256 _timeout);
constructor() public {
owner = msg.sender;
}
/**
* @dev Allows the current owner to transfer the ownership.
* @param _newOwner The address to transfer ownership to.
*/
function transferOwnership(address _newOwner) public {
require(owner == msg.sender);
require(_newOwner != address(0));
require(_newOwner != admin1);
require(_newOwner != admin2);
require(_newOwner != owner); //sanity check
tmpOwner = _newOwner;
}
function claimOwnership() public {
require(tmpOwner == msg.sender);
owner = tmpOwner;
tmpOwner = address(0);
}
function setAdmin(address _admin1, address _admin2) public {
require(owner == msg.sender);
require(!mintingDone);
require(_admin1 != address(0));
require(_admin1 != owner);
require(_admin2 != address(0));
require(_admin2 != owner);
require(_admin1 != _admin2);
admin1 = _admin1;
admin2 = _admin2;
}
function addWhitelist(address contractAddress) public {
require(owner == msg.sender || admin1 == msg.sender || admin2 == msg.sender);
contractWhitelist[contractAddress] = true;
}
function removeWhitelist(address contractAddress) public {
require(owner == msg.sender || admin1 == msg.sender || admin2 == msg.sender);
delete contractWhitelist[contractAddress];
}
// minting functionality
function mint(address[] calldata _recipients, uint256[] calldata _amounts) external {
require(owner == msg.sender);
require(!mintingDone);
require(_recipients.length == _amounts.length);
require(_recipients.length <= 255);
for (uint8 i = 0; i < _recipients.length; i++) {
uint256 amount = _amounts[i];
totalSupply_ = totalSupply_.add(amount);
require(totalSupply_ <= maxSupply); // enforce maximum token supply
address recipient = _recipients[i];
balances[recipient] = balances[recipient].add(amount);
emit Transfer(address(0), recipient, amount);
}
}
/**
* @param _sixMonthCliff Number of a six month cliff. E.g., 1 is for 6 month, 2 is for 12 month, 3 is for 18 month, etc.
*/
function lockTokens(address[] calldata _holders, uint256[] calldata _sixMonthCliff) external {
require(owner == msg.sender);
require(!mintingDone);
require(_holders.length == _sixMonthCliff.length);
require(_holders.length <= 255);
for (uint8 i = 0; i < _holders.length; i++) {
address holder = _holders[i];
// make sure lockup period can not be overwritten
require(lockups[holder] == 0);
uint256 timeout = (_sixMonthCliff[i].mul(sixMonth)).add(firstFeb19);
lockups[holder] = timeout;
emit TokensLocked(holder, timeout);
}
}
//If this is called, no more tokens can be generated
//The status of the contract can be checked with getMintingDone, as
//this variable is set to public, thus, getters are generated automatically
function finishMinting() public {
require(owner == msg.sender);
require(!mintingDone);
require(admin1 != address(0));
require(admin2 != address(0));
mintingDone = true;
}
function transferDisable() public {
if(msg.sender == owner) {
transfersEnabled1 = false;
} else if(msg.sender == admin1) {
transfersEnabled2 = false;
} else if(msg.sender == admin2) {
transfersEnabled3 = false;
} else {
revert();
}
}
function isTransferEnabled() public view returns (bool) {
//all three must agree to disable the transfer
return transfersEnabled1 || transfersEnabled2 || transfersEnabled3;
}
/**
* @dev total number of tokens in existence, which is mandated by the ERC20 interface
*/
function totalSupply() public view returns (uint256) {
return totalSupply_;
}
function transfer(address _to, uint256 _value) public returns (bool) {
_transfer(msg.sender, _to, _value, 0, address(0));
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
_transfer(_from, _to, _value, 0, address(0));
_approve(_from, msg.sender, allowed[_from][msg.sender].sub(_value));
return true;
}
function _transfer(address _from, address _to, uint256 _value, uint256 _fee, address _feeAddress) internal {
require(isTransferEnabled());
require(_to != address(0));
require(_to != address(this));
uint256 total = _value.add(_fee);
require(mintingDone);
require(now >= lockups[_from]); // check lockups
require(total <= balances[_from]);
balances[_from] = balances[_from].sub(total);
if(_fee > 0 && _feeAddress != address(0)) {
balances[_feeAddress] = balances[_feeAddress].add(_fee);
}
balances[_to] = balances[_to].add(_value);
emit Transfer(_from, _to, _value);
}
/**
* @dev Gets the balance of the specified address.
* @param _owner The address to query the the balance of.
* @return An uint256 representing the amount owned by the passed address.
*/
function balanceOf(address _owner) public view returns (uint256) {
return balances[_owner];
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
* Beware that changing an allowance with this method brings the risk that someone may use both the old
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* @param _spender The address which will spend the funds.
* @param _value The amount of tokens to be spent.
*/
function approve(address _spender, uint256 _value) public returns (bool) {
_approve(msg.sender, _spender, _value);
return true;
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param _owner address The address which owns the funds.
* @param _spender address The address which will spend the funds.
* @return A uint256 specifying the amount of tokens still available for the spender.
*/
function allowance(address _owner, address _spender) public view returns (uint256) {
return allowed[_owner][_spender];
}
/**
* @dev Increase the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][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 MonolithDAO Token.sol
* Emits an Approval event.
* @param _spender The address which will spend the funds.
* @param _addedValue The amount of tokens to increase the allowance by.
*/
function increaseAllowance(address _spender, uint256 _addedValue) public returns (bool) {
_approve(msg.sender, _spender, allowed[msg.sender][_spender].add(_addedValue));
return true;
}
/**
* @dev Decrease the amount of tokens that an owner allowed to a spender.
* approve should be called when _allowed[msg.sender][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 MonolithDAO Token.sol
* Emits an Approval event.
* @param _spender The address which will spend the funds.
* @param _subtractedValue The amount of tokens to decrease the allowance by.
*/
function decreaseAllowance(address _spender, uint256 _subtractedValue) public returns (bool) {
_approve(msg.sender, _spender, allowed[msg.sender][_spender].sub(_subtractedValue));
return true;
}
/**
* @dev Approve an address to spend another addresses' tokens.
* @param _owner The address that owns the tokens.
* @param _spender The address that will spend the tokens.
* @param _value The number of tokens that can be spent.
*/
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 transferAndCall(address _to, uint256 _value, bytes4 _methodName, bytes memory _args) public returns (bytes memory) {
require(contractWhitelist[_to]);
require(transfer(_to, _value));
emit TransferAndCall(msg.sender, _to, _value, _methodName, _args);
// call receiver
require(Utils.isContract(_to));
(bool success, bytes memory data) = _to.call(abi.encodePacked(abi.encodeWithSelector(_methodName, msg.sender, _value), _args));
require(success);
return data;
}
//ERC 865 + delegate transfer and call
//The signature only allows s < secp256k1n / 2 and v to be 27/28
//If this is not the case the function will revert
function transferPreSigned(bytes memory _signature, address _to, uint256 _value, uint256 _fee, uint256 _nonce) public returns (bool) {
require(!signatures[_signature]);
bytes32 hashedTx = Utils.transferPreSignedHashing(address(this), _to, _value, _fee, _nonce);
address from = Utils.recover(hashedTx, _signature);
require(from != address(0));
require(!nonces[from][_nonce]);
_transfer(from, _to, _value, _fee, msg.sender);
signatures[_signature] = true;
nonces[from][_nonce] = true;
emit Transfer(from, msg.sender, _fee);
emit TransferPreSigned(from, _to, msg.sender, _value, _fee);
return true;
}
//The signature only allows s < secp256k1n / 2 and v to be 27/28
//If this is not the case the function will revert
function transferAndCallPreSigned(bytes memory _signature, address _to, uint256 _value, uint256 _fee, uint256 _nonce,
bytes4 _methodName, bytes memory _args) public returns (bytes memory) {
require(contractWhitelist[_to]);
require(!signatures[_signature]);
bytes32 hashedTx = Utils.transferAndCallPreSignedHashing(address(this), _to, _value, _fee, _nonce, _methodName, _args);
address from = Utils.recover(hashedTx, _signature);
require(from != address(0));
require(!nonces[from][_nonce]);
_transfer(from, _to, _value, _fee, msg.sender);
signatures[_signature] = true;
nonces[from][_nonce] = true;
emit Transfer(from, msg.sender, _fee);
emit TransferAndCallPreSigned(from, _to, msg.sender, _value, _fee, _methodName, _args);
// call receiver
require(Utils.isContract(_to));
//call on behalf of from and not msg.sender
(bool success, bytes memory data) = _to.call(abi.encodePacked(abi.encodeWithSelector(_methodName, from, _value), _args));
require(success);
return data;
}
}
//using: https://github.com/OpenZeppelin/openzeppelin-solidity/blob/f80c65ff67957404c964af864ffb230e4cbb1cf4/contracts/math/SafeMath.sol
pragma solidity 0.5.7;
/**
* @title SafeMath
* @dev Unsigned math operations with safety checks that revert on error
*/
library SafeMath {
/**
* @dev Multiplies two unsigned integers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two unsigned integers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
pragma solidity 0.5.7;
library Utils {
//From: https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/AddressUtils.sol
/**
* Returns whether the target address is a contract
* @dev This function will return false if invoked during the constructor of a contract,
* as the code is not actually created until after the constructor finishes.
* @param addr address to check
* @return whether the target address is a contract
*/
function isContract(address addr) internal view returns (bool) {
uint256 size;
// XXX Currently there is no better way to check if there is a contract in an address
// than to check the size of the code at that address.
// See https://ethereum.stackexchange.com/a/14016/36603
// for more details about how this works.
// TODO Check this again before the Serenity release, because all addresses will be
// contracts then.
// solium-disable-next-line security/no-inline-assembly
assembly { size := extcodesize(addr) }
return size > 0;
}
//From: https://github.com/PROPSProject/props-token-distribution/blob/master/contracts/token/ERC865Token.sol
//adapted to: https://solidity.readthedocs.io/en/v0.5.3/050-breaking-changes.html?highlight=abi%20encode
/**
* @notice Hash (keccak256) of the payload used by transferPreSigned
* @param _token address The address of the token.
* @param _to address The address which you want to transfer to.
* @param _value uint256 The amount of tokens to be transferred.
* @param _fee uint256 The amount of tokens paid to msg.sender, by the owner.
*/
function transferAndCallPreSignedHashing(address _token, address _to, uint256 _value, uint256 _fee, uint256 _nonce,
bytes4 _methodName, bytes memory _args) internal pure returns (bytes32) {
/* "38980f82": transferAndCallPreSignedHashing(address,address,uint256,uint256,uint256,bytes4,bytes) */
return keccak256(abi.encode(bytes4(0x38980f82), _token, _to, _value, _fee, _nonce, _methodName, _args));
}
function transferPreSignedHashing(address _token, address _to, uint256 _value, uint256 _fee, uint256 _nonce)
internal pure returns (bytes32) {
/* "15420b71": transferPreSignedHashing(address,address,uint256,uint256,uint256) */
return keccak256(abi.encode(bytes4(0x15420b71), _token, _to, _value, _fee, _nonce));
}
//From: https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/cryptography/ECDSA.sol
/**
* @dev Recover signer address from a message by using their signature
* @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
* @param signature bytes signature, the signature is generated using web3.eth.sign()
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
// Check the signature length
if (signature.length != 65) {
return (address(0));
}
// Divide the signature in r, s and v variables
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
// solhint-disable-next-line no-inline-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return address(0);
}
if (v != 27 && v != 28) {
return address(0);
}
// If the signature is valid (and not malleable), return the signer address
return ecrecover(hash, v, r, s);
}
}
{
"compilationTarget": {
"DOS.sol": "DOS"
},
"evmVersion": "petersburg",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"admin2","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":"admin1","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_signature","type":"bytes"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_fee","type":"uint256"},{"name":"_nonce","type":"uint256"}],"name":"transferPreSigned","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":"_signature","type":"bytes"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_fee","type":"uint256"},{"name":"_nonce","type":"uint256"},{"name":"_methodName","type":"bytes4"},{"name":"_args","type":"bytes"}],"name":"transferAndCallPreSigned","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","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":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"transferDisable","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_holders","type":"address[]"},{"name":"_sixMonthCliff","type":"uint256[]"}],"name":"lockTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_methodName","type":"bytes4"},{"name":"_args","type":"bytes"}],"name":"transferAndCall","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"claimOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","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":"contractAddress","type":"address"}],"name":"removeWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"mintingDone","outputs":[{"name":"","type":"bool"}],"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":"sixMonth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"transfersEnabled1","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","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":true,"inputs":[],"name":"transfersEnabled2","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"transfersEnabled3","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_admin1","type":"address"},{"name":"_admin2","type":"address"}],"name":"setAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isTransferEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxSupply","outputs":[{"name":"","type":"uint256"}],"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":"_recipients","type":"address[]"},{"name":"_amounts","type":"uint256[]"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tmpOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"firstFeb19","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"contractAddress","type":"address"}],"name":"addWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_holder","type":"address"},{"indexed":false,"name":"_timeout","type":"uint256"}],"name":"TokensLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"},{"indexed":false,"name":"_methodName","type":"bytes4"},{"indexed":false,"name":"_args","type":"bytes"}],"name":"TransferAndCall","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":true,"name":"_delegate","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"},{"indexed":false,"name":"_fee","type":"uint256"}],"name":"TransferPreSigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":true,"name":"_delegate","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"},{"indexed":false,"name":"_fee","type":"uint256"},{"indexed":false,"name":"_methodName","type":"bytes4"},{"indexed":false,"name":"_args","type":"bytes"}],"name":"TransferAndCallPreSigned","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"},{"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"}]