ETH Price: $2,991.54 (+1.59%)
Gas: 35 Gwei

Contract

0xEf58491224958d978fACF55D2120c55A24516B98
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Generate Securit...67422762018-11-20 23:30:311921 days 19 hrs ago1542756631IN
0xEf5849...24516B98
0 ETH0.032269695
Generate Securit...67397152018-11-20 13:19:461922 days 5 hrs ago1542719986IN
0xEf5849...24516B98
0 ETH0.032267375
Generate Securit...67168192018-11-16 19:01:381925 days 23 hrs ago1542394898IN
0xEf5849...24516B98
0 ETH0.032358665
Generate Securit...67088952018-11-15 12:00:511927 days 6 hrs ago1542283251IN
0xEf5849...24516B98
0 ETH0.032263615
Generate Securit...66827892018-11-11 5:23:211931 days 13 hrs ago1541913801IN
0xEf5849...24516B98
0 ETH0.032279095
Generate Securit...66827242018-11-11 5:10:111931 days 13 hrs ago1541913011IN
0xEf5849...24516B98
0 ETH0.003615683.1
Generate Securit...66669932018-11-08 15:27:281934 days 3 hrs ago1541690848IN
0xEf5849...24516B98
0 ETH0.032349545
Generate Securit...66646262018-11-08 6:00:341934 days 12 hrs ago1541656834IN
0xEf5849...24516B98
0 ETH0.0965672815
Generate Securit...66603602018-11-07 13:27:381935 days 5 hrs ago1541597258IN
0xEf5849...24516B98
0 ETH0.032355945
Generate Securit...66497432018-11-05 19:31:501936 days 23 hrs ago1541446310IN
0xEf5849...24516B98
0 ETH0.032284415
Generate Securit...66379292018-11-03 20:46:211938 days 21 hrs ago1541277981IN
0xEf5849...24516B98
0 ETH0.032268795
Generate Securit...66251182018-11-01 18:26:241941 days 9 mins ago1541096784IN
0xEf5849...24516B98
0 ETH0.032283715
Generate Securit...66174882018-10-31 12:15:251942 days 6 hrs ago1540988125IN
0xEf5849...24516B98
0 ETH0.033423345
Generate Securit...66173132018-10-31 11:35:181942 days 7 hrs ago1540985718IN
0xEf5849...24516B98
0 ETH0.032199495
Generate Securit...66171562018-10-31 10:52:051942 days 7 hrs ago1540983125IN
0xEf5849...24516B98
0 ETH0.032269325
Generate Securit...66168412018-10-31 9:37:441942 days 8 hrs ago1540978664IN
0xEf5849...24516B98
0 ETH0.032263615
Generate Securit...66039432018-10-29 7:09:481944 days 11 hrs ago1540796988IN
0xEf5849...24516B98
0 ETH0.032271375
Generate Securit...65891192018-10-26 20:56:211946 days 21 hrs ago1540587381IN
0xEf5849...24516B98
0 ETH0.032345455
Generate Securit...65419272018-10-19 3:49:431954 days 14 hrs ago1539920983IN
0xEf5849...24516B98
0 ETH0.032267295
Generate Securit...65322442018-10-17 13:54:121956 days 4 hrs ago1539784452IN
0xEf5849...24516B98
0 ETH0.045493057.05
Generate Securit...65111842018-10-14 3:30:051959 days 15 hrs ago1539487805IN
0xEf5849...24516B98
0 ETH0.3228696550
Generate Securit...65108492018-10-14 2:05:511959 days 16 hrs ago1539482751IN
0xEf5849...24516B98
0 ETH0.039246846
Generate Securit...65066602018-10-13 9:50:491960 days 8 hrs ago1539424249IN
0xEf5849...24516B98
0 ETH0.012907112
Generate Securit...64875052018-10-10 7:08:401963 days 11 hrs ago1539155320IN
0xEf5849...24516B98
0 ETH0.032972765
Generate Securit...64836532018-10-09 16:15:291964 days 2 hrs ago1539101729IN
0xEf5849...24516B98
0 ETH0.032262415
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SecurityTokenRegistry

Compiler Version
v0.4.24+commit.e67f0147

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2018-07-30
*/

pragma solidity ^0.4.24;

/**
 * @title Interface for the polymath ticker registry contract
 */
contract ITickerRegistry {
    /**
    * @notice Check the validity of the symbol
    * @param _symbol token symbol
    * @param _owner address of the owner
    * @param _tokenName Name of the token
    * @return bool
    */
    function checkValidity(string _symbol, address _owner, string _tokenName) public returns(bool);

    /**
    * @notice Returns the owner and timestamp for a given symbol
    * @param _symbol symbol
    */
    function getDetails(string _symbol) public view returns (address, uint256, string, bytes32, bool);

    /**
     * @notice Check the symbol is reserved or not
     * @param _symbol Symbol of the token
     * @return bool
     */
     function isReserved(string _symbol, address _owner, string _tokenName, bytes32 _swarmHash) public returns(bool);

}

/**
 * @title Math
 * @dev Assorted math operations
 */
library Math {
  function max64(uint64 a, uint64 b) internal pure returns (uint64) {
    return a >= b ? a : b;
  }

  function min64(uint64 a, uint64 b) internal pure returns (uint64) {
    return a < b ? a : b;
  }

  function max256(uint256 a, uint256 b) internal pure returns (uint256) {
    return a >= b ? a : b;
  }

  function min256(uint256 a, uint256 b) internal pure returns (uint256) {
    return a < b ? a : b;
  }
}

/**
 * @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
  );
}

contract IERC20 is ERC20 {

    function decreaseApproval(
    address _spender,
    uint _subtractedValue
  )
    public
    returns (bool);

    function increaseApproval(
    address _spender,
    uint _addedValue
  )
    public
    returns (bool);
}

/**
 * @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;
  }
}

/**
 * @title Basic token
 * @dev Basic version of StandardToken, with no allowances.
 */
contract BasicToken is ERC20Basic {
  using SafeMath for uint256;

  mapping(address => uint256) balances;

  uint256 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(_to != address(0));
    require(_value <= balances[msg.sender]);

    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];
  }

}

/**
 * @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]);

    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,
    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 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;
  }
}

/**
 * @title Interface for the ST20 token standard
 */
contract IST20 is StandardToken, DetailedERC20 {

    // off-chain hash
    string public tokenDetails;

    //transfer, transferFrom must respect use respect the result of verifyTransfer
    function verifyTransfer(address _from, address _to, uint256 _amount) public returns (bool success);

    /**
     * @notice mints new tokens and assigns them to the target _investor.
     * Can only be called by the STO attached to the token (Or by the ST owner if there's no STO attached yet)
     */
    function mint(address _investor, uint256 _amount) public returns (bool success);

    /**
     * @notice Burn function used to burn the securityToken
     * @param _value No. of token that get burned
     */
    function burn(uint256 _value) public;

    event Minted(address indexed to, uint256 amount);
    event Burnt(address indexed _burner, uint256 _value);

}

/**
 * @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.
   */
  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;
  }
}

/**
 * @title Interface for all security tokens
 */
contract ISecurityToken is IST20, Ownable {

    uint8 public constant PERMISSIONMANAGER_KEY = 1;
    uint8 public constant TRANSFERMANAGER_KEY = 2;
    uint8 public constant STO_KEY = 3;
    uint8 public constant CHECKPOINT_KEY = 4;
    uint256 public granularity;

    // Value of current checkpoint
    uint256 public currentCheckpointId;

    // Total number of non-zero token holders
    uint256 public investorCount;

    // List of token holders
    address[] public investors;

    // Permissions this to a Permission module, which has a key of 1
    // If no Permission return false - note that IModule withPerm will allow ST owner all permissions anyway
    // this allows individual modules to override this logic if needed (to not allow ST owner all permissions)
    function checkPermission(address _delegate, address _module, bytes32 _perm) public view returns(bool);

    /**
     * @notice returns module list for a module type
     * @param _moduleType is which type of module we are trying to remove
     * @param _moduleIndex is the index of the module within the chosen type
     */
    function getModule(uint8 _moduleType, uint _moduleIndex) public view returns (bytes32, address);

    /**
     * @notice returns module list for a module name - will return first match
     * @param _moduleType is which type of module we are trying to remove
     * @param _name is the name of the module within the chosen type
     */
    function getModuleByName(uint8 _moduleType, bytes32 _name) public view returns (bytes32, address);

    /**
     * @notice Queries totalSupply as of a defined checkpoint
     * @param _checkpointId Checkpoint ID to query as of
     */
    function totalSupplyAt(uint256 _checkpointId) public view returns(uint256);

    /**
     * @notice Queries balances as of a defined checkpoint
     * @param _investor Investor to query balance for
     * @param _checkpointId Checkpoint ID to query as of
     */
    function balanceOfAt(address _investor, uint256 _checkpointId) public view returns(uint256);

    /**
     * @notice Creates a checkpoint that can be used to query historical balances / totalSuppy
     */
    function createCheckpoint() public returns(uint256);

    /**
     * @notice gets length of investors array
     * NB - this length may differ from investorCount if list has not been pruned of zero balance investors
     * @return length
     */
    function getInvestorsLength() public view returns(uint256);

}

/**
 * @title Interface that any module factory contract should implement
 */
contract IModuleFactory is Ownable {

    ERC20 public polyToken;
    uint256 public setupCost;
    uint256 public usageCost;
    uint256 public monthlySubscriptionCost;

    event LogChangeFactorySetupFee(uint256 _oldSetupcost, uint256 _newSetupCost, address _moduleFactory);
    event LogChangeFactoryUsageFee(uint256 _oldUsageCost, uint256 _newUsageCost, address _moduleFactory);
    event LogChangeFactorySubscriptionFee(uint256 _oldSubscriptionCost, uint256 _newMonthlySubscriptionCost, address _moduleFactory);
    event LogGenerateModuleFromFactory(address _module, bytes32 indexed _moduleName, address indexed _moduleFactory, address _creator, uint256 _timestamp);

    /**
     * @notice Constructor
     * @param _polyAddress Address of the polytoken
     */
    constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public {
      polyToken = ERC20(_polyAddress);
      setupCost = _setupCost;
      usageCost = _usageCost;
      monthlySubscriptionCost = _subscriptionCost;
    }

    //Should create an instance of the Module, or throw
    function deploy(bytes _data) external returns(address);

    /**
     * @notice Type of the Module factory
     */
    function getType() public view returns(uint8);

    /**
     * @notice Get the name of the Module
     */
    function getName() public view returns(bytes32);

    /**
     * @notice Get the description of the Module
     */
    function getDescription() public view returns(string);

    /**
     * @notice Get the title of the Module
     */
    function getTitle() public view returns(string);

    /**
     * @notice Get the Instructions that helped to used the module
     */
    function getInstructions() public view returns (string);

    /**
     * @notice Get the tags related to the module factory
     */
    function getTags() public view returns (bytes32[]);

    //Pull function sig from _data
    function getSig(bytes _data) internal pure returns (bytes4 sig) {
        uint len = _data.length < 4 ? _data.length : 4;
        for (uint i = 0; i < len; i++) {
            sig = bytes4(uint(sig) + uint(_data[i]) * (2 ** (8 * (len - 1 - i))));
        }
    }

    /**
     * @notice used to change the fee of the setup cost
     * @param _newSetupCost new setup cost
     */
    function changeFactorySetupFee(uint256 _newSetupCost) public onlyOwner {
        emit LogChangeFactorySetupFee(setupCost, _newSetupCost, address(this));
        setupCost = _newSetupCost;
    }

    /**
     * @notice used to change the fee of the usage cost
     * @param _newUsageCost new usage cost
     */
    function changeFactoryUsageFee(uint256 _newUsageCost) public onlyOwner {
        emit LogChangeFactoryUsageFee(usageCost, _newUsageCost, address(this));
        usageCost = _newUsageCost;
    }

    /**
     * @notice used to change the fee of the subscription cost
     * @param _newSubscriptionCost new subscription cost
     */
    function changeFactorySubscriptionFee(uint256 _newSubscriptionCost) public onlyOwner {
        emit LogChangeFactorySubscriptionFee(monthlySubscriptionCost, _newSubscriptionCost, address(this));
        monthlySubscriptionCost = _newSubscriptionCost;
        
    }

}

/**
 * @title Interface that any module contract should implement
 */
contract IModule {

    address public factory;

    address public securityToken;

    bytes32 public constant FEE_ADMIN = "FEE_ADMIN";

    ERC20 public polyToken;

    /**
     * @notice Constructor
     * @param _securityToken Address of the security token
     * @param _polyAddress Address of the polytoken
     */
    constructor (address _securityToken, address _polyAddress) public {
        securityToken = _securityToken;
        factory = msg.sender;
        polyToken = ERC20(_polyAddress);
    }

    /**
     * @notice This function returns the signature of configure function
     */
    function getInitFunction() public pure returns (bytes4);

    //Allows owner, factory or permissioned delegate
    modifier withPerm(bytes32 _perm) {
        bool isOwner = msg.sender == ISecurityToken(securityToken).owner();
        bool isFactory = msg.sender == factory;
        require(isOwner||isFactory||ISecurityToken(securityToken).checkPermission(msg.sender, address(this), _perm), "Permission check failed");
        _;
    }

    modifier onlyOwner {
        require(msg.sender == ISecurityToken(securityToken).owner(), "Sender is not owner");
        _;
    }

    modifier onlyFactory {
        require(msg.sender == factory, "Sender is not factory");
        _;
    }

    modifier onlyFactoryOwner {
        require(msg.sender == IModuleFactory(factory).owner(), "Sender is not factory owner");
        _;
    }

    /**
     * @notice Return the permissions flag that are associated with Module
     */
    function getPermissions() public view returns(bytes32[]);

    /**
     * @notice used to withdraw the fee by the factory owner
     */
    function takeFee(uint256 _amount) public withPerm(FEE_ADMIN) returns(bool) {
        require(polyToken.transferFrom(address(this), IModuleFactory(factory).owner(), _amount), "Unable to take fee");
        return true;
    }
}

/**
 * @title Interface for the polymath module registry contract
 */
contract IModuleRegistry {

    /**
     * @notice Called by a security token to notify the registry it is using a module
     * @param _moduleFactory is the address of the relevant module factory
     */
    function useModule(address _moduleFactory) external;

    /**
     * @notice Called by moduleFactory owner to register new modules for SecurityToken to use
     * @param _moduleFactory is the address of the module factory to be registered
     */
    function registerModule(address _moduleFactory) external returns(bool);

    /**
     * @notice Use to get all the tags releated to the functionality of the Module Factory.
     * @param _moduleType Type of module
     */
    function getTagByModuleType(uint8 _moduleType) public view returns(bytes32[]);

}

/**
 * @title Utility contract to allow pausing and unpausing of certain functions
 */
contract Pausable {

    event Pause(uint256 _timestammp);
    event Unpause(uint256 _timestamp);

    bool public paused = false;

    /**
    * @notice Modifier to make a function callable only when the contract is not paused.
    */
    modifier whenNotPaused() {
        require(!paused);
        _;
    }

    /**
    * @notice Modifier to make a function callable only when the contract is paused.
    */
    modifier whenPaused() {
        require(paused);
        _;
    }

   /**
    * @notice called by the owner to pause, triggers stopped state
    */
    function _pause() internal {
        require(!paused);
        paused = true;
        emit Pause(now);
    }

    /**
    * @notice called by the owner to unpause, returns to normal state
    */
    function _unpause() internal {
        require(paused);
        paused = false;
        emit Unpause(now);
    }

}

/**
 * @title Interface to be implemented by all Transfer Manager modules
 */
contract ITransferManager is IModule, Pausable {

    //If verifyTransfer returns:
    //  FORCE_VALID, the transaction will always be valid, regardless of other TM results
    //  INVALID, then the transfer should not be allowed regardless of other TM results
    //  VALID, then the transfer is valid for this TM
    //  NA, then the result from this TM is ignored
    enum Result {INVALID, NA, VALID, FORCE_VALID}

    function verifyTransfer(address _from, address _to, uint256 _amount, bool _isTransfer) public returns(Result);

    function unpause() onlyOwner public {
        super._unpause();
    }

    function pause() onlyOwner public {
        super._pause();
    }
}

/**
 * @title Interface to be implemented by all permission manager modules
 */
contract IPermissionManager is IModule {

    function checkPermission(address _delegate, address _module, bytes32 _perm) public view returns(bool);

    function changePermission(address _delegate, address _module, bytes32 _perm, bool _valid) public returns(bool);

    function getDelegateDetails(address _delegate) public view returns(bytes32);

}

/**
 * @title Interface for the token burner contract
 */
interface ITokenBurner {

    function burn(address _burner, uint256  _value ) external returns(bool);

}

/**
 * @title Utility contract to allow owner to retreive any ERC20 sent to the contract
 */
contract ReclaimTokens is Ownable {

    /**
    * @notice Reclaim all ERC20Basic compatible tokens
    * @param _tokenContract The address of the token contract
    */
    function reclaimERC20(address _tokenContract) external onlyOwner {
        require(_tokenContract != address(0));
        ERC20Basic token = ERC20Basic(_tokenContract);
        uint256 balance = token.balanceOf(address(this));
        require(token.transfer(owner, balance));
    }
}

/**
 * @title Core functionality for registry upgradability
 */
contract PolymathRegistry is ReclaimTokens {

    mapping (bytes32 => address) public storedAddresses;

    event LogChangeAddress(string _nameKey, address indexed _oldAddress, address indexed _newAddress);

    /**
     * @notice Get the contract address
     * @param _nameKey is the key for the contract address mapping
     * @return address
     */
    function getAddress(string _nameKey) view public returns(address) {
        bytes32 key = keccak256(bytes(_nameKey));
        require(storedAddresses[key] != address(0), "Invalid address key");
        return storedAddresses[key];
    }

    /**
     * @notice change the contract address
     * @param _nameKey is the key for the contract address mapping
     * @param _newAddress is the new contract address
     */
    function changeAddress(string _nameKey, address _newAddress) public onlyOwner {
        bytes32 key = keccak256(bytes(_nameKey));
        emit LogChangeAddress(_nameKey, storedAddresses[key], _newAddress);
        storedAddresses[key] = _newAddress;
    }


}

contract RegistryUpdater is Ownable {

    address public polymathRegistry;
    address public moduleRegistry;
    address public securityTokenRegistry;
    address public tickerRegistry;
    address public polyToken;

    constructor (address _polymathRegistry) public {
        require(_polymathRegistry != address(0));
        polymathRegistry = _polymathRegistry;
    }

    function updateFromRegistry() onlyOwner public {
        moduleRegistry = PolymathRegistry(polymathRegistry).getAddress("ModuleRegistry");
        securityTokenRegistry = PolymathRegistry(polymathRegistry).getAddress("SecurityTokenRegistry");
        tickerRegistry = PolymathRegistry(polymathRegistry).getAddress("TickerRegistry");
        polyToken = PolymathRegistry(polymathRegistry).getAddress("PolyToken");
    }

}

/**
 * @title Helps contracts guard agains reentrancy attacks.
 * @author Remco Bloemen <remco@2π.com>
 * @notice If you mark a function `nonReentrant`, you should also
 * mark it `external`.
 */
contract ReentrancyGuard {

  /**
   * @dev We use a single lock for the whole contract.
   */
  bool private reentrancyLock = false;

  /**
   * @dev Prevents a contract from calling itself, directly or indirectly.
   * @notice If you mark a function `nonReentrant`, you should also
   * mark it `external`. Calling one nonReentrant function from
   * another is not supported. Instead, you can implement a
   * `private` function doing the actual work, and a `external`
   * wrapper marked as `nonReentrant`.
   */
  modifier nonReentrant() {
    require(!reentrancyLock);
    reentrancyLock = true;
    _;
    reentrancyLock = false;
  }

}

/**
* @title Security Token contract
* @notice SecurityToken is an ERC20 token with added capabilities:
* @notice - Implements the ST-20 Interface
* @notice - Transfers are restricted
* @notice - Modules can be attached to it to control its behaviour
* @notice - ST should not be deployed directly, but rather the SecurityTokenRegistry should be used
*/
contract SecurityToken is ISecurityToken, ReentrancyGuard, RegistryUpdater {
    using SafeMath for uint256;

    bytes32 public constant securityTokenVersion = "0.0.1";

    // Reference to token burner contract
    ITokenBurner public tokenBurner;

    // Use to halt all the transactions
    bool public freeze = false;

    struct ModuleData {
        bytes32 name;
        address moduleAddress;
    }

    // Structures to maintain checkpoints of balances for governance / dividends
    struct Checkpoint {
        uint256 checkpointId;
        uint256 value;
    }

    mapping (address => Checkpoint[]) public checkpointBalances;
    Checkpoint[] public checkpointTotalSupply;

    bool public finishedIssuerMinting = false;
    bool public finishedSTOMinting = false;

    mapping (bytes4 => bool) transferFunctions;

    // Module list should be order agnostic!
    mapping (uint8 => ModuleData[]) public modules;

    uint8 public constant MAX_MODULES = 20;

    mapping (address => bool) public investorListed;

    // Emit at the time when module get added
    event LogModuleAdded(
        uint8 indexed _type,
        bytes32 _name,
        address _moduleFactory,
        address _module,
        uint256 _moduleCost,
        uint256 _budget,
        uint256 _timestamp
    );

    // Emit when the token details get updated
    event LogUpdateTokenDetails(string _oldDetails, string _newDetails);
    // Emit when the granularity get changed
    event LogGranularityChanged(uint256 _oldGranularity, uint256 _newGranularity);
    // Emit when Module get removed from the securityToken
    event LogModuleRemoved(uint8 indexed _type, address _module, uint256 _timestamp);
    // Emit when the budget allocated to a module is changed
    event LogModuleBudgetChanged(uint8 indexed _moduleType, address _module, uint256 _budget);
    // Emit when all the transfers get freeze
    event LogFreezeTransfers(bool _freeze, uint256 _timestamp);
    // Emit when new checkpoint created
    event LogCheckpointCreated(uint256 indexed _checkpointId, uint256 _timestamp);
    // Emit when the minting get finished for the Issuer
    event LogFinishMintingIssuer(uint256 _timestamp);
    // Emit when the minting get finished for the STOs
    event LogFinishMintingSTO(uint256 _timestamp);
    // Change the STR address in the event of a upgrade
    event LogChangeSTRAddress(address indexed _oldAddress, address indexed _newAddress);

    // If _fallback is true, then for STO module type we only allow the module if it is set, if it is not set we only allow the owner
    // for other _moduleType we allow both issuer and module.
    modifier onlyModule(uint8 _moduleType, bool _fallback) {
      //Loop over all modules of type _moduleType
        bool isModuleType = false;
        for (uint8 i = 0; i < modules[_moduleType].length; i++) {
            isModuleType = isModuleType || (modules[_moduleType][i].moduleAddress == msg.sender);
        }
        if (_fallback && !isModuleType) {
            if (_moduleType == STO_KEY)
                require(modules[_moduleType].length == 0 && msg.sender == owner, "Sender is not owner or STO module is attached");
            else
                require(msg.sender == owner, "Sender is not owner");
        } else {
            require(isModuleType, "Sender is not correct module type");
        }
        _;
    }

    modifier checkGranularity(uint256 _amount) {
        require(_amount % granularity == 0, "Unable to modify token balances at this granularity");
        _;
    }

    // Checks whether the minting is allowed or not, check for the owner if owner is no the msg.sender then check
    // for the finishedSTOMinting flag because only STOs and owner are allowed for minting
    modifier isMintingAllowed() {
        if (msg.sender == owner) {
            require(!finishedIssuerMinting, "Minting is finished for Issuer");
        } else {
            require(!finishedSTOMinting, "Minting is finished for STOs");
        }
        _;
    }

    /**
     * @notice Constructor
     * @param _name Name of the SecurityToken
     * @param _symbol Symbol of the Token
     * @param _decimals Decimals for the securityToken
     * @param _granularity granular level of the token
     * @param _tokenDetails Details of the token that are stored off-chain (IPFS hash)
     * @param _polymathRegistry Contract address of the polymath registry
     */
    constructor (
        string _name,
        string _symbol,
        uint8 _decimals,
        uint256 _granularity,
        string _tokenDetails,
        address _polymathRegistry
    )
    public
    DetailedERC20(_name, _symbol, _decimals)
    RegistryUpdater(_polymathRegistry)
    {
        //When it is created, the owner is the STR
        updateFromRegistry();
        tokenDetails = _tokenDetails;
        granularity = _granularity;
        transferFunctions[bytes4(keccak256("transfer(address,uint256)"))] = true;
        transferFunctions[bytes4(keccak256("transferFrom(address,address,uint256)"))] = true;
        transferFunctions[bytes4(keccak256("mint(address,uint256)"))] = true;
        transferFunctions[bytes4(keccak256("burn(uint256)"))] = true;
    }

    /**
     * @notice Function used to attach the module in security token
     * @param _moduleFactory Contract address of the module factory that needs to be attached
     * @param _data Data used for the intialization of the module factory variables
     * @param _maxCost Maximum cost of the Module factory
     * @param _budget Budget of the Module factory
     */
    function addModule(
        address _moduleFactory,
        bytes _data,
        uint256 _maxCost,
        uint256 _budget
    ) external onlyOwner nonReentrant {
        _addModule(_moduleFactory, _data, _maxCost, _budget);
    }

    /**
    * @notice _addModule handles the attachment (or replacement) of modules for the ST
    * @dev  E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it
    * @dev to control restrictions on transfers.
    * @dev You are allowed to add a new moduleType if:
    * @dev - there is no existing module of that type yet added
    * @dev - the last member of the module list is replacable
    * @param _moduleFactory is the address of the module factory to be added
    * @param _data is data packed into bytes used to further configure the module (See STO usage)
    * @param _maxCost max amount of POLY willing to pay to module. (WIP)
    */
    function _addModule(address _moduleFactory, bytes _data, uint256 _maxCost, uint256 _budget) internal {
        //Check that module exists in registry - will throw otherwise
        IModuleRegistry(moduleRegistry).useModule(_moduleFactory);
        IModuleFactory moduleFactory = IModuleFactory(_moduleFactory);
        uint8 moduleType = moduleFactory.getType();
        require(modules[moduleType].length < MAX_MODULES, "Limit of MAX MODULES is reached");
        uint256 moduleCost = moduleFactory.setupCost();
        require(moduleCost <= _maxCost, "Max Cost is always be greater than module cost");
        //Approve fee for module
        require(ERC20(polyToken).approve(_moduleFactory, moduleCost), "Not able to approve the module cost");
        //Creates instance of module from factory
        address module = moduleFactory.deploy(_data);
        //Approve ongoing budget
        require(ERC20(polyToken).approve(module, _budget), "Not able to approve the budget");
        //Add to SecurityToken module map
        bytes32 moduleName = moduleFactory.getName();
        modules[moduleType].push(ModuleData(moduleName, module));
        //Emit log event
        emit LogModuleAdded(moduleType, moduleName, _moduleFactory, module, moduleCost, _budget, now);
    }

    /**
    * @notice Removes a module attached to the SecurityToken
    * @param _moduleType is which type of module we are trying to remove
    * @param _moduleIndex is the index of the module within the chosen type
    */
    function removeModule(uint8 _moduleType, uint8 _moduleIndex) external onlyOwner {
        require(_moduleIndex < modules[_moduleType].length,
        "Module index doesn't exist as per the choosen module type");
        require(modules[_moduleType][_moduleIndex].moduleAddress != address(0),
        "Module contract address should not be 0x");
        //Take the last member of the list, and replace _moduleIndex with this, then shorten the list by one
        emit LogModuleRemoved(_moduleType, modules[_moduleType][_moduleIndex].moduleAddress, now);
        modules[_moduleType][_moduleIndex] = modules[_moduleType][modules[_moduleType].length - 1];
        modules[_moduleType].length = modules[_moduleType].length - 1;
    }

    /**
     * @notice Returns module list for a module type
     * @param _moduleType is which type of module we are trying to get
     * @param _moduleIndex is the index of the module within the chosen type
     * @return bytes32
     * @return address
     */
    function getModule(uint8 _moduleType, uint _moduleIndex) public view returns (bytes32, address) {
        if (modules[_moduleType].length > 0) {
            return (
                modules[_moduleType][_moduleIndex].name,
                modules[_moduleType][_moduleIndex].moduleAddress
            );
        } else {
            return ("", address(0));
        }

    }

    /**
     * @notice returns module list for a module name - will return first match
     * @param _moduleType is which type of module we are trying to get
     * @param _name is the name of the module within the chosen type
     * @return bytes32
     * @return address
     */
    function getModuleByName(uint8 _moduleType, bytes32 _name) public view returns (bytes32, address) {
        if (modules[_moduleType].length > 0) {
            for (uint256 i = 0; i < modules[_moduleType].length; i++) {
                if (modules[_moduleType][i].name == _name) {
                  return (
                      modules[_moduleType][i].name,
                      modules[_moduleType][i].moduleAddress
                  );
                }
            }
            return ("", address(0));
        } else {
            return ("", address(0));
        }
    }

    /**
    * @notice allows the owner to withdraw unspent POLY stored by them on the ST.
    * @dev Owner can transfer POLY to the ST which will be used to pay for modules that require a POLY fee.
    * @param _amount amount of POLY to withdraw
    */
    function withdrawPoly(uint256 _amount) public onlyOwner {
        require(ERC20(polyToken).transfer(owner, _amount), "In-sufficient balance");
    }

    /**
    * @notice allows owner to approve more POLY to one of the modules
    * @param _moduleType module type
    * @param _moduleIndex module index
    * @param _budget new budget
    */
    function changeModuleBudget(uint8 _moduleType, uint8 _moduleIndex, uint256 _budget) public onlyOwner {
        require(_moduleType != 0, "Module type cannot be zero");
        require(_moduleIndex < modules[_moduleType].length, "Incorrrect module index");
        uint256 _currentAllowance = IERC20(polyToken).allowance(address(this), modules[_moduleType][_moduleIndex].moduleAddress);
        if (_budget < _currentAllowance) {
            require(IERC20(polyToken).decreaseApproval(modules[_moduleType][_moduleIndex].moduleAddress, _currentAllowance.sub(_budget)), "Insufficient balance to decreaseApproval");
        } else {
            require(IERC20(polyToken).increaseApproval(modules[_moduleType][_moduleIndex].moduleAddress, _budget.sub(_currentAllowance)), "Insufficient balance to increaseApproval");
        }
        emit LogModuleBudgetChanged(_moduleType, modules[_moduleType][_moduleIndex].moduleAddress, _budget);
    }

    /**
     * @notice change the tokenDetails
     * @param _newTokenDetails New token details
     */
    function updateTokenDetails(string _newTokenDetails) public onlyOwner {
        emit LogUpdateTokenDetails(tokenDetails, _newTokenDetails);
        tokenDetails = _newTokenDetails;
    }

    /**
    * @notice allows owner to change token granularity
    * @param _granularity granularity level of the token
    */
    function changeGranularity(uint256 _granularity) public onlyOwner {
        require(_granularity != 0, "Granularity can not be 0");
        emit LogGranularityChanged(granularity, _granularity);
        granularity = _granularity;
    }

    /**
    * @notice keeps track of the number of non-zero token holders
    * @param _from sender of transfer
    * @param _to receiver of transfer
    * @param _value value of transfer
    */
    function adjustInvestorCount(address _from, address _to, uint256 _value) internal {
        if ((_value == 0) || (_from == _to)) {
            return;
        }
        // Check whether receiver is a new token holder
        if ((balanceOf(_to) == 0) && (_to != address(0))) {
            investorCount = investorCount.add(1);
        }
        // Check whether sender is moving all of their tokens
        if (_value == balanceOf(_from)) {
            investorCount = investorCount.sub(1);
        }
        //Also adjust investor list
        if (!investorListed[_to] && (_to != address(0))) {
            investors.push(_to);
            investorListed[_to] = true;
        }

    }

    /**
    * @notice removes addresses with zero balances from the investors list
    * @param _start Index in investor list at which to start removing zero balances
    * @param _iters Max number of iterations of the for loop
    * NB - pruning this list will mean you may not be able to iterate over investors on-chain as of a historical checkpoint
    */
    function pruneInvestors(uint256 _start, uint256 _iters) public onlyOwner {
        for (uint256 i = _start; i < Math.min256(_start.add(_iters), investors.length); i++) {
            if ((i < investors.length) && (balanceOf(investors[i]) == 0)) {
                investorListed[investors[i]] = false;
                investors[i] = investors[investors.length - 1];
                investors.length--;
            }
        }
    }

    /**
     * @notice gets length of investors array
     * NB - this length may differ from investorCount if list has not been pruned of zero balance investors
     * @return length
     */
    function getInvestorsLength() public view returns(uint256) {
        return investors.length;
    }

    /**
     * @notice freeze all the transfers
     */
    function freezeTransfers() public onlyOwner {
        require(!freeze);
        freeze = true;
        emit LogFreezeTransfers(freeze, now);
    }

    /**
     * @notice un-freeze all the transfers
     */
    function unfreezeTransfers() public onlyOwner {
        require(freeze);
        freeze = false;
        emit LogFreezeTransfers(freeze, now);
    }

    /**
     * @notice adjust totalsupply at checkpoint after minting or burning tokens
     */
    function adjustTotalSupplyCheckpoints() internal {
        adjustCheckpoints(checkpointTotalSupply, totalSupply());
    }

    /**
     * @notice adjust token holder balance at checkpoint after a token transfer
     * @param _investor address of the token holder affected
     */
    function adjustBalanceCheckpoints(address _investor) internal {
        adjustCheckpoints(checkpointBalances[_investor], balanceOf(_investor));
    }

    /**
     * @notice store the changes to the checkpoint objects
     * @param _checkpoints the affected checkpoint object array
     * @param _newValue the new value that needs to be stored
     */
    function adjustCheckpoints(Checkpoint[] storage _checkpoints, uint256 _newValue) internal {
        //No checkpoints set yet
        if (currentCheckpointId == 0) {
            return;
        }
        //No previous checkpoint data - add current balance against checkpoint
        if (_checkpoints.length == 0) {
            _checkpoints.push(
                Checkpoint({
                    checkpointId: currentCheckpointId,
                    value: _newValue
                })
            );
            return;
        }
        //No new checkpoints since last update
        if (_checkpoints[_checkpoints.length - 1].checkpointId == currentCheckpointId) {
            return;
        }
        //New checkpoint, so record balance
        _checkpoints.push(
            Checkpoint({
                checkpointId: currentCheckpointId,
                value: _newValue
            })
        );
    }

    /**
     * @notice Overloaded version of the transfer function
     * @param _to receiver of transfer
     * @param _value value of transfer
     * @return bool success
     */
    function transfer(address _to, uint256 _value) public returns (bool success) {
        adjustInvestorCount(msg.sender, _to, _value);
        require(verifyTransfer(msg.sender, _to, _value), "Transfer is not valid");
        adjustBalanceCheckpoints(msg.sender);
        adjustBalanceCheckpoints(_to);
        require(super.transfer(_to, _value));
        return true;
    }

    /**
     * @notice Overloaded version of the transferFrom function
     * @param _from sender of transfer
     * @param _to receiver of transfer
     * @param _value value of transfer
     * @return bool success
     */
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        adjustInvestorCount(_from, _to, _value);
        require(verifyTransfer(_from, _to, _value), "Transfer is not valid");
        adjustBalanceCheckpoints(_from);
        adjustBalanceCheckpoints(_to);
        require(super.transferFrom(_from, _to, _value));
        return true;
    }

    /**
     * @notice validate transfer with TransferManager module if it exists
     * @dev TransferManager module has a key of 2
     * @param _from sender of transfer
     * @param _to receiver of transfer
     * @param _amount value of transfer
     * @return bool
     */
    function verifyTransfer(address _from, address _to, uint256 _amount) public checkGranularity(_amount) returns (bool) {
        if (!freeze) {
            bool isTransfer = false;
            if (transferFunctions[getSig(msg.data)]) {
              isTransfer = true;
            }
            if (modules[TRANSFERMANAGER_KEY].length == 0) {
                return true;
            }
            bool isInvalid = false;
            bool isValid = false;
            bool isForceValid = false;
            for (uint8 i = 0; i < modules[TRANSFERMANAGER_KEY].length; i++) {
                ITransferManager.Result valid = ITransferManager(modules[TRANSFERMANAGER_KEY][i].moduleAddress).verifyTransfer(_from, _to, _amount, isTransfer);
                if (valid == ITransferManager.Result.INVALID) {
                    isInvalid = true;
                }
                if (valid == ITransferManager.Result.VALID) {
                    isValid = true;
                }
                if (valid == ITransferManager.Result.FORCE_VALID) {
                    isForceValid = true;
                }
            }
            return isForceValid ? true : (isInvalid ? false : isValid);
      }
      return false;
    }

    /**
     * @notice End token minting period permanently for Issuer
     */
    function finishMintingIssuer() public onlyOwner {
        finishedIssuerMinting = true;
        emit LogFinishMintingIssuer(now);
    }

    /**
     * @notice End token minting period permanently for STOs
     */
    function finishMintingSTO() public onlyOwner {
        finishedSTOMinting = true;
        emit LogFinishMintingSTO(now);
    }

    /**
     * @notice mints new tokens and assigns them to the target _investor.
     * @dev Can only be called by the STO attached to the token (Or by the ST owner if there's no STO attached yet)
     * @param _investor Address to whom the minted tokens will be dilivered
     * @param _amount Number of tokens get minted
     * @return success
     */
    function mint(address _investor, uint256 _amount) public onlyModule(STO_KEY, true) checkGranularity(_amount) isMintingAllowed() returns (bool success) {
        require(_investor != address(0), "Investor address should not be 0x");
        adjustInvestorCount(address(0), _investor, _amount);
        require(verifyTransfer(address(0), _investor, _amount), "Transfer is not valid");
        adjustBalanceCheckpoints(_investor);
        adjustTotalSupplyCheckpoints();
        totalSupply_ = totalSupply_.add(_amount);
        balances[_investor] = balances[_investor].add(_amount);
        emit Minted(_investor, _amount);
        emit Transfer(address(0), _investor, _amount);
        return true;
    }

    /**
     * @notice mints new tokens and assigns them to the target _investor.
     * Can only be called by the STO attached to the token (Or by the ST owner if there's no STO attached yet)
     * @param _investors A list of addresses to whom the minted tokens will be dilivered
     * @param _amounts A list of number of tokens get minted and transfer to corresponding address of the investor from _investor[] list
     * @return success
     */
    function mintMulti(address[] _investors, uint256[] _amounts) public onlyModule(STO_KEY, true) returns (bool success) {
        require(_investors.length == _amounts.length, "Mis-match in the length of the arrays");
        for (uint256 i = 0; i < _investors.length; i++) {
            mint(_investors[i], _amounts[i]);
        }
        return true;
    }

    /**
     * @notice Validate permissions with PermissionManager if it exists, If no Permission return false
     * @dev Note that IModule withPerm will allow ST owner all permissions anyway
     * @dev this allows individual modules to override this logic if needed (to not allow ST owner all permissions)
     * @param _delegate address of delegate
     * @param _module address of PermissionManager module
     * @param _perm the permissions
     * @return success
     */
    function checkPermission(address _delegate, address _module, bytes32 _perm) public view returns(bool) {
        if (modules[PERMISSIONMANAGER_KEY].length == 0) {
            return false;
        }

        for (uint8 i = 0; i < modules[PERMISSIONMANAGER_KEY].length; i++) {
            if (IPermissionManager(modules[PERMISSIONMANAGER_KEY][i].moduleAddress).checkPermission(_delegate, _module, _perm)) {
                return true;
            }
        }
    }

    /**
     * @notice used to set the token Burner address. It only be called by the owner
     * @param _tokenBurner Address of the token burner contract
     */
    function setTokenBurner(address _tokenBurner) public onlyOwner {
        tokenBurner = ITokenBurner(_tokenBurner);
    }

    /**
     * @notice Burn function used to burn the securityToken
     * @param _value No. of token that get burned
     */
    function burn(uint256 _value) checkGranularity(_value) public {
        adjustInvestorCount(msg.sender, address(0), _value);
        require(tokenBurner != address(0), "Token Burner contract address is not set yet");
        require(verifyTransfer(msg.sender, address(0), _value), "Transfer is not valid");
        require(_value <= balances[msg.sender], "Value should no be greater than the balance of msg.sender");
        adjustBalanceCheckpoints(msg.sender);
        adjustTotalSupplyCheckpoints();
        // no need to require value <= totalSupply, since that would imply the
        // sender's balance is greater than the totalSupply, which *should* be an assertion failure

        balances[msg.sender] = balances[msg.sender].sub(_value);
        require(tokenBurner.burn(msg.sender, _value), "Token burner process is not validated");
        totalSupply_ = totalSupply_.sub(_value);
        emit Burnt(msg.sender, _value);
        emit Transfer(msg.sender, address(0), _value);
    }

    /**
     * @notice Get function signature from _data
     * @param _data passed data
     * @return bytes4 sig
     */
    function getSig(bytes _data) internal pure returns (bytes4 sig) {
        uint len = _data.length < 4 ? _data.length : 4;
        for (uint i = 0; i < len; i++) {
            sig = bytes4(uint(sig) + uint(_data[i]) * (2 ** (8 * (len - 1 - i))));
        }
    }

    /**
     * @notice Creates a checkpoint that can be used to query historical balances / totalSuppy
     * @return uint256
     */
    function createCheckpoint() public onlyModule(CHECKPOINT_KEY, true) returns(uint256) {
        require(currentCheckpointId < 2**256 - 1);
        currentCheckpointId = currentCheckpointId + 1;
        emit LogCheckpointCreated(currentCheckpointId, now);
        return currentCheckpointId;
    }

    /**
     * @notice Queries totalSupply as of a defined checkpoint
     * @param _checkpointId Checkpoint ID to query
     * @return uint256
     */
    function totalSupplyAt(uint256 _checkpointId) public view returns(uint256) {
        return getValueAt(checkpointTotalSupply, _checkpointId, totalSupply());
    }

    /**
     * @notice Queries value at a defined checkpoint
     * @param checkpoints is array of Checkpoint objects
     * @param _checkpointId Checkpoint ID to query
     * @param _currentValue Current value of checkpoint
     * @return uint256
     */
    function getValueAt(Checkpoint[] storage checkpoints, uint256 _checkpointId, uint256 _currentValue) internal view returns(uint256) {
        require(_checkpointId <= currentCheckpointId);
        //Checkpoint id 0 is when the token is first created - everyone has a zero balance
        if (_checkpointId == 0) {
          return 0;
        }
        if (checkpoints.length == 0) {
            return _currentValue;
        }
        if (checkpoints[0].checkpointId >= _checkpointId) {
            return checkpoints[0].value;
        }
        if (checkpoints[checkpoints.length - 1].checkpointId < _checkpointId) {
            return _currentValue;
        }
        if (checkpoints[checkpoints.length - 1].checkpointId == _checkpointId) {
            return checkpoints[checkpoints.length - 1].value;
        }
        uint256 min = 0;
        uint256 max = checkpoints.length - 1;
        while (max > min) {
            uint256 mid = (max + min) / 2;
            if (checkpoints[mid].checkpointId == _checkpointId) {
                max = mid;
                break;
            }
            if (checkpoints[mid].checkpointId < _checkpointId) {
                min = mid + 1;
            } else {
                max = mid;
            }
        }
        return checkpoints[max].value;
    }

    /**
     * @notice Queries balances as of a defined checkpoint
     * @param _investor Investor to query balance for
     * @param _checkpointId Checkpoint ID to query as of
     */
    function balanceOfAt(address _investor, uint256 _checkpointId) public view returns(uint256) {
        return getValueAt(checkpointBalances[_investor], _checkpointId, balanceOf(_investor));
    }

}

/**
 * @title Interface for security token proxy deployment
 */
contract ISTProxy {

    /**
     * @notice deploys the token and adds default modules like permission manager and transfer manager.
     * Future versions of the proxy can attach different modules or pass some other paramters.
     */
    function deployToken(string _name, string _symbol, uint8 _decimals, string _tokenDetails, address _issuer, bool _divisible, address _polymathRegistry)
        public returns (address);
}

/**
 * @title Interface for the polymath security token registry contract
 */
contract ISecurityTokenRegistry {

    bytes32 public protocolVersion = "0.0.1";
    mapping (bytes32 => address) public protocolVersionST;

    struct SecurityTokenData {
        string symbol;
        string tokenDetails;
    }

    mapping(address => SecurityTokenData) securityTokens;
    mapping(string => address) symbols;

    /**
     * @notice Creates a new Security Token and saves it to the registry
     * @param _name Name of the token
     * @param _symbol Ticker symbol of the security token
     * @param _tokenDetails off-chain details of the token
     */
    function generateSecurityToken(string _name, string _symbol, string _tokenDetails, bool _divisible) public;

    function setProtocolVersion(address _stVersionProxyAddress, bytes32 _version) public;

    /**
     * @notice Get security token address by ticker name
     * @param _symbol Symbol of the Scurity token
     * @return address _symbol
     */
    function getSecurityTokenAddress(string _symbol) public view returns (address);

     /**
     * @notice Get security token data by its address
     * @param _securityToken Address of the Scurity token
     * @return string, address, bytes32
     */
    function getSecurityTokenData(address _securityToken) public view returns (string, address, string);

    /**
    * @notice Check that Security Token is registered
    * @param _securityToken Address of the Scurity token
    * @return bool
    */
    function isSecurityToken(address _securityToken) public view returns (bool);
}

/**
 * @title Utility contract for reusable code
 */
contract Util {

   /**
    * @notice changes a string to upper case
    * @param _base string to change
    */
    function upper(string _base) internal pure returns (string) {
        bytes memory _baseBytes = bytes(_base);
        for (uint i = 0; i < _baseBytes.length; i++) {
            bytes1 b1 = _baseBytes[i];
            if (b1 >= 0x61 && b1 <= 0x7A) {
                b1 = bytes1(uint8(b1)-32);
            }
            _baseBytes[i] = b1;
        }
        return string(_baseBytes);
    }

}

/**
 * @title Registry contract for issuers to register their security tokens
 */
contract SecurityTokenRegistry is ISecurityTokenRegistry, Util, Pausable, RegistryUpdater, ReclaimTokens {

    // Registration fee in POLY base 18 decimals
    uint256 public registrationFee;
    // Emit when changePolyRegisterationFee is called
    event LogChangePolyRegisterationFee(uint256 _oldFee, uint256 _newFee);

    // Emit at the time of launching of new security token
    event LogNewSecurityToken(string _ticker, address indexed _securityTokenAddress, address indexed _owner);
    event LogAddCustomSecurityToken(string _name, string _symbol, address _securityToken, uint256 _addedAt);

    constructor (
        address _polymathRegistry,
        address _stVersionProxy,
        uint256 _registrationFee
    )
    public
    RegistryUpdater(_polymathRegistry)
    {
        registrationFee = _registrationFee;
        // By default, the STR version is set to 0.0.1
        setProtocolVersion(_stVersionProxy, "0.0.1");
    }

    /**
     * @notice Creates a new Security Token and saves it to the registry
     * @param _name Name of the token
     * @param _symbol Ticker symbol of the security token
     * @param _tokenDetails off-chain details of the token
     * @param _divisible Set to true if token is divisible
     */
    function generateSecurityToken(string _name, string _symbol, string _tokenDetails, bool _divisible) public whenNotPaused {
        require(bytes(_name).length > 0 && bytes(_symbol).length > 0, "Name and Symbol string length should be greater than 0");
        require(ITickerRegistry(tickerRegistry).checkValidity(_symbol, msg.sender, _name), "Trying to use non-valid symbol");
        if(registrationFee > 0)
            require(ERC20(polyToken).transferFrom(msg.sender, this, registrationFee), "Failed transferFrom because of sufficent Allowance is not provided");
        string memory symbol = upper(_symbol);
        address newSecurityTokenAddress = ISTProxy(protocolVersionST[protocolVersion]).deployToken(
            _name,
            symbol,
            18,
            _tokenDetails,
            msg.sender,
            _divisible,
            polymathRegistry
        );

        securityTokens[newSecurityTokenAddress] = SecurityTokenData(symbol, _tokenDetails);
        symbols[symbol] = newSecurityTokenAddress;
        emit LogNewSecurityToken(symbol, newSecurityTokenAddress, msg.sender);
    }

    /**
     * @notice Add a new custom (Token should follow the ISecurityToken interface) Security Token and saves it to the registry
     * @param _name Name of the token
     * @param _symbol Ticker symbol of the security token
     * @param _owner Owner of the token
     * @param _securityToken Address of the securityToken
     * @param _tokenDetails off-chain details of the token
     * @param _swarmHash off-chain details about the issuer company
     */
    function addCustomSecurityToken(string _name, string _symbol, address _owner, address _securityToken, string _tokenDetails, bytes32 _swarmHash) public onlyOwner whenNotPaused {
        require(bytes(_name).length > 0 && bytes(_symbol).length > 0, "Name and Symbol string length should be greater than 0");
        string memory symbol = upper(_symbol);
        require(_securityToken != address(0) && symbols[symbol] == address(0), "Symbol is already at the polymath network or entered security token address is 0x");
        require(_owner != address(0));
        require(!(ITickerRegistry(tickerRegistry).isReserved(symbol, _owner, _name, _swarmHash)), "Trying to use non-valid symbol");
        symbols[symbol] = _securityToken;
        securityTokens[_securityToken] = SecurityTokenData(symbol, _tokenDetails);
        emit LogAddCustomSecurityToken(_name, symbol, _securityToken, now);
    }

    /**
    * @notice Changes the protocol version and the SecurityToken contract
    * @notice Used only by Polymath to upgrade the SecurityToken contract and add more functionalities to future versions
    * @notice Changing versions does not affect existing tokens.
    */
    function setProtocolVersion(address _stVersionProxyAddress, bytes32 _version) public onlyOwner {
        protocolVersion = _version;
        protocolVersionST[_version] = _stVersionProxyAddress;
    }

    //////////////////////////////
    ///////// Get Functions
    //////////////////////////////
    /**
     * @notice Get security token address by ticker name
     * @param _symbol Symbol of the Scurity token
     * @return address
     */
    function getSecurityTokenAddress(string _symbol) public view returns (address) {
        string memory __symbol = upper(_symbol);
        return symbols[__symbol];
    }

     /**
     * @notice Get security token data by its address
     * @param _securityToken Address of the Scurity token
     * @return string
     * @return address
     * @return string
     */
    function getSecurityTokenData(address _securityToken) public view returns (string, address, string) {
        return (
            securityTokens[_securityToken].symbol,
            ISecurityToken(_securityToken).owner(),
            securityTokens[_securityToken].tokenDetails
        );
    }

    /**
    * @notice Check that Security Token is registered
    * @param _securityToken Address of the Scurity token
    * @return bool
    */
    function isSecurityToken(address _securityToken) public view returns (bool) {
        return (keccak256(bytes(securityTokens[_securityToken].symbol)) != keccak256(""));
    }

    /**
     * @notice set the ticker registration fee in POLY tokens
     * @param _registrationFee registration fee in POLY tokens (base 18 decimals)
     */
    function changePolyRegisterationFee(uint256 _registrationFee) public onlyOwner {
        require(registrationFee != _registrationFee);
        emit LogChangePolyRegisterationFee(registrationFee, _registrationFee);
        registrationFee = _registrationFee;
    }

     /**
     * @notice pause registration function
     */
    function unpause() public onlyOwner  {
        _unpause();
    }

    /**
     * @notice unpause registration function
     */
    function pause() public onlyOwner {
        _pause();
    }

}

Contract Security Audit

Contract ABI

[{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_owner","type":"address"},{"name":"_securityToken","type":"address"},{"name":"_tokenDetails","type":"string"},{"name":"_swarmHash","type":"bytes32"}],"name":"addCustomSecurityToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"registrationFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_stVersionProxyAddress","type":"address"},{"name":"_version","type":"bytes32"}],"name":"setProtocolVersion","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tickerRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"protocolVersion","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"polyToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"protocolVersionST","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"polymathRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenContract","type":"address"}],"name":"reclaimERC20","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":"_securityToken","type":"address"}],"name":"getSecurityTokenData","outputs":[{"name":"","type":"string"},{"name":"","type":"address"},{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_registrationFee","type":"uint256"}],"name":"changePolyRegisterationFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"moduleRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_tokenDetails","type":"string"},{"name":"_divisible","type":"bool"}],"name":"generateSecurityToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"securityTokenRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_securityToken","type":"address"}],"name":"isSecurityToken","outputs":[{"name":"","type":"bool"}],"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":"updateFromRegistry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_symbol","type":"string"}],"name":"getSecurityTokenAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_polymathRegistry","type":"address"},{"name":"_stVersionProxy","type":"address"},{"name":"_registrationFee","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_oldFee","type":"uint256"},{"indexed":false,"name":"_newFee","type":"uint256"}],"name":"LogChangePolyRegisterationFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_ticker","type":"string"},{"indexed":true,"name":"_securityTokenAddress","type":"address"},{"indexed":true,"name":"_owner","type":"address"}],"name":"LogNewSecurityToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_name","type":"string"},{"indexed":false,"name":"_symbol","type":"string"},{"indexed":false,"name":"_securityToken","type":"address"},{"indexed":false,"name":"_addedAt","type":"uint256"}],"name":"LogAddCustomSecurityToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","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":false,"name":"_timestammp","type":"uint256"}],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_timestamp","type":"uint256"}],"name":"Unpause","type":"event"}]

60806040527f302e302e310000000000000000000000000000000000000000000000000000006000556004805460ff1916905534801561003e57600080fd5b50604051606080620021f18339810160409081528151602083015191909201516004805461010060a860020a031916336101000217905582600160a060020a038116151561008b57600080fd5b60058054600160a060020a031916600160a060020a0392909216919091179055600a8190556100e3827f302e302e310000000000000000000000000000000000000000000000000000006401000000006100eb810204565b505050610138565b6004546101009004600160a060020a0316331461010757600080fd5b60008181559081526001602052604090208054600160a060020a031916600160a060020a0392909216919091179055565b6120a980620001486000396000f3006080604052600436106101325763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663095408a7811461013757806314c44e091461022b5780631dd14317146102525780632a858126146102765780632ae9c600146102a75780633f4ba83a146102bc5780635c975abb146102d15780636faa22a5146102fa578063715018a61461030f57806375f9f5971461032457806377282b701461033c5780638456cb59146103515780638905fd4f146103665780638da5cb5b146103875780638f9bbf161461039c578063a79094b7146104b4578063b95459e4146104cc578063c37792b5146104e1578063ce4dbdff146105ba578063d300a968146105cf578063f2fde38b146105f0578063f433262f14610611578063fb621f1414610626575b600080fd5b34801561014357600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261022994369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020888301358a018035601f8101839004830284018301909452838352979a8935600160a060020a039081169b8b8401359091169a91999098506060909101965091945090810192508190840183828082843750949750509335945061067f9350505050565b005b34801561023757600080fd5b50610240610c48565b60408051918252519081900360200190f35b34801561025e57600080fd5b50610229600160a060020a0360043516602435610c4e565b34801561028257600080fd5b5061028b610c9b565b60408051600160a060020a039092168252519081900360200190f35b3480156102b357600080fd5b50610240610caa565b3480156102c857600080fd5b50610229610cb0565b3480156102dd57600080fd5b506102e6610cd6565b604080519115158252519081900360200190f35b34801561030657600080fd5b5061028b610cdf565b34801561031b57600080fd5b50610229610cee565b34801561033057600080fd5b5061028b600435610d66565b34801561034857600080fd5b5061028b610d81565b34801561035d57600080fd5b50610229610d90565b34801561037257600080fd5b50610229600160a060020a0360043516610db4565b34801561039357600080fd5b5061028b610f2e565b3480156103a857600080fd5b506103bd600160a060020a0360043516610f42565b604051808060200184600160a060020a0316600160a060020a0316815260200180602001838103835286818151815260200191508051906020019080838360005b838110156104165781810151838201526020016103fe565b50505050905090810190601f1680156104435780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561047657818101518382015260200161045e565b50505050905090810190601f1680156104a35780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b3480156104c057600080fd5b50610229600435611119565b3480156104d857600080fd5b5061028b611186565b3480156104ed57600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261022994369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750505050913515159250611195915050565b3480156105c657600080fd5b5061028b6118d2565b3480156105db57600080fd5b506102e6600160a060020a03600435166118e1565b3480156105fc57600080fd5b50610229600160a060020a0360043516611994565b34801561061d57600080fd5b506102296119bc565b34801561063257600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261028b943694929360249392840191908190840183828082843750949750611cd69650505050505050565b6004546060906101009004600160a060020a0316331461069e57600080fd5b60045460ff16156106ae57600080fd5b600087511180156106c0575060008651115b151561073c576040805160e560020a62461bcd02815260206004820152603660248201527f4e616d6520616e642053796d626f6c20737472696e67206c656e67746820736860448201527f6f756c642062652067726561746572207468616e203000000000000000000000606482015290519081900360840190fd5b61074586611d55565b9050600160a060020a038416158015906107d457506000600160a060020a03166003826040518082805190602001908083835b602083106107975780518252601f199092019160209182019101610778565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054600160a060020a0316929092149150505b1515610876576040805160e560020a62461bcd02815260206004820152605160248201527f53796d626f6c20697320616c72656164792061742074686520706f6c796d617460448201527f68206e6574776f726b206f7220656e746572656420736563757269747920746f60648201527f6b656e2061646472657373206973203078000000000000000000000000000000608482015290519081900360a40190fd5b600160a060020a038516151561088b57600080fd5b6008546040517fce9af2b9000000000000000000000000000000000000000000000000000000008152600160a060020a03878116602483015260648201859052608060048301908152845160848401528451919093169263ce9af2b99285928a928d9289928291604481019160a490910190602089019080838360005b83811015610920578181015183820152602001610908565b50505050905090810190601f16801561094d5780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838360005b83811015610980578181015183820152602001610968565b50505050905090810190601f1680156109ad5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156109d057600080fd5b505af11580156109e4573d6000803e3d6000fd5b505050506040513d60208110156109fa57600080fd5b505115610a51576040805160e560020a62461bcd02815260206004820152601e60248201527f547279696e6720746f20757365206e6f6e2d76616c69642073796d626f6c0000604482015290519081900360640190fd5b836003826040518082805190602001908083835b60208310610a845780518252601f199092019160209182019101610a65565b51815160209384036101000a60001901801990921691161790529201948552506040805194859003820185208054600160a060020a031916600160a060020a039788161790558481018152868552848201899052948916600090815260028252949094208351805194959194610b009450859350910190611fe2565b506020828101518051610b199260018501920190611fe2565b509050507f64b91bbee335851d4f490bc9a6d0a60e9da265c67d0258e9f300b8a933ecb3408782864260405180806020018060200185600160a060020a0316600160a060020a03168152602001848152602001838103835287818151815260200191508051906020019080838360005b83811015610ba1578181015183820152602001610b89565b50505050905090810190601f168015610bce5780820380516001836020036101000a031916815260200191505b50838103825286518152865160209182019188019080838360005b83811015610c01578181015183820152602001610be9565b50505050905090810190601f168015610c2e5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a150505050505050565b600a5481565b6004546101009004600160a060020a03163314610c6a57600080fd5b60008181559081526001602052604090208054600160a060020a031916600160a060020a0392909216919091179055565b600854600160a060020a031681565b60005481565b6004546101009004600160a060020a03163314610ccc57600080fd5b610cd4611eb7565b565b60045460ff1681565b600954600160a060020a031681565b6004546101009004600160a060020a03163314610d0a57600080fd5b600454604051610100909104600160a060020a0316907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26004805474ffffffffffffffffffffffffffffffffffffffff0019169055565b600160205260009081526040902054600160a060020a031681565b600554600160a060020a031681565b6004546101009004600160a060020a03163314610dac57600080fd5b610cd4611f07565b60045460009081906101009004600160a060020a03163314610dd557600080fd5b600160a060020a0383161515610dea57600080fd5b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051849350600160a060020a038416916370a082319160248083019260209291908290030181600087803b158015610e4e57600080fd5b505af1158015610e62573d6000803e3d6000fd5b505050506040513d6020811015610e7857600080fd5b505160048054604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a03610100909304831693810193909352602483018490525192935084169163a9059cbb916044808201926020929091908290030181600087803b158015610ef257600080fd5b505af1158015610f06573d6000803e3d6000fd5b505050506040513d6020811015610f1c57600080fd5b50511515610f2957600080fd5b505050565b6004546101009004600160a060020a031681565b600160a060020a038116600081815260026020908152604080832081517f8da5cb5b0000000000000000000000000000000000000000000000000000000081529151606095869492939092638da5cb5b9260048084019382900301818987803b158015610fae57600080fd5b505af1158015610fc2573d6000803e3d6000fd5b505050506040513d6020811015610fd857600080fd5b5051600160a060020a03861660009081526002602081815260409283902085548451600180831615610100026000190190921694909404601f8101849004840285018401909552848452019285918301828280156110775780601f1061104c57610100808354040283529160200191611077565b820191906000526020600020905b81548152906001019060200180831161105a57829003601f168201915b5050845460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152959850869450925084019050828280156111055780601f106110da57610100808354040283529160200191611105565b820191906000526020600020905b8154815290600101906020018083116110e857829003601f168201915b505050505090509250925092509193909250565b6004546101009004600160a060020a0316331461113557600080fd5b600a5481141561114457600080fd5b600a54604080519182526020820183905280517fc999477ee25ca441ffa3217ee90d84865b6d945f40e1d625dc2e8982ed22d3a19281900390910190a1600a55565b600654600160a060020a031681565b60045460609060009060ff16156111ab57600080fd5b600086511180156111bd575060008551115b1515611239576040805160e560020a62461bcd02815260206004820152603660248201527f4e616d6520616e642053796d626f6c20737472696e67206c656e67746820736860448201527f6f756c642062652067726561746572207468616e203000000000000000000000606482015290519081900360840190fd5b6008546040517fac1e765b0000000000000000000000000000000000000000000000000000000081523360248201819052606060048301908152885160648401528851600160a060020a039094169363ac1e765b938a93928c9290918291604482019160840190602088019080838360005b838110156112c35781810151838201526020016112ab565b50505050905090810190601f1680156112f05780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561132357818101518382015260200161130b565b50505050905090810190601f1680156113505780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561137257600080fd5b505af1158015611386573d6000803e3d6000fd5b505050506040513d602081101561139c57600080fd5b505115156113f4576040805160e560020a62461bcd02815260206004820152601e60248201527f547279696e6720746f20757365206e6f6e2d76616c69642073796d626f6c0000604482015290519081900360640190fd5b6000600a54111561154357600954600a54604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481019290925251600160a060020a03909216916323b872dd916064808201926020929091908290030181600087803b15801561147557600080fd5b505af1158015611489573d6000803e3d6000fd5b505050506040513d602081101561149f57600080fd5b50511515611543576040805160e560020a62461bcd02815260206004820152604260248201527f4661696c6564207472616e7366657246726f6d2062656361757365206f66207360448201527f7566666963656e7420416c6c6f77616e6365206973206e6f742070726f76696460648201527f6564000000000000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b61154c85611d55565b6000805481526001602090815260408083205460055491517fc85fd4f800000000000000000000000000000000000000000000000000000000815260126044820181905233608483018190528a151560a4840152600160a060020a0394851660c4840181905260e0600485019081528f5160e48601528f51999b50959094169763c85fd4f8978f978c9794968f9694958f959194909384936024840193606481019361010490910192918e01918190849084905b83811015611618578181015183820152602001611600565b50505050905090810190601f1680156116455780820380516001836020036101000a031916815260200191505b5084810383528a5181528a516020918201918c019080838360005b83811015611678578181015183820152602001611660565b50505050905090810190601f1680156116a55780820380516001836020036101000a031916815260200191505b5084810382528851815288516020918201918a019080838360005b838110156116d85781810151838201526020016116c0565b50505050905090810190601f1680156117055780820380516001836020036101000a031916815260200191505b509a5050505050505050505050602060405180830381600087803b15801561172c57600080fd5b505af1158015611740573d6000803e3d6000fd5b505050506040513d602081101561175657600080fd5b50516040805180820182528481526020818101889052600160a060020a03841660009081526002825292909220815180519495509193909261179c928492910190611fe2565b5060208281015180516117b59260018501920190611fe2565b50905050806003836040518082805190602001908083835b602083106117ec5780518252601f1990920191602091820191016117cd565b51815160209384036101000a60001901801990921691161790529201948552506040805194859003820185208054600160a060020a031916600160a060020a03978816179055818552875185830152875133968816957f2510d802a0818e71139a7680a6388bcffcd3fa686e02a0f7319488c5bdb38fcb95508994509283928301919085019080838360005b83811015611890578181015183820152602001611878565b50505050905090810190601f1680156118bd5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3505050505050565b600754600160a060020a031681565b60408051600160a060020a038316600090815260026020819052928120805491937fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47093919282918491610100600182161502600019011604801561197c5780601f1061195a57610100808354040283529182019161197c565b820191906000526020600020905b815481529060010190602001808311611968575b50506040519081900390209290921415949350505050565b6004546101009004600160a060020a031633146119b057600080fd5b6119b981611f59565b50565b6004546101009004600160a060020a031633146119d857600080fd5b6005546040805160e060020a63bf40fac1028152602060048201819052600e60248301527f4d6f64756c65526567697374727900000000000000000000000000000000000060448301529151600160a060020a039093169263bf40fac1926064808401939192918290030181600087803b158015611a5557600080fd5b505af1158015611a69573d6000803e3d6000fd5b505050506040513d6020811015611a7f57600080fd5b505160068054600160a060020a031916600160a060020a039283161790556005546040805160e060020a63bf40fac1028152602060048201819052601560248301527f5365637572697479546f6b656e5265676973747279000000000000000000000060448301529151929093169263bf40fac192606480830193928290030181600087803b158015611b1157600080fd5b505af1158015611b25573d6000803e3d6000fd5b505050506040513d6020811015611b3b57600080fd5b505160078054600160a060020a031916600160a060020a039283161790556005546040805160e060020a63bf40fac1028152602060048201819052600e60248301527f5469636b6572526567697374727900000000000000000000000000000000000060448301529151929093169263bf40fac192606480830193928290030181600087803b158015611bcd57600080fd5b505af1158015611be1573d6000803e3d6000fd5b505050506040513d6020811015611bf757600080fd5b505160088054600160a060020a031916600160a060020a039283161790556005546040805160e060020a63bf40fac1028152602060048201819052600960248301527f506f6c79546f6b656e000000000000000000000000000000000000000000000060448301529151929093169263bf40fac192606480830193928290030181600087803b158015611c8957600080fd5b505af1158015611c9d573d6000803e3d6000fd5b505050506040513d6020811015611cb357600080fd5b505160098054600160a060020a031916600160a060020a03909216919091179055565b60006060611ce383611d55565b90506003816040518082805190602001908083835b60208310611d175780518252601f199092019160209182019101611cf8565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054600160a060020a031695945050505050565b6060816000805b8251821015611eae578282815181101515611d7357fe5b01602001517f0100000000000000000000000000000000000000000000000000000000000000908190040290507f61000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610801590611e3457507f7a000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821611155b15611e6457601f197f01000000000000000000000000000000000000000000000000000000000000009182900401025b808383815181101515611e7357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190910190611d5c565b50909392505050565b60045460ff161515611ec857600080fd5b6004805460ff191690556040805142815290517faaa520fdd7d2c83061d632fa017b0432407e798818af63ea908589fceda39ab79181900360200190a1565b60045460ff1615611f1757600080fd5b6004805460ff191660011790556040805142815290517f68b095021b1f40fe513109f513c66692f0b3219aee674a69f4efc57badb8201d9181900360200190a1565b600160a060020a0381161515611f6e57600080fd5b600454604051600160a060020a0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a360048054600160a060020a039092166101000274ffffffffffffffffffffffffffffffffffffffff0019909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061202357805160ff1916838001178555612050565b82800160010185558215612050579182015b82811115612050578251825591602001919060010190612035565b5061205c929150612060565b5090565b61207a91905b8082111561205c5760008155600101612066565b905600a165627a7a723058200278e95063a7233ec27e76af96080041bc15e494984168248546e0e9e0083434002900000000000000000000000006595656b93ce14834f0d22b7bbda4382d5ab510000000000000000000000000b19e341f45412d0e2661aea25cadc75b7d03039d00000000000000000000000000000000000000000000000d8d726b7177a80000

Deployed Bytecode

0x6080604052600436106101325763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663095408a7811461013757806314c44e091461022b5780631dd14317146102525780632a858126146102765780632ae9c600146102a75780633f4ba83a146102bc5780635c975abb146102d15780636faa22a5146102fa578063715018a61461030f57806375f9f5971461032457806377282b701461033c5780638456cb59146103515780638905fd4f146103665780638da5cb5b146103875780638f9bbf161461039c578063a79094b7146104b4578063b95459e4146104cc578063c37792b5146104e1578063ce4dbdff146105ba578063d300a968146105cf578063f2fde38b146105f0578063f433262f14610611578063fb621f1414610626575b600080fd5b34801561014357600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261022994369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020888301358a018035601f8101839004830284018301909452838352979a8935600160a060020a039081169b8b8401359091169a91999098506060909101965091945090810192508190840183828082843750949750509335945061067f9350505050565b005b34801561023757600080fd5b50610240610c48565b60408051918252519081900360200190f35b34801561025e57600080fd5b50610229600160a060020a0360043516602435610c4e565b34801561028257600080fd5b5061028b610c9b565b60408051600160a060020a039092168252519081900360200190f35b3480156102b357600080fd5b50610240610caa565b3480156102c857600080fd5b50610229610cb0565b3480156102dd57600080fd5b506102e6610cd6565b604080519115158252519081900360200190f35b34801561030657600080fd5b5061028b610cdf565b34801561031b57600080fd5b50610229610cee565b34801561033057600080fd5b5061028b600435610d66565b34801561034857600080fd5b5061028b610d81565b34801561035d57600080fd5b50610229610d90565b34801561037257600080fd5b50610229600160a060020a0360043516610db4565b34801561039357600080fd5b5061028b610f2e565b3480156103a857600080fd5b506103bd600160a060020a0360043516610f42565b604051808060200184600160a060020a0316600160a060020a0316815260200180602001838103835286818151815260200191508051906020019080838360005b838110156104165781810151838201526020016103fe565b50505050905090810190601f1680156104435780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561047657818101518382015260200161045e565b50505050905090810190601f1680156104a35780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b3480156104c057600080fd5b50610229600435611119565b3480156104d857600080fd5b5061028b611186565b3480156104ed57600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261022994369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750505050913515159250611195915050565b3480156105c657600080fd5b5061028b6118d2565b3480156105db57600080fd5b506102e6600160a060020a03600435166118e1565b3480156105fc57600080fd5b50610229600160a060020a0360043516611994565b34801561061d57600080fd5b506102296119bc565b34801561063257600080fd5b506040805160206004803580820135601f810184900484028501840190955284845261028b943694929360249392840191908190840183828082843750949750611cd69650505050505050565b6004546060906101009004600160a060020a0316331461069e57600080fd5b60045460ff16156106ae57600080fd5b600087511180156106c0575060008651115b151561073c576040805160e560020a62461bcd02815260206004820152603660248201527f4e616d6520616e642053796d626f6c20737472696e67206c656e67746820736860448201527f6f756c642062652067726561746572207468616e203000000000000000000000606482015290519081900360840190fd5b61074586611d55565b9050600160a060020a038416158015906107d457506000600160a060020a03166003826040518082805190602001908083835b602083106107975780518252601f199092019160209182019101610778565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054600160a060020a0316929092149150505b1515610876576040805160e560020a62461bcd02815260206004820152605160248201527f53796d626f6c20697320616c72656164792061742074686520706f6c796d617460448201527f68206e6574776f726b206f7220656e746572656420736563757269747920746f60648201527f6b656e2061646472657373206973203078000000000000000000000000000000608482015290519081900360a40190fd5b600160a060020a038516151561088b57600080fd5b6008546040517fce9af2b9000000000000000000000000000000000000000000000000000000008152600160a060020a03878116602483015260648201859052608060048301908152845160848401528451919093169263ce9af2b99285928a928d9289928291604481019160a490910190602089019080838360005b83811015610920578181015183820152602001610908565b50505050905090810190601f16801561094d5780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838360005b83811015610980578181015183820152602001610968565b50505050905090810190601f1680156109ad5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156109d057600080fd5b505af11580156109e4573d6000803e3d6000fd5b505050506040513d60208110156109fa57600080fd5b505115610a51576040805160e560020a62461bcd02815260206004820152601e60248201527f547279696e6720746f20757365206e6f6e2d76616c69642073796d626f6c0000604482015290519081900360640190fd5b836003826040518082805190602001908083835b60208310610a845780518252601f199092019160209182019101610a65565b51815160209384036101000a60001901801990921691161790529201948552506040805194859003820185208054600160a060020a031916600160a060020a039788161790558481018152868552848201899052948916600090815260028252949094208351805194959194610b009450859350910190611fe2565b506020828101518051610b199260018501920190611fe2565b509050507f64b91bbee335851d4f490bc9a6d0a60e9da265c67d0258e9f300b8a933ecb3408782864260405180806020018060200185600160a060020a0316600160a060020a03168152602001848152602001838103835287818151815260200191508051906020019080838360005b83811015610ba1578181015183820152602001610b89565b50505050905090810190601f168015610bce5780820380516001836020036101000a031916815260200191505b50838103825286518152865160209182019188019080838360005b83811015610c01578181015183820152602001610be9565b50505050905090810190601f168015610c2e5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a150505050505050565b600a5481565b6004546101009004600160a060020a03163314610c6a57600080fd5b60008181559081526001602052604090208054600160a060020a031916600160a060020a0392909216919091179055565b600854600160a060020a031681565b60005481565b6004546101009004600160a060020a03163314610ccc57600080fd5b610cd4611eb7565b565b60045460ff1681565b600954600160a060020a031681565b6004546101009004600160a060020a03163314610d0a57600080fd5b600454604051610100909104600160a060020a0316907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26004805474ffffffffffffffffffffffffffffffffffffffff0019169055565b600160205260009081526040902054600160a060020a031681565b600554600160a060020a031681565b6004546101009004600160a060020a03163314610dac57600080fd5b610cd4611f07565b60045460009081906101009004600160a060020a03163314610dd557600080fd5b600160a060020a0383161515610dea57600080fd5b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051849350600160a060020a038416916370a082319160248083019260209291908290030181600087803b158015610e4e57600080fd5b505af1158015610e62573d6000803e3d6000fd5b505050506040513d6020811015610e7857600080fd5b505160048054604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a03610100909304831693810193909352602483018490525192935084169163a9059cbb916044808201926020929091908290030181600087803b158015610ef257600080fd5b505af1158015610f06573d6000803e3d6000fd5b505050506040513d6020811015610f1c57600080fd5b50511515610f2957600080fd5b505050565b6004546101009004600160a060020a031681565b600160a060020a038116600081815260026020908152604080832081517f8da5cb5b0000000000000000000000000000000000000000000000000000000081529151606095869492939092638da5cb5b9260048084019382900301818987803b158015610fae57600080fd5b505af1158015610fc2573d6000803e3d6000fd5b505050506040513d6020811015610fd857600080fd5b5051600160a060020a03861660009081526002602081815260409283902085548451600180831615610100026000190190921694909404601f8101849004840285018401909552848452019285918301828280156110775780601f1061104c57610100808354040283529160200191611077565b820191906000526020600020905b81548152906001019060200180831161105a57829003601f168201915b5050845460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152959850869450925084019050828280156111055780601f106110da57610100808354040283529160200191611105565b820191906000526020600020905b8154815290600101906020018083116110e857829003601f168201915b505050505090509250925092509193909250565b6004546101009004600160a060020a0316331461113557600080fd5b600a5481141561114457600080fd5b600a54604080519182526020820183905280517fc999477ee25ca441ffa3217ee90d84865b6d945f40e1d625dc2e8982ed22d3a19281900390910190a1600a55565b600654600160a060020a031681565b60045460609060009060ff16156111ab57600080fd5b600086511180156111bd575060008551115b1515611239576040805160e560020a62461bcd02815260206004820152603660248201527f4e616d6520616e642053796d626f6c20737472696e67206c656e67746820736860448201527f6f756c642062652067726561746572207468616e203000000000000000000000606482015290519081900360840190fd5b6008546040517fac1e765b0000000000000000000000000000000000000000000000000000000081523360248201819052606060048301908152885160648401528851600160a060020a039094169363ac1e765b938a93928c9290918291604482019160840190602088019080838360005b838110156112c35781810151838201526020016112ab565b50505050905090810190601f1680156112f05780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561132357818101518382015260200161130b565b50505050905090810190601f1680156113505780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b15801561137257600080fd5b505af1158015611386573d6000803e3d6000fd5b505050506040513d602081101561139c57600080fd5b505115156113f4576040805160e560020a62461bcd02815260206004820152601e60248201527f547279696e6720746f20757365206e6f6e2d76616c69642073796d626f6c0000604482015290519081900360640190fd5b6000600a54111561154357600954600a54604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481019290925251600160a060020a03909216916323b872dd916064808201926020929091908290030181600087803b15801561147557600080fd5b505af1158015611489573d6000803e3d6000fd5b505050506040513d602081101561149f57600080fd5b50511515611543576040805160e560020a62461bcd02815260206004820152604260248201527f4661696c6564207472616e7366657246726f6d2062656361757365206f66207360448201527f7566666963656e7420416c6c6f77616e6365206973206e6f742070726f76696460648201527f6564000000000000000000000000000000000000000000000000000000000000608482015290519081900360a40190fd5b61154c85611d55565b6000805481526001602090815260408083205460055491517fc85fd4f800000000000000000000000000000000000000000000000000000000815260126044820181905233608483018190528a151560a4840152600160a060020a0394851660c4840181905260e0600485019081528f5160e48601528f51999b50959094169763c85fd4f8978f978c9794968f9694958f959194909384936024840193606481019361010490910192918e01918190849084905b83811015611618578181015183820152602001611600565b50505050905090810190601f1680156116455780820380516001836020036101000a031916815260200191505b5084810383528a5181528a516020918201918c019080838360005b83811015611678578181015183820152602001611660565b50505050905090810190601f1680156116a55780820380516001836020036101000a031916815260200191505b5084810382528851815288516020918201918a019080838360005b838110156116d85781810151838201526020016116c0565b50505050905090810190601f1680156117055780820380516001836020036101000a031916815260200191505b509a5050505050505050505050602060405180830381600087803b15801561172c57600080fd5b505af1158015611740573d6000803e3d6000fd5b505050506040513d602081101561175657600080fd5b50516040805180820182528481526020818101889052600160a060020a03841660009081526002825292909220815180519495509193909261179c928492910190611fe2565b5060208281015180516117b59260018501920190611fe2565b50905050806003836040518082805190602001908083835b602083106117ec5780518252601f1990920191602091820191016117cd565b51815160209384036101000a60001901801990921691161790529201948552506040805194859003820185208054600160a060020a031916600160a060020a03978816179055818552875185830152875133968816957f2510d802a0818e71139a7680a6388bcffcd3fa686e02a0f7319488c5bdb38fcb95508994509283928301919085019080838360005b83811015611890578181015183820152602001611878565b50505050905090810190601f1680156118bd5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3505050505050565b600754600160a060020a031681565b60408051600160a060020a038316600090815260026020819052928120805491937fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47093919282918491610100600182161502600019011604801561197c5780601f1061195a57610100808354040283529182019161197c565b820191906000526020600020905b815481529060010190602001808311611968575b50506040519081900390209290921415949350505050565b6004546101009004600160a060020a031633146119b057600080fd5b6119b981611f59565b50565b6004546101009004600160a060020a031633146119d857600080fd5b6005546040805160e060020a63bf40fac1028152602060048201819052600e60248301527f4d6f64756c65526567697374727900000000000000000000000000000000000060448301529151600160a060020a039093169263bf40fac1926064808401939192918290030181600087803b158015611a5557600080fd5b505af1158015611a69573d6000803e3d6000fd5b505050506040513d6020811015611a7f57600080fd5b505160068054600160a060020a031916600160a060020a039283161790556005546040805160e060020a63bf40fac1028152602060048201819052601560248301527f5365637572697479546f6b656e5265676973747279000000000000000000000060448301529151929093169263bf40fac192606480830193928290030181600087803b158015611b1157600080fd5b505af1158015611b25573d6000803e3d6000fd5b505050506040513d6020811015611b3b57600080fd5b505160078054600160a060020a031916600160a060020a039283161790556005546040805160e060020a63bf40fac1028152602060048201819052600e60248301527f5469636b6572526567697374727900000000000000000000000000000000000060448301529151929093169263bf40fac192606480830193928290030181600087803b158015611bcd57600080fd5b505af1158015611be1573d6000803e3d6000fd5b505050506040513d6020811015611bf757600080fd5b505160088054600160a060020a031916600160a060020a039283161790556005546040805160e060020a63bf40fac1028152602060048201819052600960248301527f506f6c79546f6b656e000000000000000000000000000000000000000000000060448301529151929093169263bf40fac192606480830193928290030181600087803b158015611c8957600080fd5b505af1158015611c9d573d6000803e3d6000fd5b505050506040513d6020811015611cb357600080fd5b505160098054600160a060020a031916600160a060020a03909216919091179055565b60006060611ce383611d55565b90506003816040518082805190602001908083835b60208310611d175780518252601f199092019160209182019101611cf8565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054600160a060020a031695945050505050565b6060816000805b8251821015611eae578282815181101515611d7357fe5b01602001517f0100000000000000000000000000000000000000000000000000000000000000908190040290507f61000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821610801590611e3457507f7a000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000821611155b15611e6457601f197f01000000000000000000000000000000000000000000000000000000000000009182900401025b808383815181101515611e7357fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600190910190611d5c565b50909392505050565b60045460ff161515611ec857600080fd5b6004805460ff191690556040805142815290517faaa520fdd7d2c83061d632fa017b0432407e798818af63ea908589fceda39ab79181900360200190a1565b60045460ff1615611f1757600080fd5b6004805460ff191660011790556040805142815290517f68b095021b1f40fe513109f513c66692f0b3219aee674a69f4efc57badb8201d9181900360200190a1565b600160a060020a0381161515611f6e57600080fd5b600454604051600160a060020a0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a360048054600160a060020a039092166101000274ffffffffffffffffffffffffffffffffffffffff0019909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061202357805160ff1916838001178555612050565b82800160010185558215612050579182015b82811115612050578251825591602001919060010190612035565b5061205c929150612060565b5090565b61207a91905b8082111561205c5760008155600101612066565b905600a165627a7a723058200278e95063a7233ec27e76af96080041bc15e494984168248546e0e9e00834340029

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000006595656b93ce14834f0d22b7bbda4382d5ab510000000000000000000000000b19e341f45412d0e2661aea25cadc75b7d03039d00000000000000000000000000000000000000000000000d8d726b7177a80000

-----Decoded View---------------
Arg [0] : _polymathRegistry (address): 0x06595656b93ce14834f0d22b7bbDA4382d5ab510
Arg [1] : _stVersionProxy (address): 0xB19e341F45412D0e2661aEA25CADc75b7d03039D
Arg [2] : _registrationFee (uint256): 250000000000000000000

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000006595656b93ce14834f0d22b7bbda4382d5ab510
Arg [1] : 000000000000000000000000b19e341f45412d0e2661aea25cadc75b7d03039d
Arg [2] : 00000000000000000000000000000000000000000000000d8d726b7177a80000


Swarm Source

bzzr://0278e95063a7233ec27e76af96080041bc15e494984168248546e0e9e0083434

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.