Contract 0x9A8B83bc3315feE8f3A1482642A3c52143aF0fA2

 

TxHash Block Age From To Value [TxFee]
0xa2b99ff3940b06cf1ea4ebec8b8507ecccea8410475f16b936dee915eaf5308673718374 days 16 mins ago0xc6860754ac59c9ec82b2db3147862d59685f164f IN  0x9a8b83bc3315fee8f3a1482642a3c52143af0fa20 Ether0.000045759
0xa36200eb43665b607d1bf0a07404a4d27e8c5c33bc8c6639a6568a6a54e66853733091610 days 9 hrs ago0xc6860754ac59c9ec82b2db3147862d59685f164f IN  0x9a8b83bc3315fee8f3a1482642a3c52143af0fa20 Ether0.000057344
0xbba1dd8bde2f001aabb6d0fec4032a4401ff2051f33cb0c8d9b5df55314d16ce732307111 days 14 hrs ago0xc6860754ac59c9ec82b2db3147862d59685f164f IN  0x9a8b83bc3315fee8f3a1482642a3c52143af0fa20 Ether0.004929274
0xb368505b57db5443abb23872a0b13817887a9e41078a9daa1aa46308b203bec2731768512 days 10 hrs ago0xc6860754ac59c9ec82b2db3147862d59685f164f IN  0x9a8b83bc3315fee8f3a1482642a3c52143af0fa20 Ether0.000557958
[ Download CSV Export 

Latest 1 internal transaction Internal Transactions as a result of Contract Execution

Parent TxHash Block Age From To Value
0xaf67e608ae735c20eb783d6fabc4bef11f37b7c7b29f3e589e9a8b45805e79e2731020713 days 14 hrs ago0x47da34f192d3fd946fd6ce7494e9eedf171a1208  Contract Creation0 Ether
[ Download CSV Export 
Warning: The compiled contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity) Solidity Compiler Bugs.

Contract Source Code Verified (Similar Match)
Note: This contract matches the deployed ByteCode of the Verified Source Code for Contract 0x1a8c11df0de8507ab1841eadc9d188b582ce9e6c
Contract Name: SecurityToken
Compiler Version: v0.4.24+commit.e67f0147
Optimization Enabled: Yes
Runs (Optimizer):  200


Contract Source Code
pragma solidity ^0.4.24;

/**
 * @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 ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
interface IERC20 {
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint256);
    function balanceOf(address _owner) external view returns (uint256);
    function allowance(address _owner, address _spender) external view returns (uint256);
    function transfer(address _to, uint256 _value) external returns (bool);
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool);
    function approve(address _spender, uint256 _value) external returns (bool);
    function decreaseApproval(address _spender, uint _subtractedValue) external returns (bool);
    function increaseApproval(address _spender, uint _addedValue) external returns (bool);
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

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

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

    /**
     * @notice Return the permission flags that are associated with a module
     */
    function getPermissions() external view returns(bytes32[]);

    /**
     * @notice Used to withdraw the fee by the factory owner
     */
    function takeFee(uint256 _amount) external returns(bool);

}

/**
 * @title Interface that every module factory contract should implement
 */
interface IModuleFactory {

    event ChangeFactorySetupFee(uint256 _oldSetupCost, uint256 _newSetupCost, address _moduleFactory);
    event ChangeFactoryUsageFee(uint256 _oldUsageCost, uint256 _newUsageCost, address _moduleFactory);
    event ChangeFactorySubscriptionFee(uint256 _oldSubscriptionCost, uint256 _newMonthlySubscriptionCost, address _moduleFactory);
    event GenerateModuleFromFactory(
        address _module,
        bytes32 indexed _moduleName,
        address indexed _moduleFactory,
        address _creator,
        uint256 _setupCost,
        uint256 _timestamp
    );
    event ChangeSTVersionBound(string _boundType, uint8 _major, uint8 _minor, uint8 _patch);

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

    /**
     * @notice Type of the Module factory
     */
    function getTypes() external view returns(uint8[]);

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

    /**
     * @notice Returns the instructions associated with the module
     */
    function getInstructions() external view returns (string);

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

    /**
     * @notice Used to change the setup fee
     * @param _newSetupCost New setup fee
     */
    function changeFactorySetupFee(uint256 _newSetupCost) external;

    /**
     * @notice Used to change the usage fee
     * @param _newUsageCost New usage fee
     */
    function changeFactoryUsageFee(uint256 _newUsageCost) external;

    /**
     * @notice Used to change the subscription fee
     * @param _newSubscriptionCost New subscription fee
     */
    function changeFactorySubscriptionFee(uint256 _newSubscriptionCost) external;

    /**
     * @notice Function use to change the lower and upper bound of the compatible version st
     * @param _boundType Type of bound
     * @param _newVersion New version array
     */
    function changeSTVersionBounds(string _boundType, uint8[] _newVersion) external;

   /**
     * @notice Get the setup cost of the module
     */
    function getSetupCost() external view returns (uint256);

    /**
     * @notice Used to get the lower bound
     * @return Lower bound
     */
    function getLowerSTVersionBounds() external view returns(uint8[]);

     /**
     * @notice Used to get the upper bound
     * @return Upper bound
     */
    function getUpperSTVersionBounds() external view returns(uint8[]);

}

/**
 * @title Interface for the Polymath Module Registry contract
 */
interface 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 the 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;

    /**
     * @notice Called by the ModuleFactory owner or registry curator to delete a ModuleFactory
     * @param _moduleFactory is the address of the module factory to be deleted
     */
    function removeModule(address _moduleFactory) external;

    /**
    * @notice Called by Polymath to verify modules for SecurityToken to use.
    * @notice A module can not be used by an ST unless first approved/verified by Polymath
    * @notice (The only exception to this is that the author of the module is the owner of the ST - Only if enabled by the FeatureRegistry)
    * @param _moduleFactory is the address of the module factory to be registered
    */
    function verifyModule(address _moduleFactory, bool _verified) external;

    /**
     * @notice Used to get the reputation of a Module Factory
     * @param _factoryAddress address of the Module Factory
     * @return address array which has the list of securityToken's uses that module factory
     */
    function getReputationByFactory(address _factoryAddress) external view returns(address[]);

    /**
     * @notice Returns all the tags related to the a module type which are valid for the given token
     * @param _moduleType is the module type
     * @param _securityToken is the token
     * @return list of tags
     * @return corresponding list of module factories
     */
    function getTagsByTypeAndToken(uint8 _moduleType, address _securityToken) external view returns(bytes32[], address[]);

    /**
     * @notice Returns all the tags related to the a module type which are valid for the given token
     * @param _moduleType is the module type
     * @return list of tags
     * @return corresponding list of module factories
     */
    function getTagsByType(uint8 _moduleType) external view returns(bytes32[], address[]);

    /**
     * @notice Returns the list of addresses of Module Factory of a particular type
     * @param _moduleType Type of Module
     * @return address array that contains the list of addresses of module factory contracts.
     */
    function getModulesByType(uint8 _moduleType) external view returns(address[]);

    /**
     * @notice Returns the list of available Module factory addresses of a particular type for a given token.
     * @param _moduleType is the module type to look for
     * @param _securityToken is the address of SecurityToken
     * @return address array that contains the list of available addresses of module factory contracts.
     */
    function getModulesByTypeAndToken(uint8 _moduleType, address _securityToken) external view returns (address[]);

    /**
     * @notice Use to get the latest contract address of the regstries
     */
    function updateFromRegistry() external;

    /**
     * @notice Get the owner of the contract
     * @return address owner
     */
    function owner() external view returns(address);

    /**
     * @notice Check whether the contract operations is paused or not
     * @return bool 
     */
    function isPaused() external view returns(bool);

}

/**
 * @title Interface for managing polymath feature switches
 */
interface IFeatureRegistry {

    /**
     * @notice Get the status of a feature
     * @param _nameKey is the key for the feature status mapping
     * @return bool
     */
    function getFeatureStatus(string _nameKey) external view returns(bool);

}

/**
 * @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, "Contract is paused");
        _;
    }

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

   /**
    * @notice Called by the owner to pause, triggers stopped state
    */
    function _pause() internal whenNotPaused {
        paused = true;
        /*solium-disable-next-line security/no-block-members*/
        emit Pause(now);
    }

    /**
    * @notice Called by the owner to unpause, returns to normal state
    */
    function _unpause() internal whenPaused {
        paused = false;
        /*solium-disable-next-line security/no-block-members*/
        emit Unpause(now);
    }

}

/**
 * @title Interface for all security tokens
 */
interface ISecurityToken {

    // Standard ERC20 interface
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint256);
    function balanceOf(address _owner) external view returns (uint256);
    function allowance(address _owner, address _spender) external view returns (uint256);
    function transfer(address _to, uint256 _value) external returns (bool);
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool);
    function approve(address _spender, uint256 _value) external returns (bool);
    function decreaseApproval(address _spender, uint _subtractedValue) external returns (bool);
    function increaseApproval(address _spender, uint _addedValue) external returns (bool);
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    //transfer, transferFrom must respect the result of verifyTransfer
    function verifyTransfer(address _from, address _to, uint256 _value) external 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)
     * @param _investor Address the tokens will be minted to
     * @param _value is the amount of tokens that will be minted to the investor
     */
    function mint(address _investor, uint256 _value) external 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)
     * @param _investor Address the tokens will be minted to
     * @param _value is The amount of tokens that will be minted to the investor
     * @param _data Data to indicate validation
     */
    function mintWithData(address _investor, uint256 _value, bytes _data) external returns (bool success);

    /**
     * @notice Used to burn the securityToken on behalf of someone else
     * @param _from Address for whom to burn tokens
     * @param _value No. of tokens to be burned
     * @param _data Data to indicate validation
     */
    function burnFromWithData(address _from, uint256 _value, bytes _data) external;

    /**
     * @notice Used to burn the securityToken
     * @param _value No. of tokens to be burned
     * @param _data Data to indicate validation
     */
    function burnWithData(uint256 _value, bytes _data) external;

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

    // 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) external view returns (bool);

    /**
     * @notice Returns module list for a module type
     * @param _module Address of the module
     * @return bytes32 Name
     * @return address Module address
     * @return address Module factory address
     * @return bool Module archived
     * @return uint8 Module type
     * @return uint256 Module index
     * @return uint256 Name index

     */
    function getModule(address _module) external view returns(bytes32, address, address, bool, uint8, uint256, uint256);

    /**
     * @notice Returns module list for a module name
     * @param _name Name of the module
     * @return address[] List of modules with this name
     */
    function getModulesByName(bytes32 _name) external view returns (address[]);

    /**
     * @notice Returns module list for a module type
     * @param _type Type of the module
     * @return address[] List of modules with this type
     */
    function getModulesByType(uint8 _type) external view returns (address[]);

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

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

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

    /**
     * @notice Gets length of investors array
     * NB - this length may differ from investorCount if the list has not been pruned of zero-balance investors
     * @return Length
     */
    function getInvestors() external view returns (address[]);

    /**
     * @notice returns an array of investors at a given checkpoint
     * NB - this length may differ from investorCount as it contains all investors that ever held tokens
     * @param _checkpointId Checkpoint id at which investor list is to be populated
     * @return list of investors
     */
    function getInvestorsAt(uint256 _checkpointId) external view returns(address[]);

    /**
     * @notice generates subset of investors
     * NB - can be used in batches if investor list is large
     * @param _start Position of investor to start iteration from
     * @param _end Position of investor to stop iteration at
     * @return list of investors
     */
    function iterateInvestors(uint256 _start, uint256 _end) external view returns(address[]);
    
    /**
     * @notice Gets current checkpoint ID
     * @return Id
     */
    function currentCheckpointId() external view returns (uint256);

    /**
    * @notice Gets an investor at a particular index
    * @param _index Index to return address from
    * @return Investor address
    */
    function investors(uint256 _index) external view returns (address);

   /**
    * @notice Allows the owner to withdraw unspent POLY stored by them on the ST or any ERC20 token.
    * @dev Owner can transfer POLY to the ST which will be used to pay for modules that require a POLY fee.
    * @param _tokenContract Address of the ERC20Basic compliance token
    * @param _value Amount of POLY to withdraw
    */
    function withdrawERC20(address _tokenContract, uint256 _value) external;

    /**
    * @notice Allows owner to approve more POLY to one of the modules
    * @param _module Module address
    * @param _budget New budget
    */
    function changeModuleBudget(address _module, uint256 _budget) external;

    /**
     * @notice Changes the tokenDetails
     * @param _newTokenDetails New token details
     */
    function updateTokenDetails(string _newTokenDetails) external;

    /**
    * @notice Allows the owner to change token granularity
    * @param _granularity Granularity level of the token
    */
    function changeGranularity(uint256 _granularity) external;

    /**
    * @notice Removes addresses with zero balances from the investors list
    * @param _start Index in investors 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) external;

    /**
     * @notice Freezes all the transfers
     */
    function freezeTransfers() external;

    /**
     * @notice Un-freezes all the transfers
     */
    function unfreezeTransfers() external;

    /**
     * @notice Ends token minting period permanently
     */
    function freezeMinting() external;

    /**
     * @notice Mints new tokens and assigns them to the target investors.
     * Can only be called by the STO attached to the token or by the Issuer (Security Token contract owner)
     * @param _investors A list of addresses to whom the minted tokens will be delivered
     * @param _values A list of the amount of tokens to mint to corresponding addresses from _investor[] list
     * @return Success
     */
    function mintMulti(address[] _investors, uint256[] _values) external returns (bool success);

    /**
     * @notice Function used to attach a module to the security token
     * @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
    ) external;

    /**
    * @notice Archives a module attached to the SecurityToken
    * @param _module address of module to archive
    */
    function archiveModule(address _module) external;

    /**
    * @notice Unarchives a module attached to the SecurityToken
    * @param _module address of module to unarchive
    */
    function unarchiveModule(address _module) external;

    /**
    * @notice Removes a module attached to the SecurityToken
    * @param _module address of module to archive
    */
    function removeModule(address _module) external;

    /**
     * @notice Used by the issuer to set the controller addresses
     * @param _controller address of the controller
     */
    function setController(address _controller) external;

    /**
     * @notice Used by a controller to execute a forced transfer
     * @param _from address from which to take tokens
     * @param _to address where to send tokens
     * @param _value amount of tokens to transfer
     * @param _data data to indicate validation
     * @param _log data attached to the transfer by controller to emit in event
     */
    function forceTransfer(address _from, address _to, uint256 _value, bytes _data, bytes _log) external;

    /**
     * @notice Used by a controller to execute a foced burn
     * @param _from address from which to take tokens
     * @param _value amount of tokens to transfer
     * @param _data data to indicate validation
     * @param _log data attached to the transfer by controller to emit in event
     */
    function forceBurn(address _from, uint256 _value, bytes _data, bytes _log) external;

    /**
     * @notice Used by the issuer to permanently disable controller functionality
     * @dev enabled via feature switch "disableControllerAllowed"
     */
     function disableController() external;

     /**
     * @notice Used to get the version of the securityToken
     */
     function getVersion() external view returns(uint8[]);

     /**
     * @notice Gets the investor count
     */
     function getInvestorCount() external view returns(uint256);

     /**
      * @notice Overloaded version of the transfer function
      * @param _to receiver of transfer
      * @param _value value of transfer
      * @param _data data to indicate validation
      * @return bool success
      */
     function transferWithData(address _to, uint256 _value, bytes _data) external returns (bool success);

     /**
      * @notice Overloaded version of the transferFrom function
      * @param _from sender of transfer
      * @param _to receiver of transfer
      * @param _value value of transfer
      * @param _data data to indicate validation
      * @return bool success
      */
     function transferFromWithData(address _from, address _to, uint256 _value, bytes _data) external returns(bool);

     /**
      * @notice Provides the granularity of the token
      * @return uint256
      */
     function granularity() external view returns(uint256);
}

/**
 * @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 that any module contract should implement
 * @notice Contract is abstract
 */
contract Module is IModule {

    address public factory;

    address public securityToken;

    bytes32 public constant FEE_ADMIN = "FEE_ADMIN";

    IERC20 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 = IERC20(_polyAddress);
    }

    //Allows owner, factory or permissioned delegate
    modifier withPerm(bytes32 _perm) {
        bool isOwner = msg.sender == Ownable(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 == Ownable(securityToken).owner(), "Sender is not owner");
        _;
    }

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

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

    modifier onlyFactoryOrOwner {
        require((msg.sender == Ownable(securityToken).owner()) || (msg.sender == factory), "Sender is not factory or owner");
        _;
    }

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

/**
 * @title Interface to be implemented by all Transfer Manager modules
 * @dev abstract contract
 */
contract ITransferManager is Module, 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, bytes _data, bool _isTransfer) public returns(Result);

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

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

/**
 * @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), "Invalid address");
        IERC20 token = IERC20(_tokenContract);
        uint256 balance = token.balanceOf(address(this));
        require(token.transfer(owner, balance), "Transfer failed");
    }
}

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

    mapping (bytes32 => address) public storedAddresses;

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

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

    /**
     * @notice Changes 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) external onlyOwner {
        bytes32 key = keccak256(bytes(_nameKey));
        emit ChangeAddress(_nameKey, storedAddresses[key], _newAddress);
        storedAddresses[key] = _newAddress;
    }


}

contract RegistryUpdater is Ownable {

    address public polymathRegistry;
    address public moduleRegistry;
    address public securityTokenRegistry;
    address public featureRegistry;
    address public polyToken;

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

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

}

/**
 * @title Utility contract for reusable code
 */
library 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);
    }

    /**
     * @notice Changes the string into bytes32
     * @param _source String that need to convert into bytes32
     */
    /// Notice - Maximum Length for _source will be 32 chars otherwise returned bytes32 value will have lossy value.
    function stringToBytes32(string memory _source) internal pure returns (bytes32) {
        return bytesToBytes32(bytes(_source), 0);
    }

    /**
     * @notice Changes bytes into bytes32
     * @param _b Bytes that need to convert into bytes32
     * @param _offset Offset from which to begin conversion
     */
    /// Notice - Maximum length for _source will be 32 chars otherwise returned bytes32 value will have lossy value.
    function bytesToBytes32(bytes _b, uint _offset) internal pure returns (bytes32) {
        bytes32 result;

        for (uint i = 0; i < _b.length; i++) {
            result |= bytes32(_b[_offset + i] & 0xFF) >> (i * 8);
        }
        return result;
    }

    /**
     * @notice Changes the bytes32 into string
     * @param _source that need to convert into string
     */
    function bytes32ToString(bytes32 _source) internal pure returns (string result) {
        bytes memory bytesString = new bytes(32);
        uint charCount = 0;
        for (uint j = 0; j < 32; j++) {
            byte char = byte(bytes32(uint(_source) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[charCount] = char;
                charCount++;
            }
        }
        bytes memory bytesStringTrimmed = new bytes(charCount);
        for (j = 0; j < charCount; j++) {
            bytesStringTrimmed[j] = bytesString[j];
        }
        return string(bytesStringTrimmed);
    }

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


}

/**
 * @title Helps contracts guard agains reentrancy attacks.
 * @author Remco Bloemen <[email protected]π.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 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 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 ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
contract ERC20 is ERC20Basic {
  function allowance(address owner, address spender)
    public view returns (uint256);

  function transferFrom(address from, address to, uint256 value)
    public returns (bool);

  function approve(address spender, uint256 value) public returns (bool);
  event Approval(
    address indexed owner,
    address indexed spender,
    uint256 value
  );
}

/**
 * @title 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 to be implemented by all permission manager modules
 */
interface IPermissionManager {

    /**
    * @notice Used to check the permission on delegate corresponds to module contract address
    * @param _delegate Ethereum address of the delegate
    * @param _module Ethereum contract address of the module
    * @param _perm Permission flag
    * @return bool
    */
    function checkPermission(address _delegate, address _module, bytes32 _perm) external view returns(bool);

    /**
    * @notice Used to add a delegate
    * @param _delegate Ethereum address of the delegate
    * @param _details Details about the delegate i.e `Belongs to financial firm`
    */
    function addDelegate(address _delegate, bytes32 _details) external;

    /**
    * @notice Used to delete a delegate
    * @param _delegate Ethereum address of the delegate
    */
    function deleteDelegate(address _delegate) external;

    /**
    * @notice Used to check if an address is a delegate or not
    * @param _potentialDelegate the address of potential delegate
    * @return bool
    */
    function checkDelegate(address _potentialDelegate) external view returns(bool);

    /**
    * @notice Used to provide/change the permission to the delegate corresponds to the module contract
    * @param _delegate Ethereum address of the delegate
    * @param _module Ethereum contract address of the module
    * @param _perm Permission flag
    * @param _valid Bool flag use to switch on/off the permission
    * @return bool
    */
    function changePermission(
        address _delegate,
        address _module,
        bytes32 _perm,
        bool _valid
    )
    external;

    /**
    * @notice Used to change one or more permissions for a single delegate at once
    * @param _delegate Ethereum address of the delegate
    * @param _modules Multiple module matching the multiperms, needs to be same length
    * @param _perms Multiple permission flag needs to be changed
    * @param _valids Bool array consist the flag to switch on/off the permission
    * @return nothing
    */
    function changePermissionMulti(
        address _delegate,
        address[] _modules,
        bytes32[] _perms,
        bool[] _valids
    )
    external;

    /**
    * @notice Used to return all delegates with a given permission and module
    * @param _module Ethereum contract address of the module
    * @param _perm Permission flag
    * @return address[]
    */
    function getAllDelegatesWithPerm(address _module, bytes32 _perm) external view returns(address[]);

     /**
    * @notice Used to return all permission of a single or multiple module
    * @dev possible that function get out of gas is there are lot of modules and perm related to them
    * @param _delegate Ethereum address of the delegate
    * @param _types uint8[] of types
    * @return address[] the address array of Modules this delegate has permission
    * @return bytes32[] the permission array of the corresponding Modules
    */
    function getAllModulesAndPermsFromTypes(address _delegate, uint8[] _types) external view returns(address[], bytes32[]);

    /**
    * @notice Used to get the Permission flag related the `this` contract
    * @return Array of permission flags
    */
    function getPermissions() external view returns(bytes32[]);

    /**
    * @notice Used to get all delegates
    * @return address[]
    */
    function getAllDelegates() external view returns(address[]);

}

library TokenLib {

    using SafeMath for uint256;

    // Struct for module data
    struct ModuleData {
        bytes32 name;
        address module;
        address moduleFactory;
        bool isArchived;
        uint8[] moduleTypes;
        uint256[] moduleIndexes;
        uint256 nameIndex;
    }

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

    struct InvestorDataStorage {
        // List of investors who have ever held a non-zero token balance
        mapping (address => bool) investorListed;
        // List of token holders
        address[] investors;
        // Total number of non-zero token holders
        uint256 investorCount;
    }

    // Emit when Module is archived from the SecurityToken
    event ModuleArchived(uint8[] _types, address _module, uint256 _timestamp);
    // Emit when Module is unarchived from the SecurityToken
    event ModuleUnarchived(uint8[] _types, address _module, uint256 _timestamp);

    /**
    * @notice Archives a module attached to the SecurityToken
    * @param _moduleData Storage data
    * @param _module Address of module to archive
    */
    function archiveModule(ModuleData storage _moduleData, address _module) public {
        require(!_moduleData.isArchived, "Module archived");
        require(_moduleData.module != address(0), "Module missing");
        /*solium-disable-next-line security/no-block-members*/
        emit ModuleArchived(_moduleData.moduleTypes, _module, now);
        _moduleData.isArchived = true;
    }

    /**
    * @notice Unarchives a module attached to the SecurityToken
    * @param _moduleData Storage data
    * @param _module Address of module to unarchive
    */
    function unarchiveModule(ModuleData storage _moduleData, address _module) public {
        require(_moduleData.isArchived, "Module unarchived");
        /*solium-disable-next-line security/no-block-members*/
        emit ModuleUnarchived(_moduleData.moduleTypes, _module, now);
        _moduleData.isArchived = false;
    }

    /**
     * @notice Validates permissions with PermissionManager if it exists. If there's no permission return false
     * @dev Note that IModule withPerm will allow ST owner all permissions by default
     * @dev this allows individual modules to override this logic if needed (to not allow ST owner all permissions)
     * @param _modules is the modules to check permissions on
     * @param _delegate is the address of the delegate
     * @param _module is the address of the PermissionManager module
     * @param _perm is the permissions data
     * @return success
     */
    function checkPermission(address[] storage _modules, address _delegate, address _module, bytes32 _perm) public view returns(bool) {
        if (_modules.length == 0) {
            return false;
        }

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

        return false;
    }

    /**
     * @notice Queries a value at a defined checkpoint
     * @param _checkpoints is array of Checkpoint objects
     * @param _checkpointId is the Checkpoint ID to query
     * @param _currentValue is the Current value of checkpoint
     * @return uint256
     */
    function getValueAt(Checkpoint[] storage _checkpoints, uint256 _checkpointId, uint256 _currentValue) public view returns(uint256) {
        //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 Stores the changes to the checkpoint objects
     * @param _checkpoints is the affected checkpoint object array
     * @param _newValue is the new value that needs to be stored
     */
    function adjustCheckpoints(TokenLib.Checkpoint[] storage _checkpoints, uint256 _newValue, uint256 _currentCheckpointId) public {
        //No checkpoints set yet
        if (_currentCheckpointId == 0) {
            return;
        }
        //No new checkpoints since last update
        if ((_checkpoints.length > 0) && (_checkpoints[_checkpoints.length - 1].checkpointId == _currentCheckpointId)) {
            return;
        }
        //New checkpoint, so record balance
        _checkpoints.push(
            TokenLib.Checkpoint({
                checkpointId: _currentCheckpointId,
                value: _newValue
            })
        );
    }

    /**
    * @notice Keeps track of the number of non-zero token holders
    * @param _investorData Date releated to investor metrics
    * @param _from Sender of transfer
    * @param _to Receiver of transfer
    * @param _value Value of transfer
    * @param _balanceTo Balance of the _to address
    * @param _balanceFrom Balance of the _from address
    */
    function adjustInvestorCount(
        InvestorDataStorage storage _investorData,
        address _from,
        address _to,
        uint256 _value,
        uint256 _balanceTo,
        uint256 _balanceFrom
        ) public  {
        if ((_value == 0) || (_from == _to)) {
            return;
        }
        // Check whether receiver is a new token holder
        if ((_balanceTo == 0) && (_to != address(0))) {
            _investorData.investorCount = (_investorData.investorCount).add(1);
        }
        // Check whether sender is moving all of their tokens
        if (_value == _balanceFrom) {
            _investorData.investorCount = (_investorData.investorCount).sub(1);
        }
        //Also adjust investor list
        if (!_investorData.investorListed[_to] && (_to != address(0))) {
            _investorData.investors.push(_to);
            _investorData.investorListed[_to] = true;
        }

    }

}

/**
* @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
* @notice - ST does not inherit from ISecurityToken due to:
* @notice - https://github.com/ethereum/solidity/issues/4847
*/
contract SecurityToken is StandardToken, DetailedERC20, ReentrancyGuard, RegistryUpdater {
    using SafeMath for uint256;

    TokenLib.InvestorDataStorage investorData;

    // Used to hold the semantic version data
    struct SemanticVersion {
        uint8 major;
        uint8 minor;
        uint8 patch;
    }

    SemanticVersion securityTokenVersion;

    // off-chain data
    string public tokenDetails;

    uint8 constant PERMISSION_KEY = 1;
    uint8 constant TRANSFER_KEY = 2;
    uint8 constant MINT_KEY = 3;
    uint8 constant CHECKPOINT_KEY = 4;
    uint8 constant BURN_KEY = 5;

    uint256 public granularity;

    // Value of current checkpoint
    uint256 public currentCheckpointId;

    // Used to temporarily halt all transactions
    bool public transfersFrozen;

    // Used to permanently halt all minting
    bool public mintingFrozen;

    // Used to permanently halt controller actions
    bool public controllerDisabled;

    // Address whitelisted by issuer as controller
    address public controller;

    // Records added modules - module list should be order agnostic!
    mapping (uint8 => address[]) modules;

    // Records information about the module
    mapping (address => TokenLib.ModuleData) modulesToData;

    // Records added module names - module list should be order agnostic!
    mapping (bytes32 => address[]) names;

    // Map each investor to a series of checkpoints
    mapping (address => TokenLib.Checkpoint[]) checkpointBalances;

    // List of checkpoints that relate to total supply
    TokenLib.Checkpoint[] checkpointTotalSupply;

    // Times at which each checkpoint was created
    uint256[] checkpointTimes;

    // Emit at the time when module get added
    event ModuleAdded(
        uint8[] _types,
        bytes32 _name,
        address _moduleFactory,
        address _module,
        uint256 _moduleCost,
        uint256 _budget,
        uint256 _timestamp
    );

    // Emit when the token details get updated
    event UpdateTokenDetails(string _oldDetails, string _newDetails);
    // Emit when the granularity get changed
    event GranularityChanged(uint256 _oldGranularity, uint256 _newGranularity);
    // Emit when Module get archived from the securityToken
    event ModuleArchived(uint8[] _types, address _module, uint256 _timestamp);
    // Emit when Module get unarchived from the securityToken
    event ModuleUnarchived(uint8[] _types, address _module, uint256 _timestamp);
    // Emit when Module get removed from the securityToken
    event ModuleRemoved(uint8[] _types, address _module, uint256 _timestamp);
    // Emit when the budget allocated to a module is changed
    event ModuleBudgetChanged(uint8[] _moduleTypes, address _module, uint256 _oldBudget, uint256 _budget);
    // Emit when transfers are frozen or unfrozen
    event FreezeTransfers(bool _status, uint256 _timestamp);
    // Emit when new checkpoint created
    event CheckpointCreated(uint256 indexed _checkpointId, uint256 _timestamp);
    // Emit when is permanently frozen by the issuer
    event FreezeMinting(uint256 _timestamp);
    // Events to log minting and burning
    event Minted(address indexed _to, uint256 _value);
    event Burnt(address indexed _from, uint256 _value);

    // Events to log controller actions
    event SetController(address indexed _oldController, address indexed _newController);
    event ForceTransfer(
        address indexed _controller,
        address indexed _from,
        address indexed _to,
        uint256 _value,
        bool _verifyTransfer,
        bytes _data
    );
    event ForceBurn(
        address indexed _controller,
        address indexed _from,
        uint256 _value,
        bool _verifyTransfer,
        bytes _data
    );
    event DisableController(uint256 _timestamp);

    function _isModule(address _module, uint8 _type) internal view returns (bool) {
        require(modulesToData[_module].module == _module, "Wrong address");
        require(!modulesToData[_module].isArchived, "Module archived");
        for (uint256 i = 0; i < modulesToData[_module].moduleTypes.length; i++) {
            if (modulesToData[_module].moduleTypes[i] == _type) {
                return true;
            }
        }
        return false;
    }

    // Require msg.sender to be the specified module type
    modifier onlyModule(uint8 _type) {
        require(_isModule(msg.sender, _type));
        _;
    }

    // Require msg.sender to be the specified module type or the owner of the token
    modifier onlyModuleOrOwner(uint8 _type) {
        if (msg.sender == owner) {
            _;
        } else {
            require(_isModule(msg.sender, _type));
            _;
        }
    }

    modifier checkGranularity(uint256 _value) {
        require(_value % granularity == 0, "Invalid granularity");
        _;
    }

    modifier isMintingAllowed() {
        require(!mintingFrozen, "Minting frozen");
        _;
    }

    modifier isEnabled(string _nameKey) {
        require(IFeatureRegistry(featureRegistry).getFeatureStatus(_nameKey));
        _;
    }

    /**
     * @notice Revert if called by an account which is not a controller
     */
    modifier onlyController() {
        require(msg.sender == controller, "Not controller");
        require(!controllerDisabled, "Controller disabled");
        _;
    }

    /**
     * @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
     * @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;
        securityTokenVersion = SemanticVersion(2,0,0);
    }

    /**
     * @notice Attachs a module to the SecurityToken
     * @dev  E.G.: On deployment (through the STR) ST gets a TransferManager module attached to it
     * @dev to control restrictions on transfers.
     * @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 the module.
     * @param _budget max amount of ongoing POLY willing to assign to the module.
     */
    function addModule(
        address _moduleFactory,
        bytes _data,
        uint256 _maxCost,
        uint256 _budget
    ) external onlyOwner nonReentrant {
        //Check that the module factory exists in the ModuleRegistry - will throw otherwise
        IModuleRegistry(moduleRegistry).useModule(_moduleFactory);
        IModuleFactory moduleFactory = IModuleFactory(_moduleFactory);
        uint8[] memory moduleTypes = moduleFactory.getTypes();
        uint256 moduleCost = moduleFactory.getSetupCost();
        require(moduleCost <= _maxCost, "Invalid cost");
        //Approve fee for module
        ERC20(polyToken).approve(_moduleFactory, moduleCost);
        //Creates instance of module from factory
        address module = moduleFactory.deploy(_data);
        require(modulesToData[module].module == address(0), "Module exists");
        //Approve ongoing budget
        ERC20(polyToken).approve(module, _budget);
        //Add to SecurityToken module map
        bytes32 moduleName = moduleFactory.getName();
        uint256[] memory moduleIndexes = new uint256[](moduleTypes.length);
        uint256 i;
        for (i = 0; i < moduleTypes.length; i++) {
            moduleIndexes[i] = modules[moduleTypes[i]].length;
            modules[moduleTypes[i]].push(module);
        }
        modulesToData[module] = TokenLib.ModuleData(
            moduleName, module, _moduleFactory, false, moduleTypes, moduleIndexes, names[moduleName].length
        );
        names[moduleName].push(module);
        //Emit log event
        /*solium-disable-next-line security/no-block-members*/
        emit ModuleAdded(moduleTypes, moduleName, _moduleFactory, module, moduleCost, _budget, now);
    }

    /**
    * @notice Archives a module attached to the SecurityToken
    * @param _module address of module to archive
    */
    function archiveModule(address _module) external onlyOwner {
        TokenLib.archiveModule(modulesToData[_module], _module);
    }

    /**
    * @notice Unarchives a module attached to the SecurityToken
    * @param _module address of module to unarchive
    */
    function unarchiveModule(address _module) external onlyOwner {
        TokenLib.unarchiveModule(modulesToData[_module], _module);
    }

    /**
    * @notice Removes a module attached to the SecurityToken
    * @param _module address of module to unarchive
    */
    function removeModule(address _module) external onlyOwner {
        require(modulesToData[_module].isArchived, "Not archived");
        require(modulesToData[_module].module != address(0), "Module missing");
        /*solium-disable-next-line security/no-block-members*/
        emit ModuleRemoved(modulesToData[_module].moduleTypes, _module, now);
        // Remove from module type list
        uint8[] memory moduleTypes = modulesToData[_module].moduleTypes;
        for (uint256 i = 0; i < moduleTypes.length; i++) {
            _removeModuleWithIndex(moduleTypes[i], modulesToData[_module].moduleIndexes[i]);
            /* modulesToData[_module].moduleType[moduleTypes[i]] = false; */
        }
        // Remove from module names list
        uint256 index = modulesToData[_module].nameIndex;
        bytes32 name = modulesToData[_module].name;
        uint256 length = names[name].length;
        names[name][index] = names[name][length - 1];
        names[name].length = length - 1;
        if ((length - 1) != index) {
            modulesToData[names[name][index]].nameIndex = index;
        }
        // Remove from modulesToData
        delete modulesToData[_module];
    }

    /**
    * @notice Internal - Removes a module attached to the SecurityToken by index
    */
    function _removeModuleWithIndex(uint8 _type, uint256 _index) internal {
        uint256 length = modules[_type].length;
        modules[_type][_index] = modules[_type][length - 1];
        modules[_type].length = length - 1;

        if ((length - 1) != _index) {
            //Need to find index of _type in moduleTypes of module we are moving
            uint8[] memory newTypes = modulesToData[modules[_type][_index]].moduleTypes;
            for (uint256 i = 0; i < newTypes.length; i++) {
                if (newTypes[i] == _type) {
                    modulesToData[modules[_type][_index]].moduleIndexes[i] = _index;
                }
            }
        }
    }

    /**
     * @notice Returns the data associated to a module
     * @param _module address of the module
     * @return bytes32 name
     * @return address module address
     * @return address module factory address
     * @return bool module archived
     * @return uint8 module type
     */
    function getModule(address _module) external view returns (bytes32, address, address, bool, uint8[]) {
        return (modulesToData[_module].name,
        modulesToData[_module].module,
        modulesToData[_module].moduleFactory,
        modulesToData[_module].isArchived,
        modulesToData[_module].moduleTypes);
    }

    /**
     * @notice Returns a list of modules that match the provided name
     * @param _name name of the module
     * @return address[] list of modules with this name
     */
    function getModulesByName(bytes32 _name) external view returns (address[]) {
        return names[_name];
    }

    /**
     * @notice Returns a list of modules that match the provided module type
     * @param _type type of the module
     * @return address[] list of modules with this type
     */
    function getModulesByType(uint8 _type) external view returns (address[]) {
        return modules[_type];
    }

   /**
    * @notice Allows the owner to withdraw unspent POLY stored by them on the ST or any ERC20 token.
    * @dev Owner can transfer POLY to the ST which will be used to pay for modules that require a POLY fee.
    * @param _tokenContract Address of the ERC20Basic compliance token
    * @param _value amount of POLY to withdraw
    */
    function withdrawERC20(address _tokenContract, uint256 _value) external onlyOwner {
        require(_tokenContract != address(0));
        IERC20 token = IERC20(_tokenContract);
        require(token.transfer(owner, _value));
    }

    /**

    * @notice allows owner to increase/decrease POLY approval of one of the modules
    * @param _module module address
    * @param _change change in allowance
    * @param _increase true if budget has to be increased, false if decrease
    */
    function changeModuleBudget(address _module, uint256 _change, bool _increase) external onlyOwner {
        require(modulesToData[_module].module != address(0), "Module missing");
        uint256 currentAllowance = IERC20(polyToken).allowance(address(this), _module);
        uint256 newAllowance;
        if (_increase) {
            require(IERC20(polyToken).increaseApproval(_module, _change), "IncreaseApproval fail");
            newAllowance = currentAllowance.add(_change);
        } else {
            require(IERC20(polyToken).decreaseApproval(_module, _change), "Insufficient allowance");
            newAllowance = currentAllowance.sub(_change);
        }
        emit ModuleBudgetChanged(modulesToData[_module].moduleTypes, _module, currentAllowance, newAllowance);
    }

    /**
     * @notice updates the tokenDetails associated with the token
     * @param _newTokenDetails New token details
     */
    function updateTokenDetails(string _newTokenDetails) external onlyOwner {
        emit UpdateTokenDetails(tokenDetails, _newTokenDetails);
        tokenDetails = _newTokenDetails;
    }

    /**
    * @notice Allows owner to change token granularity
    * @param _granularity granularity level of the token
    */
    function changeGranularity(uint256 _granularity) external onlyOwner {
        require(_granularity != 0, "Invalid granularity");
        emit GranularityChanged(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 {
        TokenLib.adjustInvestorCount(investorData, _from, _to, _value, balanceOf(_to), balanceOf(_from));
    }

    /**
     * @notice returns an array of investors
     * NB - this length may differ from investorCount as it contains all investors that ever held tokens
     * @return list of addresses
     */
    function getInvestors() external view returns(address[]) {
        return investorData.investors;
    }

    /**
     * @notice returns an array of investors at a given checkpoint
     * NB - this length may differ from investorCount as it contains all investors that ever held tokens
     * @param _checkpointId Checkpoint id at which investor list is to be populated
     * @return list of investors
     */
    function getInvestorsAt(uint256 _checkpointId) external view returns(address[]) {
        uint256 count = 0;
        uint256 i;
        for (i = 0; i < investorData.investors.length; i++) {
            if (balanceOfAt(investorData.investors[i], _checkpointId) > 0) {
                count++;
            }
        }
        address[] memory investors = new address[](count);
        count = 0;
        for (i = 0; i < investorData.investors.length; i++) {
            if (balanceOfAt(investorData.investors[i], _checkpointId) > 0) {
                investors[count] = investorData.investors[i];
                count++;
            }
        }
        return investors;
    }

    /**
     * @notice generates subset of investors
     * NB - can be used in batches if investor list is large
     * @param _start Position of investor to start iteration from
     * @param _end Position of investor to stop iteration at
     * @return list of investors
     */
    function iterateInvestors(uint256 _start, uint256 _end) external view returns(address[]) {
        require(_end <= investorData.investors.length, "Invalid end");
        address[] memory investors = new address[](_end.sub(_start));
        uint256 index = 0;
        for (uint256 i = _start; i < _end; i++) {
            investors[index] = investorData.investors[i];
            index++;
        }
        return investors;
    }

    /**
     * @notice Returns the investor count
     * @return Investor count
     */
    function getInvestorCount() external view returns(uint256) {
        return investorData.investorCount;
    }

    /**
     * @notice freezes transfers
     */
    function freezeTransfers() external onlyOwner {
        require(!transfersFrozen, "Already frozen");
        transfersFrozen = true;
        /*solium-disable-next-line security/no-block-members*/
        emit FreezeTransfers(true, now);
    }

    /**
     * @notice Unfreeze transfers
     */
    function unfreezeTransfers() external onlyOwner {
        require(transfersFrozen, "Not frozen");
        transfersFrozen = false;
        /*solium-disable-next-line security/no-block-members*/
        emit FreezeTransfers(false, now);
    }

    /**
     * @notice Internal - adjusts totalSupply at checkpoint after minting or burning tokens
     */
    function _adjustTotalSupplyCheckpoints() internal {
        TokenLib.adjustCheckpoints(checkpointTotalSupply, totalSupply(), currentCheckpointId);
    }

    /**
     * @notice Internal - adjusts token holder balance at checkpoint after a token transfer
     * @param _investor address of the token holder affected
     */
    function _adjustBalanceCheckpoints(address _investor) internal {
        TokenLib.adjustCheckpoints(checkpointBalances[_investor], balanceOf(_investor), currentCheckpointId);
    }

    /**
     * @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) {
        return transferWithData(_to, _value, "");
    }

    /**
     * @notice Overloaded version of the transfer function
     * @param _to receiver of transfer
     * @param _value value of transfer
     * @param _data data to indicate validation
     * @return bool success
     */
    function transferWithData(address _to, uint256 _value, bytes _data) public returns (bool success) {
        require(_updateTransfer(msg.sender, _to, _value, _data), "Transfer invalid");
        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) {
        return transferFromWithData(_from, _to, _value, "");
    }

    /**
     * @notice Overloaded version of the transferFrom function
     * @param _from sender of transfer
     * @param _to receiver of transfer
     * @param _value value of transfer
     * @param _data data to indicate validation
     * @return bool success
     */
    function transferFromWithData(address _from, address _to, uint256 _value, bytes _data) public returns(bool) {
        require(_updateTransfer(_from, _to, _value, _data), "Transfer invalid");
        require(super.transferFrom(_from, _to, _value));
        return true;
    }

    /**
     * @notice Updates internal variables when performing a transfer
     * @param _from sender of transfer
     * @param _to receiver of transfer
     * @param _value value of transfer
     * @param _data data to indicate validation
     * @return bool success
     */
    function _updateTransfer(address _from, address _to, uint256 _value, bytes _data) internal nonReentrant returns(bool) {
        // NB - the ordering in this function implies the following:
        //  - investor counts are updated before transfer managers are called - i.e. transfer managers will see
        //investor counts including the current transfer.
        //  - checkpoints are updated after the transfer managers are called. This allows TMs to create
        //checkpoints as though they have been created before the current transactions,
        //  - to avoid the situation where a transfer manager transfers tokens, and this function is called recursively,
        //the function is marked as nonReentrant. This means that no TM can transfer (or mint / burn) tokens.
        _adjustInvestorCount(_from, _to, _value);
        bool verified = _verifyTransfer(_from, _to, _value, _data, true);
        _adjustBalanceCheckpoints(_from);
        _adjustBalanceCheckpoints(_to);
        return verified;
    }

    /**
     * @notice Validate transfer with TransferManager module if it exists
     * @dev TransferManager module has a key of 2
     * @dev _isTransfer boolean flag is the deciding factor for whether the
     * state variables gets modified or not within the different modules. i.e isTransfer = true
     * leads to change in the modules environment otherwise _verifyTransfer() works as a read-only
     * function (no change in the state).
     * @param _from sender of transfer
     * @param _to receiver of transfer
     * @param _value value of transfer
     * @param _data data to indicate validation
     * @param _isTransfer whether transfer is being executed
     * @return bool
     */
    function _verifyTransfer(
        address _from,
        address _to,
        uint256 _value,
        bytes _data,
        bool _isTransfer
    ) internal checkGranularity(_value) returns (bool) {
        if (!transfersFrozen) {
            bool isInvalid = false;
            bool isValid = false;
            bool isForceValid = false;
            bool unarchived = false;
            address module;
            for (uint256 i = 0; i < modules[TRANSFER_KEY].length; i++) {
                module = modules[TRANSFER_KEY][i];
                if (!modulesToData[module].isArchived) {
                    unarchived = true;
                    ITransferManager.Result valid = ITransferManager(module).verifyTransfer(_from, _to, _value, _data, _isTransfer);
                    if (valid == ITransferManager.Result.INVALID) {
                        isInvalid = true;
                    } else if (valid == ITransferManager.Result.VALID) {
                        isValid = true;
                    } else if (valid == ITransferManager.Result.FORCE_VALID) {
                        isForceValid = true;
                    }
                }
            }
            // If no unarchived modules, return true by default
            return unarchived ? (isForceValid ? true : (isInvalid ? false : isValid)) : true;
        }
        return false;
    }

    /**
     * @notice Validates a transfer with a TransferManager module if it exists
     * @dev TransferManager module has a key of 2
     * @param _from sender of transfer
     * @param _to receiver of transfer
     * @param _value value of transfer
     * @param _data data to indicate validation
     * @return bool
     */
    function verifyTransfer(address _from, address _to, uint256 _value, bytes _data) public returns (bool) {
        return _verifyTransfer(_from, _to, _value, _data, false);
    }

    /**
     * @notice Permanently freeze minting of this security token.
     * @dev It MUST NOT be possible to increase `totalSuppy` after this function is called.
     */
    function freezeMinting() external isMintingAllowed() isEnabled("freezeMintingAllowed") onlyOwner {
        mintingFrozen = true;
        /*solium-disable-next-line security/no-block-members*/
        emit FreezeMinting(now);
    }

    /**
     * @notice Mints new tokens and assigns them to the target _investor.
     * @dev Can only be called by the issuer or STO attached to the token
     * @param _investor Address where the minted tokens will be delivered
     * @param _value Number of tokens be minted
     * @return success
     */
    function mint(address _investor, uint256 _value) public returns (bool success) {
        return mintWithData(_investor, _value, "");
    }

    /**
     * @notice mints new tokens and assigns them to the target _investor.
     * @dev Can only be called by the issuer or STO attached to the token
     * @param _investor Address where the minted tokens will be delivered
     * @param _value Number of tokens be minted
     * @param _data data to indicate validation
     * @return success
     */
    function mintWithData(
        address _investor,
        uint256 _value,
        bytes _data
        ) public onlyModuleOrOwner(MINT_KEY) isMintingAllowed() returns (bool success) {
        require(_investor != address(0), "Investor is 0");
        require(_updateTransfer(address(0), _investor, _value, _data), "Transfer invalid");
        _adjustTotalSupplyCheckpoints();
        totalSupply_ = totalSupply_.add(_value);
        balances[_investor] = balances[_investor].add(_value);
        emit Minted(_investor, _value);
        emit Transfer(address(0), _investor, _value);
        return true;
    }

    /**
     * @notice Mints new tokens and assigns them to the target _investor.
     * @dev Can only be called by the issuer or STO attached to the token.
     * @param _investors A list of addresses to whom the minted tokens will be dilivered
     * @param _values 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[] _values) external returns (bool success) {
        require(_investors.length == _values.length, "Incorrect inputs");
        for (uint256 i = 0; i < _investors.length; i++) {
            mint(_investors[i], _values[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) {
        for (uint256 i = 0; i < modules[PERMISSION_KEY].length; i++) {
            if (!modulesToData[modules[PERMISSION_KEY][i]].isArchived)
                return TokenLib.checkPermission(modules[PERMISSION_KEY], _delegate, _module, _perm);
        }
        return false;
    }

    function _burn(address _from, uint256 _value, bytes _data) internal returns(bool) {
        require(_value <= balances[_from], "Value too high");
        bool verified = _updateTransfer(_from, address(0), _value, _data);
        _adjustTotalSupplyCheckpoints();
        balances[_from] = balances[_from].sub(_value);
        totalSupply_ = totalSupply_.sub(_value);
        emit Burnt(_from, _value);
        emit Transfer(_from, address(0), _value);
        return verified;
    }

    /**
     * @notice Burn function used to burn the securityToken
     * @param _value No. of tokens that get burned
     * @param _data data to indicate validation
     */
    function burnWithData(uint256 _value, bytes _data) public onlyModule(BURN_KEY) {
        require(_burn(msg.sender, _value, _data), "Burn invalid");
    }

    /**
     * @notice Burn function used to burn the securityToken on behalf of someone else
     * @param _from Address for whom to burn tokens
     * @param _value No. of tokens that get burned
     * @param _data data to indicate validation
     */
    function burnFromWithData(address _from, uint256 _value, bytes _data) public onlyModule(BURN_KEY) {
        require(_value <= allowed[_from][msg.sender], "Value too high");
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
        require(_burn(_from, _value, _data), "Burn invalid");
    }

    /**
     * @notice Creates a checkpoint that can be used to query historical balances / totalSuppy
     * @return uint256
     */
    function createCheckpoint() external onlyModuleOrOwner(CHECKPOINT_KEY) returns(uint256) {
        require(currentCheckpointId < 2**256 - 1);
        currentCheckpointId = currentCheckpointId + 1;
        /*solium-disable-next-line security/no-block-members*/
        checkpointTimes.push(now);
        /*solium-disable-next-line security/no-block-members*/
        emit CheckpointCreated(currentCheckpointId, now);
        return currentCheckpointId;
    }

    /**
     * @notice Gets list of times that checkpoints were created
     * @return List of checkpoint times
     */
    function getCheckpointTimes() external view returns(uint256[]) {
        return checkpointTimes;
    }

    /**
     * @notice Queries totalSupply as of a defined checkpoint
     * @param _checkpointId Checkpoint ID to query
     * @return uint256
     */
    function totalSupplyAt(uint256 _checkpointId) external view returns(uint256) {
        require(_checkpointId <= currentCheckpointId);
        return TokenLib.getValueAt(checkpointTotalSupply, _checkpointId, totalSupply());
    }

    /**
     * @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) {
        require(_checkpointId <= currentCheckpointId);
        return TokenLib.getValueAt(checkpointBalances[_investor], _checkpointId, balanceOf(_investor));
    }

    /**
     * @notice Used by the issuer to set the controller addresses
     * @param _controller address of the controller
     */
    function setController(address _controller) public onlyOwner {
        require(!controllerDisabled);
        emit SetController(controller, _controller);
        controller = _controller;
    }

    /**
     * @notice Used by the issuer to permanently disable controller functionality
     * @dev enabled via feature switch "disableControllerAllowed"
     */
    function disableController() external isEnabled("disableControllerAllowed") onlyOwner {
        require(!controllerDisabled);
        controllerDisabled = true;
        delete controller;
        /*solium-disable-next-line security/no-block-members*/
        emit DisableController(now);
    }

    /**
     * @notice Used by a controller to execute a forced transfer
     * @param _from address from which to take tokens
     * @param _to address where to send tokens
     * @param _value amount of tokens to transfer
     * @param _data data to indicate validation
     * @param _log data attached to the transfer by controller to emit in event
     */
    function forceTransfer(address _from, address _to, uint256 _value, bytes _data, bytes _log) public onlyController {
        require(_to != address(0));
        require(_value <= balances[_from]);
        bool verified = _updateTransfer(_from, _to, _value, _data);
        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);
        emit ForceTransfer(msg.sender, _from, _to, _value, verified, _log);
        emit Transfer(_from, _to, _value);
    }

    /**
     * @notice Used by a controller to execute a forced burn
     * @param _from address from which to take tokens
     * @param _value amount of tokens to transfer
     * @param _data data to indicate validation
     * @param _log data attached to the transfer by controller to emit in event
     */
    function forceBurn(address _from, uint256 _value, bytes _data, bytes _log) public onlyController {
        bool verified = _burn(_from, _value, _data);
        emit ForceBurn(msg.sender, _from, _value, verified, _log);
    }

    /**
     * @notice Returns the version of the SecurityToken
     */
    function getVersion() external view returns(uint8[]) {
        uint8[] memory _version = new uint8[](3);
        _version[0] = securityTokenVersion.major;
        _version[1] = securityTokenVersion.minor;
        _version[2] = securityTokenVersion.patch;
        return _version;
    }

}

Contract ABI
[{"constant":false,"inputs":[],"name":"freezeTransfers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getVersion","outputs":[{"name":"","type":"uint8[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_module","type":"address"}],"name":"unarchiveModule","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_granularity","type":"uint256"}],"name":"changeGranularity","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"transferWithData","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_start","type":"uint256"},{"name":"_end","type":"uint256"}],"name":"iterateInvestors","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unfreezeTransfers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_module","type":"address"}],"name":"archiveModule","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"},{"name":"_log","type":"bytes"}],"name":"forceBurn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"burnWithData","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_checkpointId","type":"uint256"}],"name":"getInvestorsAt","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_investor","type":"address"},{"name":"_value","type":"uint256"}],"name":"mint","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_investors","type":"address[]"},{"name":"_values","type":"uint256[]"}],"name":"mintMulti","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getCheckpointTimes","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_investor","type":"address"},{"name":"_checkpointId","type":"uint256"}],"name":"balanceOfAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentCheckpointId","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"granularity","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"},{"name":"_log","type":"bytes"}],"name":"forceTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_module","type":"address"},{"name":"_change","type":"uint256"},{"name":"_increase","type":"bool"}],"name":"changeModuleBudget","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"polyToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newTokenDetails","type":"string"}],"name":"updateTokenDetails","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getModulesByName","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":true,"inputs":[],"name":"controllerDisabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"burnFromWithData","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_delegate","type":"address"},{"name":"_module","type":"address"},{"name":"_perm","type":"bytes32"}],"name":"checkPermission","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"disableController","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_controller","type":"address"}],"name":"setController","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInvestorCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_investor","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"mintWithData","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_checkpointId","type":"uint256"}],"name":"totalSupplyAt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_module","type":"address"}],"name":"removeModule","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_tokenContract","type":"address"},{"name":"_value","type":"uint256"}],"name":"withdrawERC20","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"mintingFrozen","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_type","type":"uint8"}],"name":"getModulesByType","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInvestors","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_module","type":"address"}],"name":"getModule","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"bool"},{"name":"","type":"uint8[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"moduleRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"freezeMinting","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"featureRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"securityTokenRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenDetails","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"transfersFrozen","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"transferFromWithData","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"verifyTransfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","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":false,"inputs":[{"name":"_moduleFactory","type":"address"},{"name":"_data","type":"bytes"},{"name":"_maxCost","type":"uint256"},{"name":"_budget","type":"uint256"}],"name":"addModule","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"controller","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"createCheckpoint","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_decimals","type":"uint8"},{"name":"_granularity","type":"uint256"},{"name":"_tokenDetails","type":"string"},{"name":"_polymathRegistry","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_types","type":"uint8[]"},{"indexed":false,"name":"_name","type":"bytes32"},{"indexed":false,"name":"_moduleFactory","type":"address"},{"indexed":false,"name":"_module","type":"address"},{"indexed":false,"name":"_moduleCost","type":"uint256"},{"indexed":false,"name":"_budget","type":"uint256"},{"indexed":false,"name":"_timestamp","type":"uint256"}],"name":"ModuleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_oldDetails","type":"string"},{"indexed":false,"name":"_newDetails","type":"string"}],"name":"UpdateTokenDetails","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_oldGranularity","type":"uint256"},{"indexed":false,"name":"_newGranularity","type":"uint256"}],"name":"GranularityChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_types","type":"uint8[]"},{"indexed":false,"name":"_module","type":"address"},{"indexed":false,"name":"_timestamp","type":"uint256"}],"name":"ModuleArchived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_types","type":"uint8[]"},{"indexed":false,"name":"_module","type":"address"},{"indexed":false,"name":"_timestamp","type":"uint256"}],"name":"ModuleUnarchived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_types","type":"uint8[]"},{"indexed":false,"name":"_module","type":"address"},{"indexed":false,"name":"_timestamp","type":"uint256"}],"name":"ModuleRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_moduleTypes","type":"uint8[]"},{"indexed":false,"name":"_module","type":"address"},{"indexed":false,"name":"_oldBudget","type":"uint256"},{"indexed":false,"name":"_budget","type":"uint256"}],"name":"ModuleBudgetChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_status","type":"bool"},{"indexed":false,"name":"_timestamp","type":"uint256"}],"name":"FreezeTransfers","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_checkpointId","type":"uint256"},{"indexed":false,"name":"_timestamp","type":"uint256"}],"name":"CheckpointCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_timestamp","type":"uint256"}],"name":"FreezeMinting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Burnt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_oldController","type":"address"},{"indexed":true,"name":"_newController","type":"address"}],"name":"SetController","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_controller","type":"address"},{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"},{"indexed":false,"name":"_verifyTransfer","type":"bool"},{"indexed":false,"name":"_data","type":"bytes"}],"name":"ForceTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_controller","type":"address"},{"indexed":true,"name":"_from","type":"address"},{"indexed":false,"name":"_value","type":"uint256"},{"indexed":false,"name":"_verifyTransfer","type":"bool"},{"indexed":false,"name":"_data","type":"bytes"}],"name":"ForceBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_timestamp","type":"uint256"}],"name":"DisableController","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":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]

Contract Creation Code
60806040526005805461ff00191690553480156200001c57600080fd5b5060405162005ca838038062005ca88339810160409081528151602080840151928401516060850151608086015160a0870151948701805190979687019693959294919093019282918891889188916200007d91600391908601906200053e565b508151620000939060049060208501906200053e565b506005805460ff191660ff92909216919091176201000060b060020a0319163362010000021790555050600160a060020a03811615156200013557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f496e76616c696420616464726573730000000000000000000000000000000000604482015290519081900360640190fd5b60068054600160a060020a031916600160a060020a039290921691909117905562000168640100000000620001bc810204565b81516200017d90600f9060208501906200053e565b50505060105550506040805160608101825260028082526000602083018190529190920152600e805460ff191690911762ffff001916905550620005e3565b600554620100009004600160a060020a03163314620001da57600080fd5b600654604080517fbf40fac1000000000000000000000000000000000000000000000000000000008152602060048201819052600e60248301527f4d6f64756c65526567697374727900000000000000000000000000000000000060448301529151600160a060020a039093169263bf40fac1926064808401939192918290030181600087803b1580156200026e57600080fd5b505af115801562000283573d6000803e3d6000fd5b505050506040513d60208110156200029a57600080fd5b505160078054600160a060020a031916600160a060020a03928316179055600654604080517fbf40fac1000000000000000000000000000000000000000000000000000000008152602060048201819052601560248301527f5365637572697479546f6b656e5265676973747279000000000000000000000060448301529151929093169263bf40fac192606480830193928290030181600087803b1580156200034357600080fd5b505af115801562000358573d6000803e3d6000fd5b505050506040513d60208110156200036f57600080fd5b505160088054600160a060020a031916600160a060020a03928316179055600654604080517fbf40fac1000000000000000000000000000000000000000000000000000000008152602060048201819052600f60248301527f466561747572655265676973747279000000000000000000000000000000000060448301529151929093169263bf40fac192606480830193928290030181600087803b1580156200041857600080fd5b505af11580156200042d573d6000803e3d6000fd5b505050506040513d60208110156200044457600080fd5b505160098054600160a060020a031916600160a060020a03928316178155600654604080517fbf40fac100000000000000000000000000000000000000000000000000000000815260206004820181905260248201949094527f506f6c79546f6b656e000000000000000000000000000000000000000000000060448201529051919093169263bf40fac19260648083019391928290030181600087803b158015620004ef57600080fd5b505af115801562000504573d6000803e3d6000fd5b505050506040513d60208110156200051b57600080fd5b5051600a8054600160a060020a031916600160a060020a03909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200058157805160ff1916838001178555620005b1565b82800160010185558215620005b1579182015b82811115620005b157825182559160200191906001019062000594565b50620005bf929150620005c3565b5090565b620005e091905b80821115620005bf5760008155600101620005ca565b90565b6156b580620005f36000396000f3006080604052600436106102d15763ffffffff60e060020a6000350416630150246081146102d657806306fdde03146102ed578063095ea7b3146103775780630d8e6e2c146103af57806312ef7fe21461041457806318160ddd14610435578063210a8d0e1461045c57806323b872dd146104745780632535f7621461049e5780633052eed814610507578063313ce5671461052257806331c420d41461054d5780633576857e1461056257806338777af2146105835780633c9dcebe1461062a5780633f5535861461068857806340c10f19146106a057806346e4959d146106c45780634c6041d3146106f05780634ee2cd7e146107055780635488cc8014610729578063556f0dc71461073e5780635c49de5e1461075357806362b348c31461080057806366188463146108295780636faa22a51461084d57806370a082311461087e578063715018a61461089f57806373826a93146108b4578063764387bd146108d457806377282b70146108ec5780637a802c71146109015780637d6ae27b146109165780638658b8b91461097f578063869e50c7146109a95780638da5cb5b146109be57806392eefe9b146109d357806395d89b41146109f4578063960524e314610a0957806396adfe4214610a1e578063981b24d014610a87578063a063246114610a9f578063a1db978214610ac0578063a284de0214610ae4578063a9059cbb14610af9578063ac90b42214610b1d578063b2f5a54c14610b38578063b5de8d4c14610b4d578063b95459e414610bf3578063c013f30f14610c08578063caf90dab14610c1d578063ce4dbdff14610c32578063d6abe11014610c47578063d73dd62314610c5c578063dd62ed3e14610c80578063e45b813414610ca7578063ee532f3114610cbc578063f1d74b0f14610d2b578063f2fde38b14610d9a578063f433262f14610dbb578063f5efbd2d14610dd0578063f77c479114610e03578063ff0b9c9014610e18575b600080fd5b3480156102e257600080fd5b506102eb610e2d565b005b3480156102f957600080fd5b50610302610ef0565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561033c578181015183820152602001610324565b50505050905090810190601f1680156103695780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561038357600080fd5b5061039b600160a060020a0360043516602435610f7e565b604080519115158252519081900360200190f35b3480156103bb57600080fd5b506103c4610fe4565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156104005781810151838201526020016103e8565b505050509050019250505060405180910390f35b34801561042057600080fd5b506102eb600160a060020a036004351661108f565b34801561044157600080fd5b5061044a61114e565b60408051918252519081900360200190f35b34801561046857600080fd5b506102eb600435611155565b34801561048057600080fd5b5061039b600160a060020a036004358116906024351660443561120b565b3480156104aa57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261039b948235600160a060020a03169460248035953695946064949201919081908401838280828437509497506112319650505050505050565b34801561051357600080fd5b506103c46004356024356112a2565b34801561052e57600080fd5b506105376113b3565b6040805160ff9092168252519081900360200190f35b34801561055957600080fd5b506102eb6113bc565b34801561056e57600080fd5b506102eb600160a060020a036004351661147c565b34801561058f57600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102eb948235600160a060020a031694602480359536959460649492019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a9998810197919650918201945092508291508401838280828437509497506115209650505050505050565b34801561063657600080fd5b5060408051602060046024803582810135601f81018590048502860185019096528585526102eb9583359536956044949193909101919081908401838280828437509497506116c29650505050505050565b34801561069457600080fd5b506103c460043561173f565b3480156106ac57600080fd5b5061039b600160a060020a0360043516602435611850565b3480156106d057600080fd5b5061039b6024600480358281019290820135918135918201910135611874565b3480156106fc57600080fd5b506103c4611928565b34801561071157600080fd5b5061044a600160a060020a0360043516602435611980565b34801561073557600080fd5b5061044a611a48565b34801561074a57600080fd5b5061044a611a4e565b34801561075f57600080fd5b50604080516020601f6064356004818101359283018490048402850184019095528184526102eb94600160a060020a03813581169560248035909216956044359536956084940191819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750611a549650505050505050565b34801561080c57600080fd5b506102eb600160a060020a03600435166024356044351515611cfc565b34801561083557600080fd5b5061039b600160a060020a036004351660243561212b565b34801561085957600080fd5b5061086261221d565b60408051600160a060020a039092168252519081900360200190f35b34801561088a57600080fd5b5061044a600160a060020a036004351661222c565b3480156108ab57600080fd5b506102eb612247565b3480156108c057600080fd5b506102eb60048035602481019101356122c2565b3480156108e057600080fd5b506103c46004356123b9565b3480156108f857600080fd5b50610862612425565b34801561090d57600080fd5b5061039b612434565b34801561092257600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102eb948235600160a060020a03169460248035953695946064949201919081908401838280828437509497506124439650505050505050565b34801561098b57600080fd5b5061039b600160a060020a0360043581169060243516604435612594565b3480156109b557600080fd5b506102eb61273a565b3480156109ca57600080fd5b506108626128fd565b3480156109df57600080fd5b506102eb600160a060020a0360043516612912565b348015610a0057600080fd5b506103026129bf565b348015610a1557600080fd5b5061044a612a1a565b348015610a2a57600080fd5b50604080516020600460443581810135601f810184900484028501840190955284845261039b948235600160a060020a0316946024803595369594606494920191908190840183828082843750949750612a209650505050505050565b348015610a9357600080fd5b5061044a600435612e16565b348015610aab57600080fd5b506102eb600160a060020a0360043516612ec4565b348015610acc57600080fd5b506102eb600160a060020a0360043516602435613339565b348015610af057600080fd5b5061039b61341b565b348015610b0557600080fd5b5061039b600160a060020a0360043516602435613429565b348015610b2957600080fd5b506103c460ff60043516613446565b348015610b4457600080fd5b506103c46134b4565b348015610b5957600080fd5b50610b6e600160a060020a0360043516613518565b60408051868152600160a060020a0380871660208084019190915290861692820192909252831515606082015260a06080820181815284519183019190915283519192909160c0840191858101910280838360005b83811015610bdb578181015183820152602001610bc3565b50505050905001965050505050505060405180910390f35b348015610bff57600080fd5b506108626135e2565b348015610c1457600080fd5b506102eb6135f1565b348015610c2957600080fd5b506108626137e0565b348015610c3e57600080fd5b506108626137ef565b348015610c5357600080fd5b506103026137fe565b348015610c6857600080fd5b5061039b600160a060020a0360043516602435613859565b348015610c8c57600080fd5b5061044a600160a060020a03600435811690602435166138f2565b348015610cb357600080fd5b5061039b61391d565b348015610cc857600080fd5b50604080516020601f60643560048181013592830184900484028501840190955281845261039b94600160a060020a0381358116956024803590921695604435953695608494019181908401838280828437509497506139269650505050505050565b348015610d3757600080fd5b50604080516020601f60643560048181013592830184900484028501840190955281845261039b94600160a060020a0381358116956024803590921695604435953695608494019181908401838280828437509497506139999650505050505050565b348015610da657600080fd5b506102eb600160a060020a03600435166139b2565b348015610dc757600080fd5b506102eb6139db565b348015610ddc57600080fd5b506102eb60048035600160a060020a03169060248035908101910135604435606435613cf8565b348015610e0f57600080fd5b506108626145e3565b348015610e2457600080fd5b5061044a6145f9565b600554620100009004600160a060020a03163314610e4a57600080fd5b60125460ff1615610ea5576040805160e560020a62461bcd02815260206004820152600e60248201527f416c72656164792066726f7a656e000000000000000000000000000000000000604482015290519081900360640190fd5b6012805460ff191660019081179091556040805191825242602083015280517f04f1ca1e602280d208c2c7ff2646257c29fd92371788c49a8a5c27de99a2bcda9281900390910190a1565b6003805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610f765780601f10610f4b57610100808354040283529160200191610f76565b820191906000526020600020905b815481529060010190602001808311610f5957829003601f168201915b505050505081565b336000818152600260209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b604080516003808252608082019092526060918291906020820183803883395050600e54825192935060ff1691839150600090811061101f57fe5b60ff92831660209182029092010152600e548251610100909104909116908290600190811061104a57fe5b60ff92831660209182029092010152600e54825162010000909104909116908290600290811061107657fe5b60ff9092166020928302909101909101529050805b5090565b600554620100009004600160a060020a031633146110ac57600080fd5b600160a060020a03811660008181526014602052604080822081517f4e5ba926000000000000000000000000000000000000000000000000000000008152600481019190915260248101939093525173220f27e198d0dbaf823e677b52374ae46f4cc71b92634e5ba926926044808301939192829003018186803b15801561113357600080fd5b505af4158015611147573d6000803e3d6000fd5b5050505050565b6001545b90565b600554620100009004600160a060020a0316331461117257600080fd5b8015156111c9576040805160e560020a62461bcd02815260206004820152601360248201527f496e76616c6964206772616e756c617269747900000000000000000000000000604482015290519081900360640190fd5b601054604080519182526020820183905280517f7728e5c461dd94b32a33e149f4ef6b674a7eff704cac77b26937eaced90f00389281900390910190a1601055565b60006112298484846020604051908101604052806000815250613926565b949350505050565b600061123f3385858561474b565b1515611283576040805160e560020a62461bcd028152602060048201526010602482015260008051602061564a833981519152604482015290519081900360640190fd5b61128d84846147b5565b151561129857600080fd5b5060019392505050565b600c5460609081906000908190851115611306576040805160e560020a62461bcd02815260206004820152600b60248201527f496e76616c696420656e64000000000000000000000000000000000000000000604482015290519081900360640190fd5b611316858763ffffffff61488416565b60405190808252806020026020018201604052801561133f578160200160208202803883390190505b509250600091508590505b848110156113a957600c80548290811061136057fe5b6000918252602090912001548351600160a060020a039091169084908490811061138657fe5b600160a060020a039092166020928302909101909101526001918201910161134a565b5090949350505050565b60055460ff1681565b600554620100009004600160a060020a031633146113d957600080fd5b60125460ff161515611435576040805160e560020a62461bcd02815260206004820152600a60248201527f4e6f742066726f7a656e00000000000000000000000000000000000000000000604482015290519081900360640190fd5b6012805460ff19169055604080516000815242602082015281517f04f1ca1e602280d208c2c7ff2646257c29fd92371788c49a8a5c27de99a2bcda929181900390910190a1565b600554620100009004600160a060020a0316331461149957600080fd5b600160a060020a03811660008181526014602052604080822081517fe486dd3b000000000000000000000000000000000000000000000000000000008152600481019190915260248101939093525173220f27e198d0dbaf823e677b52374ae46f4cc71b9263e486dd3b926044808301939192829003018186803b15801561113357600080fd5b60125460009063010000009004600160a060020a0316331461158c576040805160e560020a62461bcd02815260206004820152600e60248201527f4e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b60125462010000900460ff16156115ed576040805160e560020a62461bcd02815260206004820152601360248201527f436f6e74726f6c6c65722064697361626c656400000000000000000000000000604482015290519081900360640190fd5b6115f8858585614896565b905084600160a060020a031633600160a060020a03167f27e232e0b8b07b7d0a09164e51186c4fb62c881eb6327305713f40282a16caf3868486604051808481526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561167f578181015183820152602001611667565b50505050905090810190601f1680156116ac5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a35050505050565b60056116ce33826149ed565b15156116d957600080fd5b6116e4338484614896565b151561173a576040805160e560020a62461bcd02815260206004820152600c60248201527f4275726e20696e76616c69640000000000000000000000000000000000000000604482015290519081900360640190fd5b505050565b6060600080825b600c5482101561179857600c8054600091611780918590811061176557fe5b600091825260209091200154600160a060020a031687611980565b111561178d576001909201915b600190910190611746565b826040519080825280602002602001820160405280156117c2578160200160208202803883390190505b50905060009250600091505b600c5482101561122957600c80546000916117ed918590811061176557fe5b111561184557600c80548390811061180157fe5b6000918252602090912001548151600160a060020a039091169082908590811061182757fe5b600160a060020a039092166020928302909101909101526001909201915b6001909101906117ce565b600061186d83836020604051908101604052806000815250612a20565b9392505050565b6000808483146118ce576040805160e560020a62461bcd02815260206004820152601060248201527f496e636f727265637420696e7075747300000000000000000000000000000000604482015290519081900360640190fd5b5060005b8481101561191c576119138686838181106118e957fe5b90506020020135600160a060020a0316858584818110151561190757fe5b90506020020135611850565b506001016118d2565b50600195945050505050565b6060601880548060200260200160405190810160405280929190818152602001828054801561197657602002820191906000526020600020905b815481526020019060010190808311611962575b5050505050905090565b60115460009082111561199257600080fd5b600160a060020a038316600090815260166020526040902073220f27e198d0dbaf823e677b52374ae46f4cc71b9063b58ae1e290846119d08761222c565b6040518463ffffffff1660e060020a02815260040180848152602001838152602001828152602001935050505060206040518083038186803b158015611a1557600080fd5b505af4158015611a29573d6000803e3d6000fd5b505050506040513d6020811015611a3f57600080fd5b50519392505050565b60115481565b60105481565b60125460009063010000009004600160a060020a03163314611ac0576040805160e560020a62461bcd02815260206004820152600e60248201527f4e6f7420636f6e74726f6c6c6572000000000000000000000000000000000000604482015290519081900360640190fd5b60125462010000900460ff1615611b21576040805160e560020a62461bcd02815260206004820152601360248201527f436f6e74726f6c6c65722064697361626c656400000000000000000000000000604482015290519081900360640190fd5b600160a060020a0385161515611b3657600080fd5b600160a060020a038616600090815260208190526040902054841115611b5b57600080fd5b611b678686868661474b565b600160a060020a038716600090815260208190526040902054909150611b93908563ffffffff61488416565b600160a060020a038088166000908152602081905260408082209390935590871681522054611bc8908563ffffffff614b7516565b60008087600160a060020a0316600160a060020a031681526020019081526020016000208190555084600160a060020a031686600160a060020a031633600160a060020a03167ff38eab8c5ef9ca0b5df51f887249efab0c1e0bb6272a62cc9d330800ee7ddf6b878587604051808481526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611c7f578181015183820152602001611c67565b50505050905090810190601f168015611cac5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a484600160a060020a031686600160a060020a031660008051602061566a833981519152866040518082815260200191505060405180910390a3505050505050565b6005546000908190620100009004600160a060020a03163314611d1e57600080fd5b600160a060020a03858116600090815260146020526040902060010154161515611d92576040805160e560020a62461bcd02815260206004820152600e60248201527f4d6f64756c65206d697373696e67000000000000000000000000000000000000604482015290519081900360640190fd5b600a54604080517fdd62ed3e000000000000000000000000000000000000000000000000000000008152306004820152600160a060020a0388811660248301529151919092169163dd62ed3e9160448083019260209291908290030181600087803b158015611e0057600080fd5b505af1158015611e14573d6000803e3d6000fd5b505050506040513d6020811015611e2a57600080fd5b505191508215611f3c57600a54604080517fd73dd623000000000000000000000000000000000000000000000000000000008152600160a060020a038881166004830152602482018890529151919092169163d73dd6239160448083019260209291908290030181600087803b158015611ea357600080fd5b505af1158015611eb7573d6000803e3d6000fd5b505050506040513d6020811015611ecd57600080fd5b50511515611f25576040805160e560020a62461bcd02815260206004820152601560248201527f496e637265617365417070726f76616c206661696c0000000000000000000000604482015290519081900360640190fd5b611f35828563ffffffff614b7516565b9050612040565b600a54604080517f66188463000000000000000000000000000000000000000000000000000000008152600160a060020a038881166004830152602482018890529151919092169163661884639160448083019260209291908290030181600087803b158015611fab57600080fd5b505af1158015611fbf573d6000803e3d6000fd5b505050506040513d6020811015611fd557600080fd5b5051151561202d576040805160e560020a62461bcd02815260206004820152601660248201527f496e73756666696369656e7420616c6c6f77616e636500000000000000000000604482015290519081900360640190fd5b61203d828563ffffffff61488416565b90505b7fa00a1c33ebb7433724919cb1059328c16265f935ef84a13442045da3e81c0ccc6014600087600160a060020a0316600160a060020a03168152602001908152602001600020600301868484604051808060200185600160a060020a0316600160a060020a03168152602001848152602001838152602001828103825286818154815260200191508054801561211357602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116120e45790505b50509550505050505060405180910390a15050505050565b336000908152600260209081526040808320600160a060020a03861684529091528120548083111561218057336000908152600260209081526040808320600160a060020a03881684529091528120556121b5565b612190818463ffffffff61488416565b336000908152600260209081526040808320600160a060020a03891684529091529020555b336000818152600260209081526040808320600160a060020a0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a3600191505b5092915050565b600a54600160a060020a031681565b600160a060020a031660009081526020819052604090205490565b600554620100009004600160a060020a0316331461226457600080fd5b60055460405162010000909104600160a060020a0316907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26005805475ffffffffffffffffffffffffffffffffffffffff000019169055565b600554620100009004600160a060020a031633146122df57600080fd5b60408051818152600f8054600260001961010060018416150201909116049282018390527f4f5dc3feea8c186b1481cfe57c28df8871a61e3be16f7d65c60504cfd63440679290918591859190819060208201906060830190879080156123875780601f1061235c57610100808354040283529160200191612387565b820191906000526020600020905b81548152906001019060200180831161236a57829003601f168201915b50508381038252848152602001858580828437604051920182900397509095505050505050a161173a600f8383615453565b60008181526015602090815260409182902080548351818402810184019094528084526060939283018282801561241957602002820191906000526020600020905b8154600160a060020a031681526001909101906020018083116123fb575b50505050509050919050565b600654600160a060020a031681565b60125462010000900460ff1681565b600561244f33826149ed565b151561245a57600080fd5b600160a060020a03841660009081526002602090815260408083203384529091529020548311156124d5576040805160e560020a62461bcd02815260206004820152600e60248201527f56616c756520746f6f2068696768000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0384166000908152600260209081526040808320338452909152902054612509908463ffffffff61488416565b600160a060020a0385166000908152600260209081526040808320338452909152902055612538848484614896565b151561258e576040805160e560020a62461bcd02815260206004820152600c60248201527f4275726e20696e76616c69640000000000000000000000000000000000000000604482015290519081900360640190fd5b50505050565b6000805b600160005260136020527f4155c2f711f2cdd34f8262ab8fb9b7020a700fe7b6948222152f7670d1fdf34d5481101561272d576001600090815260136020527f4155c2f711f2cdd34f8262ab8fb9b7020a700fe7b6948222152f7670d1fdf34d805460149291908490811061260957fe5b6000918252602080832090910154600160a060020a0316835282019290925260400190206002015460ff60a060020a90910416151561272557600160005260136020908152604080517f84c0b0ef0000000000000000000000000000000000000000000000000000000081527f4155c2f711f2cdd34f8262ab8fb9b7020a700fe7b6948222152f7670d1fdf34d6004820152600160a060020a0380891660248301528716604482015260648101869052905173220f27e198d0dbaf823e677b52374ae46f4cc71b926384c0b0ef9260848082019391829003018186803b1580156126f257600080fd5b505af4158015612706573d6000803e3d6000fd5b505050506040513d602081101561271c57600080fd5b50519150612732565b600101612598565b600091505b509392505050565b604080518082018252601881527f64697361626c65436f6e74726f6c6c6572416c6c6f7765640000000000000000602080830191825260095493517f2f0019f2000000000000000000000000000000000000000000000000000000008152600481019182528351602482015283519394600160a060020a031693632f0019f29386939283926044909101919080838360005b838110156127e45781810151838201526020016127cc565b50505050905090810190601f1680156128115780820380516001836020036101000a031916815260200191505b5092505050602060405180830381600087803b15801561283057600080fd5b505af1158015612844573d6000803e3d6000fd5b505050506040513d602081101561285a57600080fd5b5051151561286757600080fd5b600554620100009004600160a060020a0316331461288457600080fd5b60125462010000900460ff161561289a57600080fd5b6012805476ffffffffffffffffffffffffffffffffffffffff0000001962ff00001990911662010000171690556040805142815290517f6d4b279f1788f74ba2f47792247cede2c5081366419a8d2e0d4b651182edbe6a9181900360200190a150565b600554620100009004600160a060020a031681565b600554620100009004600160a060020a0316331461292f57600080fd5b60125462010000900460ff161561294557600080fd5b601254604051600160a060020a03808416926301000000900416907f9fdb07212c6f92fd298affc4000712177664bc3c4cae5f61098d42da6d05be1e90600090a360128054600160a060020a0390921663010000000276ffffffffffffffffffffffffffffffffffffffff00000019909216919091179055565b6004805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610f765780601f10610f4b57610100808354040283529160200191610f76565b600d5490565b600554600090600390620100009004600160a060020a0316331415612c1f57601254610100900460ff1615612a9f576040805160e560020a62461bcd02815260206004820152600e60248201527f4d696e74696e672066726f7a656e000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0385161515612aff576040805160e560020a62461bcd02815260206004820152600d60248201527f496e766573746f72206973203000000000000000000000000000000000000000604482015290519081900360640190fd5b612b0c600086868661474b565b1515612b50576040805160e560020a62461bcd028152602060048201526010602482015260008051602061564a833981519152604482015290519081900360640190fd5b612b58614b88565b600154612b6b908563ffffffff614b7516565b600155600160a060020a038516600090815260208190526040902054612b97908563ffffffff614b7516565b600160a060020a03861660008181526020818152604091829020939093558051878152905191927f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe92918290030190a2604080518581529051600160a060020a0387169160009160008051602061566a8339815191529181900360200190a360019150612732565b612c2933826149ed565b1515612c3457600080fd5b601254610100900460ff1615612c94576040805160e560020a62461bcd02815260206004820152600e60248201527f4d696e74696e672066726f7a656e000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0385161515612cf4576040805160e560020a62461bcd02815260206004820152600d60248201527f496e766573746f72206973203000000000000000000000000000000000000000604482015290519081900360640190fd5b612d01600086868661474b565b1515612d45576040805160e560020a62461bcd028152602060048201526010602482015260008051602061564a833981519152604482015290519081900360640190fd5b612d4d614b88565b600154612d60908563ffffffff614b7516565b600155600160a060020a038516600090815260208190526040902054612d8c908563ffffffff614b7516565b600160a060020a03861660008181526020818152604091829020939093558051878152905191927f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe92918290030190a2604080518581529051600160a060020a0387169160009160008051602061566a8339815191529181900360200190a3506001949350505050565b601154600090821115612e2857600080fd5b73220f27e198d0dbaf823e677b52374ae46f4cc71b63b58ae1e2601784612e4d61114e565b6040518463ffffffff1660e060020a02815260040180848152602001838152602001828152602001935050505060206040518083038186803b158015612e9257600080fd5b505af4158015612ea6573d6000803e3d6000fd5b505050506040513d6020811015612ebc57600080fd5b505192915050565b600554606090600090819081908190620100009004600160a060020a03163314612eed57600080fd5b600160a060020a03861660009081526014602052604090206002015460a060020a900460ff161515612f69576040805160e560020a62461bcd02815260206004820152600c60248201527f4e6f742061726368697665640000000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a03868116600090815260146020526040902060010154161515612fdd576040805160e560020a62461bcd02815260206004820152600e60248201527f4d6f64756c65206d697373696e67000000000000000000000000000000000000604482015290519081900360640190fd5b7f51b49bea2e14e62ed58a6d53c2a092b2f7a04dc7d826763ae2fa3301b982fc286014600088600160a060020a0316600160a060020a031681526020019081526020016000206003018742604051808060200184600160a060020a0316600160a060020a0316815260200183815260200182810382528581815481526020019150805480156130a957602002820191906000526020600020906000905b825461010083900a900460ff1681526020600192830181810494850194909303909202910180841161307a5790505b505094505050505060405180910390a1600160a060020a0386166000908152601460209081526040918290206003018054835181840281018401909452808452909183018282801561313857602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116131095790505b50505050509450600093505b84518410156131ac576131a1858581518110151561315e57fe5b6020908102909101810151600160a060020a03891660009081526014909252604090912060040180548790811061319157fe5b9060005260206000200154614c08565b600190930192613144565b505050600160a060020a0383166000908152601460209081526040808320600581015490548085526015909352922080549060001982018281106131ec57fe5b6000918252602080832090910154848352601590915260409091208054600160a060020a03909216918590811061321f57fe5b60009182526020808320919091018054600160a060020a031916600160a060020a03949094169390931790925583815260159091526040902060001982019061326890826154cd565b50600019810183146132be5760008281526015602052604081208054859260149290918490811061329557fe5b6000918252602080832090910154600160a060020a031683528201929092526040019020600501555b600160a060020a0386166000908152601460205260408120818155600181018054600160a060020a031916905560028101805474ffffffffffffffffffffffffffffffffffffffffff191690559061331960038301826154f1565b613327600483016000615516565b60058201600090555050505050505050565b600554600090620100009004600160a060020a0316331461335957600080fd5b600160a060020a038316151561336e57600080fd5b50600554604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a036201000090930483166004820152602481018490529051849283169163a9059cbb9160448083019260209291908290030181600087803b1580156133e457600080fd5b505af11580156133f8573d6000803e3d6000fd5b505050506040513d602081101561340e57600080fd5b5051151561173a57600080fd5b601254610100900460ff1681565b600061186d83836020604051908101604052806000815250611231565b60ff811660009081526013602090815260409182902080548351818402810184019094528084526060939283018282801561241957602002820191906000526020600020908154600160a060020a031681526001909101906020018083116123fb5750505050509050919050565b6060600b60010180548060200260200160405190810160405280929190818152602001828054801561197657602002820191906000526020600020905b8154600160a060020a031681526001909101906020018083116134f1575050505050905090565b600160a060020a038181166000908152601460209081526040808320805460018201546002830154600390930180548551818802810188019096528086529697889788978897606097958416959384169460a060020a90940460ff16939290918391908301828280156135c857602002820191906000526020600020906000905b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116135995790505b505050505090509450945094509450945091939590929450565b600754600160a060020a031681565b601254610100900460ff1615613651576040805160e560020a62461bcd02815260206004820152600e60248201527f4d696e74696e672066726f7a656e000000000000000000000000000000000000604482015290519081900360640190fd5b604080518082018252601481527f667265657a654d696e74696e67416c6c6f776564000000000000000000000000602080830191825260095493517f2f0019f2000000000000000000000000000000000000000000000000000000008152600481019182528351602482015283519394600160a060020a031693632f0019f29386939283926044909101919080838360005b838110156136fb5781810151838201526020016136e3565b50505050905090810190601f1680156137285780820380516001836020036101000a031916815260200191505b5092505050602060405180830381600087803b15801561374757600080fd5b505af115801561375b573d6000803e3d6000fd5b505050506040513d602081101561377157600080fd5b5051151561377e57600080fd5b600554620100009004600160a060020a0316331461379b57600080fd5b6012805461ff0019166101001790556040805142815290517fac303fba0a810d910a7ec5499d828c1bdc0b91117ee0d547ff7c59ff4ae3f11b9181900360200190a150565b600954600160a060020a031681565b600854600160a060020a031681565b600f805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610f765780601f10610f4b57610100808354040283529160200191610f76565b336000908152600260209081526040808320600160a060020a038616845290915281205461388d908363ffffffff614b7516565b336000818152600260209081526040808320600160a060020a0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b600160a060020a03918216600090815260026020908152604080832093909416825291909152205490565b60125460ff1681565b60006139348585858561474b565b1515613978576040805160e560020a62461bcd028152602060048201526010602482015260008051602061564a833981519152604482015290519081900360640190fd5b613983858585614e13565b151561398e57600080fd5b506001949350505050565b60006139a9858585856000614f78565b95945050505050565b600554620100009004600160a060020a031633146139cf57600080fd5b6139d881615276565b50565b600554620100009004600160a060020a031633146139f857600080fd5b6006546040805160e060020a63bf40fac1028152602060048201819052600e60248301527f4d6f64756c65526567697374727900000000000000000000000000000000000060448301529151600160a060020a039093169263bf40fac1926064808401939192918290030181600087803b158015613a7557600080fd5b505af1158015613a89573d6000803e3d6000fd5b505050506040513d6020811015613a9f57600080fd5b505160078054600160a060020a031916600160a060020a039283161790556006546040805160e060020a63bf40fac1028152602060048201819052601560248301527f5365637572697479546f6b656e5265676973747279000000000000000000000060448301529151929093169263bf40fac192606480830193928290030181600087803b158015613b3157600080fd5b505af1158015613b45573d6000803e3d6000fd5b505050506040513d6020811015613b5b57600080fd5b505160088054600160a060020a031916600160a060020a039283161790556006546040805160e060020a63bf40fac1028152602060048201819052600f60248301527f466561747572655265676973747279000000000000000000000000000000000060448301529151929093169263bf40fac192606480830193928290030181600087803b158015613bed57600080fd5b505af1158015613c01573d6000803e3d6000fd5b505050506040513d6020811015613c1757600080fd5b505160098054600160a060020a031916600160a060020a039283161781556006546040805160e060020a63bf40fac102815260206004820181905260248201949094527f506f6c79546f6b656e000000000000000000000000000000000000000000000060448201529051919093169263bf40fac19260648083019391928290030181600087803b158015613cab57600080fd5b505af1158015613cbf573d6000803e3d6000fd5b505050506040513d6020811015613cd557600080fd5b5051600a8054600160a060020a031916600160a060020a03909216919091179055565b60006060600080600060606000600560029054906101000a9004600160a060020a0316600160a060020a031633600160a060020a0316141515613d3a57600080fd5b600554610100900460ff1615613d4f57600080fd5b6005805461ff001916610100179055600754604080517fdc659907000000000000000000000000000000000000000000000000000000008152600160a060020a038f811660048301529151919092169163dc65990791602480830192600092919082900301818387803b158015613dc557600080fd5b505af1158015613dd9573d6000803e3d6000fd5b505050508b965086600160a060020a031663b4579d606040518163ffffffff1660e060020a028152600401600060405180830381600087803b158015613e1e57600080fd5b505af1158015613e32573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613e5b57600080fd5b810190808051640100000000811115613e7357600080fd5b82016020810184811115613e8657600080fd5b8151856020820283011164010000000082111715613ea357600080fd5b5050929190505050955086600160a060020a031663a5e9d7c96040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015613eeb57600080fd5b505af1158015613eff573d6000803e3d6000fd5b505050506040513d6020811015613f1557600080fd5b5051945088851115613f71576040805160e560020a62461bcd02815260206004820152600c60248201527f496e76616c696420636f73740000000000000000000000000000000000000000604482015290519081900360640190fd5b600a54604080517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a038f81166004830152602482018990529151919092169163095ea7b39160448083019260209291908290030181600087803b158015613fe057600080fd5b505af1158015613ff4573d6000803e3d6000fd5b505050506040513d602081101561400a57600080fd5b50506040517e774360000000000000000000000000000000000000000000000000000000008152602060048201908152602482018c9052600160a060020a0389169162774360918e918e9190819060440184848082843782019150509350505050602060405180830381600087803b15801561408557600080fd5b505af1158015614099573d6000803e3d6000fd5b505050506040513d60208110156140af57600080fd5b5051600160a060020a038082166000908152601460205260409020600101549195501615614127576040805160e560020a62461bcd02815260206004820152600d60248201527f4d6f64756c652065786973747300000000000000000000000000000000000000604482015290519081900360640190fd5b600a54604080517f095ea7b3000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152602482018c90529151919092169163095ea7b39160448083019260209291908290030181600087803b15801561419657600080fd5b505af11580156141aa573d6000803e3d6000fd5b505050506040513d60208110156141c057600080fd5b5050604080517f17d7de7c0000000000000000000000000000000000000000000000000000000081529051600160a060020a038916916317d7de7c9160048083019260209291908290030181600087803b15801561421d57600080fd5b505af1158015614231573d6000803e3d6000fd5b505050506040513d602081101561424757600080fd5b505186516040805182815260208381028201019091529194508015614276578160200160208202803883390190505b509150600090505b85518110156143345760136000878381518110151561429957fe5b602090810290910181015160ff1682528101919091526040016000205482518390839081106142c457fe5b6020908102909101015285516013906000908890849081106142e257fe5b60209081029190910181015160ff168252818101929092526040016000908120805460018082018355918352929091209091018054600160a060020a031916600160a060020a0387161790550161427e565b60e0604051908101604052808460001916815260200185600160a060020a031681526020018d600160a060020a03168152602001600015158152602001878152602001838152602001601560008660001916600019168152602001908152602001600020805490508152506014600086600160a060020a0316600160a060020a031681526020019081526020016000206000820151816000019060001916905560208201518160010160006101000a815481600160a060020a030219169083600160a060020a0316021790555060408201518160020160006101000a815481600160a060020a030219169083600160a060020a0316021790555060608201518160020160146101000a81548160ff021916908315150217905550608082015181600301908051906020019061446a929190615534565b5060a082015180516144869160048401916020909101906155d6565b5060c082015181600501559050506015600084600019166000191681526020019081526020016000208490806001815401808255809150509060018203906000526020600020016000909192909190916101000a815481600160a060020a030219169083600160a060020a03160217905550507fa902846e90aed52d2fbbaeb545287d4605aa25564cab74181fab117022d9eeb986848e87898d426040518080602001886000191660001916815260200187600160a060020a0316600160a060020a0316815260200186600160a060020a0316600160a060020a03168152602001858152602001848152602001838152602001828103825289818151815260200191508051906020019060200280838360005b838110156145b1578181015183820152602001614599565b505050509050019850505050505050505060405180910390a150506005805461ff001916905550505050505050505050565b60125463010000009004600160a060020a031681565b600554600090600490620100009004600160a060020a03163314156146a8576011546000191161462857600080fd5b6011805460019081018255601880549182018155600052427fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e9091018190559054604080519283525190917f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f919081900360200190a2601154915061108b565b6146b233826149ed565b15156146bd57600080fd5b601154600019116146cd57600080fd5b6011805460019081018255601880549182018155600052427fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e9091018190559054604080519283525190917f624ea167e477f9d39f7f4094b9dfe2e6346eb4a7aada54338db51abd554c4b9f919081900360200190a2505060115490565b6005546000908190610100900460ff161561476557600080fd5b6005805461ff00191661010017905561477f868686615302565b61478d868686866001614f78565b9050614798866153ce565b6147a1856153ce565b6005805461ff001916905595945050505050565b6000600160a060020a03831615156147cc57600080fd5b336000908152602081905260409020548211156147e857600080fd5b33600090815260208190526040902054614808908363ffffffff61488416565b3360009081526020819052604080822092909255600160a060020a0385168152205461483a908363ffffffff614b7516565b600160a060020a0384166000818152602081815260409182902093909355805185815290519192339260008051602061566a8339815191529281900390910190a350600192915050565b60008282111561489057fe5b50900390565b600160a060020a0383166000908152602081905260408120548190841115614908576040805160e560020a62461bcd02815260206004820152600e60248201527f56616c756520746f6f2068696768000000000000000000000000000000000000604482015290519081900360640190fd5b614915856000868661474b565b905061491f614b88565b600160a060020a038516600090815260208190526040902054614948908563ffffffff61488416565b600160a060020a038616600090815260208190526040902055600154614974908563ffffffff61488416565b600155604080518581529051600160a060020a038716917f919f7e2092ffcc9d09f599be18d8152860b0c054df788a33bc549cdd9d0f15b1919081900360200190a2604080518581529051600091600160a060020a0388169160008051602061566a8339815191529181900360200190a3949350505050565b600160a060020a0380831660008181526014602052604081206001015490928392911614614a65576040805160e560020a62461bcd02815260206004820152600d60248201527f57726f6e67206164647265737300000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a03841660009081526014602052604090206002015460a060020a900460ff1615614ae0576040805160e560020a62461bcd02815260206004820152600f60248201527f4d6f64756c652061726368697665640000000000000000000000000000000000604482015290519081900360640190fd5b5060005b600160a060020a038416600090815260146020526040902060030154811015614b6b57600160a060020a0384166000908152601460205260409020600301805460ff8516919083908110614b3457fe5b60009182526020918290209181049091015460ff601f9092166101000a9004161415614b635760019150612216565b600101614ae4565b5060009392505050565b81810182811015614b8257fe5b92915050565b73220f27e198d0dbaf823e677b52374ae46f4cc71b6307c20d976017614bac61114e565b6011546040518463ffffffff1660e060020a02815260040180848152602001838152602001828152602001935050505060006040518083038186803b158015614bf457600080fd5b505af415801561258e573d6000803e3d6000fd5b60ff821660009081526013602052604081208054916060916000198401848110614c2e57fe5b600091825260208083209091015460ff88168352601390915260409091208054600160a060020a039092169186908110614c6457fe5b60009182526020808320919091018054600160a060020a031916600160a060020a03949094169390931790925560ff87168152601390915260409020600019840190614cb090826154cd565b50600019830184146111475760ff851660009081526013602052604081208054601492919087908110614cdf57fe5b6000918252602080832090910154600160a060020a03168352828101939093526040918201902060030180548251818502810185019093528083529192909190830182828015614d6c57602002820191906000526020600020906000905b825461010083900a900460ff16815260206001928301818104948501949093039092029101808411614d3d5790505b50505050509150600090505b8151811015611147578460ff168282815181101515614d9357fe5b9060200190602002015160ff161415614e0b5760ff8516600090815260136020526040812080548692601492909184908110614dcb57fe5b6000918252602080832090910154600160a060020a031683528201929092526040019020600401805483908110614dfe57fe5b6000918252602090912001555b600101614d78565b6000600160a060020a0383161515614e2a57600080fd5b600160a060020a038416600090815260208190526040902054821115614e4f57600080fd5b600160a060020a0384166000908152600260209081526040808320338452909152902054821115614e7f57600080fd5b600160a060020a038416600090815260208190526040902054614ea8908363ffffffff61488416565b600160a060020a038086166000908152602081905260408082209390935590851681522054614edd908363ffffffff614b7516565b600160a060020a03808516600090815260208181526040808320949094559187168152600282528281203382529091522054614f1f908363ffffffff61488416565b600160a060020a038086166000818152600260209081526040808320338452825291829020949094558051868152905192871693919260008051602061566a833981519152929181900390910190a35060019392505050565b6000806000806000806000808a60105481811515614f9257fe5b0615614fe8576040805160e560020a62461bcd02815260206004820152601360248201527f496e76616c6964206772616e756c617269747900000000000000000000000000604482015290519081900360640190fd5b60125460ff1615156152605760009750600096506000955060009450600092505b600260005260136020527f0b9d2c0c271bb30544eb78c59bdaebdae2728e5f65814c07768a0abe90ed19235483101561523257600260005260136020527f0b9d2c0c271bb30544eb78c59bdaebdae2728e5f65814c07768a0abe90ed192380548490811061507357fe5b6000918252602080832090910154600160a060020a0316808352601490915260409091206002015490945060ff60a060020a909104161515615227576001945083600160a060020a031663de6ee1bc8f8f8f8f8f6040518663ffffffff1660e060020a0281526004018086600160a060020a0316600160a060020a0316815260200185600160a060020a0316600160a060020a031681526020018481526020018060200183151515158152602001828103825284818151815260200191508051906020019080838360005b8381101561515657818101518382015260200161513e565b50505050905090810190601f1680156151835780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156151a657600080fd5b505af11580156151ba573d6000803e3d6000fd5b505050506040513d60208110156151d057600080fd5b5051915060008260038111156151e257fe5b14156151f15760019750615227565b60028260038111156151ff57fe5b141561520e5760019650615227565b600382600381111561521c57fe5b141561522757600195505b600190920191615009565b8461523e576001615259565b85615256578761524e5786615251565b60005b615259565b60015b9850615265565b600098505b505050505050505095945050505050565b600160a060020a038116151561528b57600080fd5b600554604051600160a060020a038084169262010000900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a360058054600160a060020a03909216620100000275ffffffffffffffffffffffffffffffffffffffff000019909216919091179055565b73220f27e198d0dbaf823e677b52374ae46f4cc71b6317dd222c600b85858561532a8861222c565b6153338a61222c565b6040518763ffffffff1660e060020a0281526004018087815260200186600160a060020a0316600160a060020a0316815260200185600160a060020a0316600160a060020a03168152602001848152602001838152602001828152602001965050505050505060006040518083038186803b1580156153b157600080fd5b505af41580156153c5573d6000803e3d6000fd5b50505050505050565b600160a060020a038116600090815260166020526040902073220f27e198d0dbaf823e677b52374ae46f4cc71b906307c20d979061540b8461222c565b6011546040518463ffffffff1660e060020a02815260040180848152602001838152602001828152602001935050505060006040518083038186803b15801561113357600080fd5b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106154945782800160ff198235161785556154c1565b828001600101855582156154c1579182015b828111156154c15782358255916020019190600101906154a6565b5061108b929150615611565b81548183558181111561173a5760008381526020902061173a918101908301615611565b50805460008255601f0160209004906000526020600020908101906139d89190615611565b50805460008255906000526020600020908101906139d89190615611565b82805482825590600052602060002090601f016020900481019282156155ca5791602002820160005b8382111561559b57835183826101000a81548160ff021916908360ff160217905550926020019260010160208160000104928301926001030261555d565b80156155c85782816101000a81549060ff021916905560010160208160000104928301926001030261559b565b505b5061108b92915061562b565b8280548282559060005260206000209081019282156154c1579160200282015b828111156154c15782518255916020019190600101906155f6565b61115291905b8082111561108b5760008155600101615617565b61115291905b8082111561108b57805460ff1916815560010161563156005472616e7366657220696e76616c696400000000000000000000000000000000ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a72305820fd8a7c73ca77a4463586f860b26876199315b2a3308bd5450c398a9952978cf4002900000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000140000000000000000000000000dfabf3e4793cd30affb47ab6fa4cf4eef26bbc27000000000000000000000000000000000000000000000000000000000000000161000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000000


   Library Used
TokenLib : 0x220f27e198d0dbaf823e677b52374ae46f4cc71b

   Swarm Source:
bzzr://fd8a7c73ca77a4463586f860b26876199315b2a3308bd5450c398a9952978cf4
Block Age Transaction Difficulty GasUsed Reward
Block Age Uncle Number Difficulty GasUsed Reward
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.