pragma solidity 0.4.24;
//@title WitToken
//@author(luoyuanq233@gmail.com)
//@dev 该合约参考自openzeppelin的erc20实现
//1.使用openzeppelin的SafeMath库防止运算溢出
//2.使用openzeppelin的Ownable,Roles,RBAC来做权限控制,自定义了ceo,coo,cro等角色
//3.ERC20扩展了ERC20Basic,实现了授权转移
//4.BasicToken,StandardToken,PausableToken均是erc20的具体实现
//5.BlackListToken加入黑名单方法
//6.TwoPhaseToken可以发行和赎回资产,并采用经办复核的二阶段提交
//7.UpgradedStandardToken参考自TetherUSD合约,可以在另一个合约升级erc20的方法
//8.可以设置交易的手续费率
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
/**
* @title Roles
* @author Francisco Giordano (@frangio)
* @dev Library for managing addresses assigned to a Role.
* See RBAC.sol for example usage.
*/
library Roles {
struct Role {
mapping (address => bool) bearer;
}
/**
* @dev give an address access to this role
*/
function add(Role storage role, address addr) internal {
role.bearer[addr] = true;
}
/**
* @dev remove an address' access to this role
*/
function remove(Role storage role, address addr) internal {
role.bearer[addr] = false;
}
/**
* @dev check if an address has this role
* // reverts
*/
function check(Role storage role, address addr) view internal {
require(has(role, addr));
}
/**
* @dev check if an address has this role
* @return bool
*/
function has(Role storage role, address addr) view internal returns (bool) {
return role.bearer[addr];
}
}
/**
* @title RBAC (Role-Based Access Control)
* @author Matt Condon (@Shrugs)
* @dev Stores and provides setters and getters for roles and addresses.
* Supports unlimited numbers of roles and addresses.
* See //contracts/mocks/RBACMock.sol for an example of usage.
* This RBAC method uses strings to key roles. It may be beneficial
* for you to write your own implementation of this interface using Enums or similar.
* It's also recommended that you define constants in the contract, like ROLE_ADMIN below,
* to avoid typos.
*/
contract RBAC is Ownable {
using Roles for Roles.Role;
mapping (string => Roles.Role) private roles;
event RoleAdded(address addr, string roleName);
event RoleRemoved(address addr, string roleName);
/**
* A constant role name for indicating admins.
*/
string public constant ROLE_CEO = "ceo";
string public constant ROLE_COO = "coo";//运营
string public constant ROLE_CRO = "cro";//风控
string public constant ROLE_MANAGER = "manager";//经办员
string public constant ROLE_REVIEWER = "reviewer";//审核员
/**
* @dev constructor. Sets msg.sender as ceo by default
*/
constructor() public{
addRole(msg.sender, ROLE_CEO);
}
/**
* @dev reverts if addr does not have role
* @param addr address
* @param roleName the name of the role
* // reverts
*/
function checkRole(address addr, string roleName) view internal {
roles[roleName].check(addr);
}
/**
* @dev determine if addr has role
* @param addr address
* @param roleName the name of the role
* @return bool
*/
function hasRole(address addr, string roleName) view public returns (bool) {
return roles[roleName].has(addr);
}
function ownerAddCeo(address addr) onlyOwner public {
addRole(addr, ROLE_CEO);
}
function ownerRemoveCeo(address addr) onlyOwner public{
removeRole(addr, ROLE_CEO);
}
function ceoAddCoo(address addr) onlyCEO public {
addRole(addr, ROLE_COO);
}
function ceoRemoveCoo(address addr) onlyCEO public{
removeRole(addr, ROLE_COO);
}
function cooAddManager(address addr) onlyCOO public {
addRole(addr, ROLE_MANAGER);
}
function cooRemoveManager(address addr) onlyCOO public {
removeRole(addr, ROLE_MANAGER);
}
function cooAddReviewer(address addr) onlyCOO public {
addRole(addr, ROLE_REVIEWER);
}
function cooRemoveReviewer(address addr) onlyCOO public {
removeRole(addr, ROLE_REVIEWER);
}
function cooAddCro(address addr) onlyCOO public {
addRole(addr, ROLE_CRO);
}
function cooRemoveCro(address addr) onlyCOO public {
removeRole(addr, ROLE_CRO);
}
/**
* @dev add a role to an address
* @param addr address
* @param roleName the name of the role
*/
function addRole(address addr, string roleName) internal {
roles[roleName].add(addr);
emit RoleAdded(addr, roleName);
}
/**
* @dev remove a role from an address
* @param addr address
* @param roleName the name of the role
*/
function removeRole(address addr, string roleName) internal {
roles[roleName].remove(addr);
emit RoleRemoved(addr, roleName);
}
/**
* @dev modifier to scope access to ceo
* // reverts
*/
modifier onlyCEO() {
checkRole(msg.sender, ROLE_CEO);
_;
}
/**
* @dev modifier to scope access to coo
* // reverts
*/
modifier onlyCOO() {
checkRole(msg.sender, ROLE_COO);
_;
}
/**
* @dev modifier to scope access to cro
* // reverts
*/
modifier onlyCRO() {
checkRole(msg.sender, ROLE_CRO);
_;
}
/**
* @dev modifier to scope access to manager
* // reverts
*/
modifier onlyMANAGER() {
checkRole(msg.sender, ROLE_MANAGER);
_;
}
/**
* @dev modifier to scope access to reviewer
* // reverts
*/
modifier onlyREVIEWER() {
checkRole(msg.sender, ROLE_REVIEWER);
_;
}
}
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 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);
return c;
}
}
/**
*
* @title ERC20Basic
* @dev Simpler version of ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/179
*/
contract ERC20Basic {
function totalSupply() public view returns (uint256);
function balanceOf(address who) public view returns (uint256);
function transfer(address to, uint256 value) public returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
}
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
contract ERC20 is ERC20Basic {
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 Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* @title Basic token
* @dev Basic version of StandardToken, with no allowances.
*/
contract BasicToken is ERC20Basic, RBAC {
using SafeMath for uint256;
mapping(address => uint256) balances;
uint256 totalSupply_;
uint256 public basisPointsRate;//手续费率
uint256 public maximumFee;//最大手续费
address public assetOwner;//收取的手续费和增发的资产都到这个地址上, 赎回资产时会从这个地址销毁资产
/**
* @dev total number of tokens in existence
*/
function totalSupply() public view returns (uint256) {
return totalSupply_;
}
/**
* @dev transfer token for a specified address
* @param _to The address to transfer to.
* @param _value The amount to be transferred.
*/
function transfer(address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value <= balances[msg.sender]);
uint256 fee = (_value.mul(basisPointsRate)).div(10000);
if (fee > maximumFee) {
fee = maximumFee;
}
uint256 sendAmount = _value.sub(fee);
// SafeMath.sub will throw if there is not enough balance.
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(sendAmount);
if (fee > 0) {
balances[assetOwner] = balances[assetOwner].add(fee);
emit Transfer(msg.sender, assetOwner, fee);
}
emit Transfer(msg.sender, _to, sendAmount);
return true;
}
/**
* @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 balance) {
return balances[_owner];
}
}
/**
* @title Standard ERC20 token
*
* @dev Implementation of the basic standard token.
* @dev https://github.com/ethereum/EIPs/issues/20
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
*/
contract StandardToken is ERC20, BasicToken {
mapping (address => mapping (address => uint256)) internal allowed;
/**
* @dev Transfer tokens from one address to another
* @param _from address The address which you want to send tokens from
* @param _to address The address which you want to transfer to
* @param _value uint256 the amount of tokens to be transferred
*/
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value <= balances[_from]);
require(_value <= allowed[_from][msg.sender]);
uint256 fee = (_value.mul(basisPointsRate)).div(10000);
if (fee > maximumFee) {
fee = maximumFee;
}
uint256 sendAmount = _value.sub(fee);
balances[_from] = balances[_from].sub(_value);
balances[_to] = balances[_to].add(sendAmount);
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
if (fee > 0) {
balances[assetOwner] = balances[assetOwner].add(fee);
emit Transfer(_from, assetOwner, fee);
}
emit Transfer(_from, _to, sendAmount);
return true;
}
/**
* @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) {
allowed[msg.sender][_spender] = _value;
emit Approval(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[_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
* @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] = allowed[msg.sender][_spender].add(_addedValue);
emit 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 MonolithDAO Token.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] = oldValue.sub(_subtractedValue);
}
emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
}
/**
* @title Pausable
* @dev Base contract which allows children to implement an emergency stop mechanism.
*/
contract Pausable is RBAC {
event Pause();
event Unpause();
bool public paused = false;
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!paused);
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*/
modifier whenPaused() {
require(paused);
_;
}
/**
* @dev called by the ceo to pause, triggers stopped state
*/
function pause() onlyCEO whenNotPaused public {
paused = true;
emit Pause();
}
/**
* @dev called by the ceo to unpause, returns to normal state
*/
function unpause() onlyCEO whenPaused public {
paused = false;
emit Unpause();
}
}
/**
* @title Pausable token
* @dev StandardToken modified with pausable transfers.
**/
contract PausableToken is StandardToken, 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 increaseApproval(address _spender, uint _addedValue) public whenNotPaused returns (bool success) {
return super.increaseApproval(_spender, _addedValue);
}
function decreaseApproval(address _spender, uint _subtractedValue) public whenNotPaused returns (bool success) {
return super.decreaseApproval(_spender, _subtractedValue);
}
}
contract BlackListToken is PausableToken {
function getBlackListStatus(address _maker) external view returns (bool) {
return isBlackListed[_maker];
}
mapping (address => bool) public isBlackListed;
function addBlackList (address _evilUser) public onlyCRO {
isBlackListed[_evilUser] = true;
emit AddedBlackList(_evilUser);
}
function removeBlackList (address _clearedUser) public onlyCRO {
isBlackListed[_clearedUser] = false;
emit RemovedBlackList(_clearedUser);
}
function destroyBlackFunds (address _blackListedUser) public onlyCEO {
require(isBlackListed[_blackListedUser]);
uint dirtyFunds = balanceOf(_blackListedUser);
balances[_blackListedUser] = 0;
totalSupply_ = totalSupply_.sub(dirtyFunds);
emit DestroyedBlackFunds(_blackListedUser, dirtyFunds);
}
event DestroyedBlackFunds(address _blackListedUser, uint _balance);
event AddedBlackList(address _user);
event RemovedBlackList(address _user);
}
/**
* 增发和赎回token由经办人和复核人配合完成
* 1.由经办人角色先执行submitIssue或submitRedeem;
* 2.复核人角色再来执行comfirmIsses或comfirmRedeem;
* 3.两者提交的参数一致,则增发和赎回才能成功
* 4.经办人提交数据后,复核人执行成功后,需要经办人再次提交才能再次执行
**/
contract TwoPhaseToken is BlackListToken{
//保存经办人提交的参数
struct MethodParam {
string method; //方法名
uint value; //增发或者赎回的数量
bool state; //true表示经办人有提交数据,复核人执行成功后变为false
}
mapping (string => MethodParam) params;
//方法名常量
string public constant ISSUE_METHOD = "issue";
string public constant REDEEM_METHOD = "redeem";
//经办人提交增发数量
function submitIssue(uint _value) public onlyMANAGER {
params[ISSUE_METHOD] = MethodParam(ISSUE_METHOD, _value, true);
emit SubmitIsses(msg.sender,_value);
}
//复核人第二次确认增发数量并执行
function comfirmIsses(uint _value) public onlyREVIEWER {
require(params[ISSUE_METHOD].value == _value);
require(params[ISSUE_METHOD].state == true);
balances[assetOwner]=balances[assetOwner].add(_value);
totalSupply_ = totalSupply_.add(_value);
params[ISSUE_METHOD].state=false;
emit ComfirmIsses(msg.sender,_value);
}
//经办人提交赎回数量
function submitRedeem(uint _value) public onlyMANAGER {
params[REDEEM_METHOD] = MethodParam(REDEEM_METHOD, _value, true);
emit SubmitRedeem(msg.sender,_value);
}
//复核人第二次确认赎回数量并执行
function comfirmRedeem(uint _value) public onlyREVIEWER {
require(params[REDEEM_METHOD].value == _value);
require(params[REDEEM_METHOD].state == true);
balances[assetOwner]=balances[assetOwner].sub(_value);
totalSupply_ = totalSupply_.sub(_value);
params[REDEEM_METHOD].state=false;
emit ComfirmIsses(msg.sender,_value);
}
//根据方法名,查看经办人提交的参数
function getMethodValue(string _method) public view returns(uint){
return params[_method].value;
}
//根据方法名,查看经办人是否有提交数据
function getMethodState(string _method) public view returns(bool) {
return params[_method].state;
}
event SubmitRedeem(address submit, uint _value);
event ComfirmRedeem(address comfirm, uint _value);
event SubmitIsses(address submit, uint _value);
event ComfirmIsses(address comfirm, uint _value);
}
contract UpgradedStandardToken {
// those methods are called by the legacy contract
function totalSupplyByLegacy() public view returns (uint256);
function balanceOfByLegacy(address who) public view returns (uint256);
function transferByLegacy(address origSender, address to, uint256 value) public returns (bool);
function allowanceByLegacy(address owner, address spender) public view returns (uint256);
function transferFromByLegacy(address origSender, address from, address to, uint256 value) public returns (bool);
function approveByLegacy(address origSender, address spender, uint256 value) public returns (bool);
function increaseApprovalByLegacy(address origSender, address spender, uint addedValue) public returns (bool);
function decreaseApprovalByLegacy(address origSende, address spender, uint subtractedValue) public returns (bool);
}
contract WitToken is TwoPhaseToken {
string public constant name = "Wealth in Token";
string public constant symbol = "WIT";
uint8 public constant decimals = 18;
address public upgradedAddress;
bool public deprecated;
modifier validDestination( address to ) {
require(to != address(0x0));
require(to != address(this));
_;
}
constructor ( uint _totalTokenAmount ) public {
basisPointsRate = 0;
maximumFee = 0;
totalSupply_ = _totalTokenAmount;
balances[msg.sender] = _totalTokenAmount;
deprecated = false;
assetOwner = msg.sender;
emit Transfer(address(0x0), msg.sender, _totalTokenAmount);
}
// Forward ERC20 methods to upgraded contract if this one is deprecated
function totalSupply() public view returns (uint256) {
if (deprecated) {
return UpgradedStandardToken(upgradedAddress).totalSupplyByLegacy();
} else {
return totalSupply_;
}
}
// Forward ERC20 methods to upgraded contract if this one is deprecated
function balanceOf(address _owner) public view returns (uint256 balance) {
if (deprecated) {
return UpgradedStandardToken(upgradedAddress).balanceOfByLegacy( _owner);
} else {
return super.balanceOf(_owner);
}
}
// Forward ERC20 methods to upgraded contract if this one is deprecated
function transfer(address _to, uint _value) public validDestination(_to) returns (bool) {
require(!isBlackListed[msg.sender]);
if (deprecated) {
return UpgradedStandardToken(upgradedAddress).transferByLegacy(msg.sender, _to, _value);
} else {
return super.transfer(_to, _value);
}
}
// Forward ERC20 methods to upgraded contract if this one is deprecated
function allowance(address _owner, address _spender) public view returns (uint256) {
if (deprecated) {
return UpgradedStandardToken(upgradedAddress).allowanceByLegacy(_owner, _spender);
} else {
return super.allowance(_owner, _spender);
}
}
// Forward ERC20 methods to upgraded contract if this one is deprecated
function transferFrom(address _from, address _to, uint _value) public validDestination(_to) returns (bool) {
require(!isBlackListed[_from]);
if (deprecated) {
return UpgradedStandardToken(upgradedAddress).transferFromByLegacy(msg.sender, _from, _to, _value);
} else {
return super.transferFrom(_from, _to, _value);
}
}
// Forward ERC20 methods to upgraded contract if this one is deprecated
function approve(address _spender, uint256 _value) public returns (bool) {
if (deprecated) {
return UpgradedStandardToken(upgradedAddress).approveByLegacy(msg.sender, _spender, _value);
} else {
return super.approve(_spender, _value);
}
}
// Forward ERC20 methods to upgraded contract if this one is deprecated
function increaseApproval(address _spender, uint _value) public returns (bool) {
if (deprecated) {
return UpgradedStandardToken(upgradedAddress).increaseApprovalByLegacy(msg.sender, _spender, _value);
} else {
return super.increaseApproval(_spender, _value);
}
}
// Forward ERC20 methods to upgraded contract if this one is deprecated
function decreaseApproval(address _spender, uint _value) public returns (bool) {
if (deprecated) {
return UpgradedStandardToken(upgradedAddress).decreaseApprovalByLegacy(msg.sender, _spender, _value);
} else {
return super.decreaseApproval(_spender, _value);
}
}
// deprecate current contract in favour of a new one
function deprecate(address _upgradedAddress) public onlyCEO whenPaused {
deprecated = true;
upgradedAddress = _upgradedAddress;
emit Deprecate(_upgradedAddress);
}
// Called when contract is deprecated
event Deprecate(address newAddress);
/**
* @dev Set up transaction fees
* @param newBasisPoints A few ten-thousandth (设置手续费率为万分之几)
* @param newMaxFee Maximum fee (设置最大手续费,不需要添加decimals)
*/
function setFeeParams(uint newBasisPoints, uint newMaxFee) public onlyCEO {
basisPointsRate = newBasisPoints;
maximumFee = newMaxFee.mul(uint(10)**decimals);
emit FeeParams(basisPointsRate, maximumFee);
}
function transferAssetOwner(address newAssetOwner) public onlyCEO {
require(newAssetOwner != address(0));
assetOwner = newAssetOwner;
emit TransferAssetOwner(assetOwner, newAssetOwner);
}
event TransferAssetOwner(address assetOwner, address newAssetOwner);
// Called if contract ever adds fees
event FeeParams(uint feeBasisPoints, uint maxFee);
}
{
"compilationTarget": {
"WitToken.sol": "WitToken"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_upgradedAddress","type":"address"}],"name":"deprecate","outputs":[],"payable":false,"stateMutability":"nonpayable","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":"deprecated","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_evilUser","type":"address"}],"name":"addBlackList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ROLE_CRO","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"addr","type":"address"},{"name":"roleName","type":"string"}],"name":"hasRole","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":"upgradedAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"cooAddReviewer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_method","type":"string"}],"name":"getMethodState","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":"maximumFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newAssetOwner","type":"address"}],"name":"transferAssetOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"comfirmRedeem","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"ownerRemoveCeo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"cooAddManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_maker","type":"address"}],"name":"getBlackListStatus","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROLE_REVIEWER","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"ceoAddCoo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROLE_CEO","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"REDEEM_METHOD","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"cooRemoveManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"ownerAddCeo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"submitIssue","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":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"assetOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newBasisPoints","type":"uint256"},{"name":"newMaxFee","type":"uint256"}],"name":"setFeeParams","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"submitRedeem","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":true,"inputs":[],"name":"ROLE_COO","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"comfirmIsses","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_method","type":"string"}],"name":"getMethodValue","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"cooRemoveReviewer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"cooAddCro","outputs":[],"payable":false,"stateMutability":"nonpayable","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":true,"inputs":[],"name":"basisPointsRate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBlackListed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_clearedUser","type":"address"}],"name":"removeBlackList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ISSUE_METHOD","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_blackListedUser","type":"address"}],"name":"destroyBlackFunds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ROLE_MANAGER","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"ceoRemoveCoo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"cooRemoveCro","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_totalTokenAmount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newAddress","type":"address"}],"name":"Deprecate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"assetOwner","type":"address"},{"indexed":false,"name":"newAssetOwner","type":"address"}],"name":"TransferAssetOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"feeBasisPoints","type":"uint256"},{"indexed":false,"name":"maxFee","type":"uint256"}],"name":"FeeParams","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"submit","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"SubmitRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"comfirm","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"ComfirmRedeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"submit","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"SubmitIsses","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"comfirm","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"ComfirmIsses","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_blackListedUser","type":"address"},{"indexed":false,"name":"_balance","type":"uint256"}],"name":"DestroyedBlackFunds","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_user","type":"address"}],"name":"AddedBlackList","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_user","type":"address"}],"name":"RemovedBlackList","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"addr","type":"address"},{"indexed":false,"name":"roleName","type":"string"}],"name":"RoleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"addr","type":"address"},{"indexed":false,"name":"roleName","type":"string"}],"name":"RoleRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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"}]