/** * Source Code first verified at https://etherscan.io on Thursday, May 9, 2019 (UTC) */ pragma solidity ^0.4.24; // File: zeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol /** * @title ERC20Basic * @dev Simpler version of ERC20 interface * 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); } // File: zeppelin-solidity/contracts/math/SafeMath.sol /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) { // Gas optimization: this is cheaper than asserting '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; } c = _a * _b; assert(c / _a == _b); return c; } /** * @dev Integer division of two numbers, truncating the quotient. */ 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 _a / _b; } /** * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 _a, uint256 _b) internal pure returns (uint256) { assert(_b <= _a); return _a - _b; } /** * @dev Adds two numbers, throws on overflow. */ function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) { c = _a + _b; assert(c >= _a); return c; } } // File: zeppelin-solidity/contracts/token/ERC20/BasicToken.sol /** * @title Basic token * @dev Basic version of StandardToken, with no allowances. */ contract BasicToken is ERC20Basic { using SafeMath for uint256; mapping(address => uint256) internal balances; uint256 internal totalSupply_; /** * @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(_value <= balances[msg.sender]); require(_to != address(0)); balances[msg.sender] = balances[msg.sender].sub(_value); balances[_to] = balances[_to].add(_value); emit Transfer(msg.sender, _to, _value); 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) { return balances[_owner]; } } // File: contracts/mocks/BasicTokenMock.sol /// @title Mock token contract using Open Zepplein's BasicToken /// @dev Adapted from https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/mocks/BasicTokenMock.sol contract BasicTokenMock is BasicToken { constructor (address initialAccount, uint256 initialBalance) public { balances[initialAccount] = initialBalance; totalSupply_ = initialBalance; } } // File: zeppelin-solidity/contracts/token/ERC20/ERC20.sol /** * @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 ); } // File: contracts/token/ERC1404/ERC1404.sol contract ERC1404 is ERC20 { /// @notice Detects if a transfer will be reverted and if so returns an appropriate reference code /// @param from Sending address /// @param to Receiving address /// @param value Amount of tokens being transferred /// @return Code by which to reference message for rejection reasoning /// @dev Overwrite with your custom transfer restriction logic function detectTransferRestriction (address from, address to, uint256 value) public view returns (uint8); /// @notice Returns a human-readable message for a given restriction code /// @param restrictionCode Identifier for looking up a message /// @return Text showing the restriction's reasoning /// @dev Overwrite with your custom message and restrictionCode handling function messageForTransferRestriction (uint8 restrictionCode) public view returns (string); } // File: zeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol /** * @title DetailedERC20 token * @dev The decimals are only for visualization purposes. * All the operations are done using the smallest and indivisible token unit, * just as on Ethereum all the operations are done in wei. */ contract DetailedERC20 is ERC20 { string public name; string public symbol; uint8 public decimals; constructor(string _name, string _symbol, uint8 _decimals) public { name = _name; symbol = _symbol; decimals = _decimals; } } // File: zeppelin-solidity/contracts/token/ERC20/StandardToken.sol /** * @title Standard ERC20 token * * @dev Implementation of the basic standard token. * https://github.com/ethereum/EIPs/issues/20 * 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(_value <= balances[_from]); require(_value <= allowed[_from][msg.sender]); require(_to != address(0)); balances[_from] = balances[_from].sub(_value); balances[_to] = balances[_to].add(_value); allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); emit Transfer(_from, _to, _value); 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, uint256 _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, uint256 _subtractedValue ) public returns (bool) { uint256 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; } } // File: zeppelin-solidity/contracts/ownership/Ownable.sol /** * @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 OwnershipRenounced(address indexed previousOwner); 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 relinquish control of the contract. * @notice Renouncing to ownership will leave the contract without an owner. * It will not be possible to call the functions with the `onlyOwner` * modifier anymore. */ function renounceOwnership() public onlyOwner { emit OwnershipRenounced(owner); owner = address(0); } /** * @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 { _transferOwnership(_newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param _newOwner The address to transfer ownership to. */ function _transferOwnership(address _newOwner) internal { require(_newOwner != address(0)); emit OwnershipTransferred(owner, _newOwner); owner = _newOwner; } } // File: zeppelin-solidity/contracts/token/ERC20/MintableToken.sol /** * @title Mintable token * @dev Simple ERC20 Token example, with mintable token creation * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol */ contract MintableToken is StandardToken, Ownable { event Mint(address indexed to, uint256 amount); event MintFinished(); bool public mintingFinished = false; modifier canMint() { require(!mintingFinished); _; } modifier hasMintPermission() { require(msg.sender == owner); _; } /** * @dev Function to mint tokens * @param _to The address that will receive the minted tokens. * @param _amount The amount of tokens to mint. * @return A boolean that indicates if the operation was successful. */ function mint( address _to, uint256 _amount ) public hasMintPermission canMint returns (bool) { totalSupply_ = totalSupply_.add(_amount); balances[_to] = balances[_to].add(_amount); emit Mint(_to, _amount); emit Transfer(address(0), _to, _amount); return true; } /** * @dev Function to stop minting new tokens. * @return True if the operation was successful. */ function finishMinting() public onlyOwner canMint returns (bool) { mintingFinished = true; emit MintFinished(); return true; } } // File: contracts/token/R-Token/RegulatorService.sol /// @notice Standard interface for `RegulatorService`s extended for ERC-1404 compatability contract RegulatorService { /* * @notice This method *MUST* be called by `RegulatedToken`s during `transfer()` and `transferFrom()`. * The implementation *SHOULD* check whether or not a transfer can be approved. * * @dev This method *MAY* call back to the token contract specified by `_token` for * more information needed to enforce trade approval. * * @param _token The address of the token to be transfered * @param _spender The address of the spender of the token * @param _from The address of the sender account * @param _to The address of the receiver account * @param _amount The quantity of the token to trade * * @return uint8 The reason code: 0 means success. Non-zero values are left to the implementation * to assign meaning. */ function check(address _token, address _spender, address _from, address _to, uint256 _amount) public returns (uint8); /* * @notice Returns the error message for a passed failed check reason. * * @param _reason The reason code: 0 means success. Non-zero values are left to the implementation * to assign meaning. * * @return The human-readable mesage string. */ function messageForReason(uint8 _reason) public view returns (string); } // File: contracts/token/R-Token/ServiceRegistry.sol /// @notice A service that points to a `RegulatorService` contract ServiceRegistry is Ownable { address public service; /** * @notice Triggered when service address is replaced */ event ReplaceService(address oldService, address newService); /** * @dev Validate contract address * Credit: https://github.com/Dexaran/ERC223-token-standard/blob/Recommended/ERC223_Token.sol#L107-L114 * * @param _addr The address of a smart contract */ modifier withContract(address _addr) { uint length; assembly { length := extcodesize(_addr) } require(length > 0); _; } /** * @notice Constructor * * @param _service The address of the `RegulatorService` * */ function ServiceRegistry(address _service) public { service = _service; } /** * @notice Replaces the address pointer to the `RegulatorService` * * @dev This method is only callable by the contract's owner * * @param _service The address of the new `RegulatorService` */ function replaceService(address _service) onlyOwner withContract(_service) public { address oldService = service; service = _service; ReplaceService(oldService, service); } } // File: contracts/token/R-Token/RegulatedToken.sol /// @notice An ERC-20 token that has the ability to check for trade validity contract RegulatedToken is DetailedERC20, MintableToken { /** * @notice R-Token decimals setting (used when constructing DetailedERC20) */ uint8 constant public RTOKEN_DECIMALS = 18; /** * @notice Triggered when regulator checks pass or fail */ event CheckStatus(uint8 reason, address indexed spender, address indexed from, address indexed to, uint256 value); /** * @notice Address of the `ServiceRegistry` that has the location of the * `RegulatorService` contract responsible for checking trade * permissions. */ ServiceRegistry public registry; /** * @notice Constructor * * @param _registry Address of `ServiceRegistry` contract * @param _name Name of the token: See DetailedERC20 * @param _symbol Symbol of the token: See DetailedERC20 */ function RegulatedToken(ServiceRegistry _registry, string _name, string _symbol) public DetailedERC20(_name, _symbol, RTOKEN_DECIMALS) { require(_registry != address(0)); registry = _registry; } /** * @notice ERC-20 overridden function that include logic to check for trade validity. * * @param _to The address of the receiver * @param _value The number of tokens to transfer * * @return `true` if successful and `false` if unsuccessful */ function transfer(address _to, uint256 _value) public returns (bool) { if (_check(msg.sender, _to, _value)) { return super.transfer(_to, _value); } else { return false; } } /** * @notice ERC-20 overridden function that include logic to check for trade validity. * * @param _from The address of the sender * @param _to The address of the receiver * @param _value The number of tokens to transfer * * @return `true` if successful and `false` if unsuccessful */ function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { if (_check(_from, _to, _value)) { return super.transferFrom(_from, _to, _value); } else { return false; } } /** * @notice Performs the regulator check * * @dev This method raises a CheckStatus event indicating success or failure of the check * * @param _from The address of the sender * @param _to The address of the receiver * @param _value The number of tokens to transfer * * @return `true` if the check was successful and `false` if unsuccessful */ function _check(address _from, address _to, uint256 _value) private returns (bool) { var reason = _service().check(this, msg.sender, _from, _to, _value); CheckStatus(reason, msg.sender, _from, _to, _value); return reason == 0; } /** * @notice Retreives the address of the `RegulatorService` that manages this token. * * @dev This function *MUST NOT* memoize the `RegulatorService` address. This would * break the ability to upgrade the `RegulatorService`. * * @return The `RegulatorService` that manages this token. */ function _service() constant public returns (RegulatorService) { return RegulatorService(registry.service()); } } // File: contracts/examples/other-standards/R-Token/RegulatedTokenExample.sol contract RegulatedTokenExample is ERC1404, RegulatedToken { function RegulatedTokenExample(ServiceRegistry _registry, string _name, string _symbol) public RegulatedToken(_registry, _name, _symbol) { } /** * @notice Implementing detectTransferRestriction makes this token ERC-1404 compatible * * @dev Notice in the call to _service.check(), the 2nd argument is address 0. * This "spender" parameter is unused in Harbor's own R-Token implementation * and will have to be remain unused for the purposes of our example. * * @param from The address of the sender * @param to The address of the receiver * @param value The number of tokens to transfer * * @return A code that is associated with the reason for a failed check */ function detectTransferRestriction (address from, address to, uint256 value) public view returns (uint8) { return _service().check(this, address(0), from, to, value); } /** * @notice Implementing messageForTransferRestriction makes this token ERC-1404 compatible * * @dev The RegulatorService contract must implement the function messageforReason in this implementation * * @param reason The restrictionCode returned from the service check * * @return The human-readable mesage string */ function messageForTransferRestriction (uint8 reason) public view returns (string) { return _service().messageForReason(reason); } } // File: contracts/mocks/LeviasToken.sol contract LeviasSecurityToken is BasicTokenMock, RegulatedTokenExample { RegulatorService public service; constructor ( address initialAccount, uint256 initialBalance, ServiceRegistry registry, string name, string symbol ) BasicTokenMock(initialAccount, initialBalance) RegulatedTokenExample(registry, name, symbol) public { } }