ETH Price: $2,648.31 (+1.59%)
Gas: 1 Gwei

Contract

0xd077c09A7E65C4Cca490a776D5e395fB4fE7179A
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Close Data Respo...79824962019-06-18 13:14:541880 days ago1560863694IN
0xd077c09A...B4fE7179A
0 ETH0.000892589
Add Data Respons...79824922019-06-18 13:13:561880 days ago1560863636IN
0xd077c09A...B4fE7179A
0 ETH0.002577019
Add Data Respons...79824592019-06-18 13:06:501880 days ago1560863210IN
0xd077c09A...B4fE7179A
0 ETH0.002577019
Add Data Respons...79824522019-06-18 13:05:041880 days ago1560863104IN
0xd077c09A...B4fE7179A
0 ETH0.002711439
Add Data Respons...79821482019-06-18 11:56:501880 days ago1560859010IN
0xd077c09A...B4fE7179A
0 ETH0.002577199
Add Data Respons...79816652019-06-18 10:07:051880 days ago1560852425IN
0xd077c09A...B4fE7179A
0 ETH0.002712019
Add Data Respons...79813572019-06-18 8:56:371880 days ago1560848197IN
0xd077c09A...B4fE7179A
0 ETH0.002577019
Add Data Respons...79813572019-06-18 8:56:371880 days ago1560848197IN
0xd077c09A...B4fE7179A
0 ETH0.002576619
Add Data Respons...79813552019-06-18 8:55:511880 days ago1560848151IN
0xd077c09A...B4fE7179A
0 ETH0.002712199
Add Data Respons...79811192019-06-18 7:58:241880 days ago1560844704IN
0xd077c09A...B4fE7179A
0 ETH0.002576439
Add Data Respons...79811182019-06-18 7:58:211880 days ago1560844701IN
0xd077c09A...B4fE7179A
0 ETH0.002576439
Close Data Respo...79807082019-06-18 6:33:431880 days ago1560839623IN
0xd077c09A...B4fE7179A
0 ETH0.000892769
Close Data Respo...79807072019-06-18 6:33:261880 days ago1560839606IN
0xd077c09A...B4fE7179A
0 ETH0.001027769
Add Data Respons...79807042019-06-18 6:32:491880 days ago1560839569IN
0xd077c09A...B4fE7179A
0 ETH0.002576439
Add Data Respons...79807042019-06-18 6:32:491880 days ago1560839569IN
0xd077c09A...B4fE7179A
0 ETH0.002576619
Add Data Respons...79806982019-06-18 6:31:401880 days ago1560839500IN
0xd077c09A...B4fE7179A
0 ETH0.002711439
Add Data Respons...79806082019-06-18 6:11:181880 days ago1560838278IN
0xd077c09A...B4fE7179A
0 ETH0.002577019
Add Data Respons...79803832019-06-18 5:16:451881 days ago1560835005IN
0xd077c09A...B4fE7179A
0 ETH0.002577199
Add Data Respons...79803682019-06-18 5:13:581881 days ago1560834838IN
0xd077c09A...B4fE7179A
0 ETH0.002577199
Add Data Respons...79803662019-06-18 5:13:351881 days ago1560834815IN
0xd077c09A...B4fE7179A
0 ETH0.002577019
Add Data Respons...79803452019-06-18 5:08:111881 days ago1560834491IN
0xd077c09A...B4fE7179A
0 ETH0.002577199
Add Data Respons...79803412019-06-18 5:07:391881 days ago1560834459IN
0xd077c09A...B4fE7179A
0 ETH0.002577199
Add Data Respons...79803392019-06-18 5:06:461881 days ago1560834406IN
0xd077c09A...B4fE7179A
0 ETH0.002577019
Add Data Respons...79801652019-06-18 4:26:571881 days ago1560832017IN
0xd077c09A...B4fE7179A
0 ETH0.002577199
Add Data Respons...79801162019-06-18 4:14:111881 days ago1560831251IN
0xd077c09A...B4fE7179A
0 ETH0.002577019
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
79526212019-06-13 20:59:561885 days ago1560459596
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
79120452019-06-07 12:31:231891 days ago1559910683
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78550602019-05-29 14:32:491900 days ago1559140369
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78416732019-05-27 12:20:401902 days ago1558959640
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78416442019-05-27 12:13:321902 days ago1558959212
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78161642019-05-23 13:10:381906 days ago1558617038
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78161552019-05-23 13:08:521906 days ago1558616932
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78161512019-05-23 13:07:471906 days ago1558616867
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78161492019-05-23 13:07:291906 days ago1558616849
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78161462019-05-23 13:07:001906 days ago1558616820
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78161392019-05-23 13:05:241906 days ago1558616724
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78161302019-05-23 13:01:121906 days ago1558616472
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78161242019-05-23 12:59:531906 days ago1558616393
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78161232019-05-23 12:59:521906 days ago1558616392
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78161192019-05-23 12:58:531906 days ago1558616333
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78157882019-05-23 11:47:211906 days ago1558612041
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78157722019-05-23 11:43:461906 days ago1558611826
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78157622019-05-23 11:40:211906 days ago1558611621
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78101702019-05-22 14:29:401907 days ago1558535380
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
78048692019-05-21 18:47:121908 days ago1558464432
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
77216972019-05-08 18:38:011921 days ago1557340681
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
76899022019-05-03 19:32:471926 days ago1556911967
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
76898912019-05-03 19:29:301926 days ago1556911770
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
76898762019-05-03 19:25:121926 days ago1556911512
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
76706882019-04-30 19:41:101929 days ago1556653270
0xd077c09A...B4fE7179A
 Contract Creation0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DataExchange

Compiler Version
v0.4.24+commit.e67f0147

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2018-10-11
*/

pragma solidity ^0.4.24;

/**
 * @title Eliptic curve signature operations
 *
 * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
 *
 * TODO Remove this library once solidity supports passing a signature to ecrecover.
 * See https://github.com/ethereum/solidity/issues/864
 *
 */

library ECRecovery {

  /**
   * @dev Recover signer address from a message by using their signature
   * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address.
   * @param sig bytes signature, the signature is generated using web3.eth.sign()
   */
  function recover(bytes32 hash, bytes sig)
    internal
    pure
    returns (address)
  {
    bytes32 r;
    bytes32 s;
    uint8 v;

    // Check the signature length
    if (sig.length != 65) {
      return (address(0));
    }

    // Divide the signature in r, s and v variables
    // ecrecover takes the signature parameters, and the only way to get them
    // currently is to use assembly.
    // solium-disable-next-line security/no-inline-assembly
    assembly {
      r := mload(add(sig, 32))
      s := mload(add(sig, 64))
      v := byte(0, mload(add(sig, 96)))
    }

    // Version of signature should be 27 or 28, but 0 and 1 are also possible versions
    if (v < 27) {
      v += 27;
    }

    // If the version is correct return the signer address
    if (v != 27 && v != 28) {
      return (address(0));
    } else {
      // solium-disable-next-line arg-overflow
      return ecrecover(hash, v, r, s);
    }
  }

  /**
   * toEthSignedMessageHash
   * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:"
   * @dev and hash the result
   */
  function toEthSignedMessageHash(bytes32 hash)
    internal
    pure
    returns (bytes32)
  {
    // 32 is the length in bytes of hash,
    // enforced by the type signature above
    return keccak256(
      "\x19Ethereum Signed Message:\n32",
      hash
    );
  }
}

/**
 * @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 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 TokenDestructible:
 * @author Remco Bloemen <remco@2π.com>
 * @dev Base contract that can be destroyed by owner. All funds in contract including
 * listed tokens will be sent to the owner.
 */
contract TokenDestructible is Ownable {

  constructor() public payable { }

  /**
   * @notice Terminate contract and refund to owner
   * @param tokens List of addresses of ERC20 or ERC20Basic token contracts to
   refund.
   * @notice The called token contracts could try to re-enter this contract. Only
   supply token contracts you trust.
   */
  function destroy(address[] tokens) onlyOwner public {

    // Transfer tokens to owner
    for (uint256 i = 0; i < tokens.length; i++) {
      ERC20Basic token = ERC20Basic(tokens[i]);
      uint256 balance = token.balanceOf(this);
      token.transfer(owner, balance);
    }

    // Transfer Eth to owner and terminate contract
    selfdestruct(owner);
  }
}

/**
 * @title Pausable
 * @dev Base contract which allows children to implement an emergency stop mechanism.
 */
contract Pausable is Ownable {
  event Pause();
  event Unpause();

  bool public paused = false;


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

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

  /**
   * @dev called by the owner to pause, triggers stopped state
   */
  function pause() onlyOwner whenNotPaused public {
    paused = true;
    emit Pause();
  }

  /**
   * @dev called by the owner to unpause, returns to normal state
   */
  function unpause() onlyOwner whenPaused public {
    paused = false;
    emit Unpause();
  }
}


/**
 * @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 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 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 WIBToken
 * @author Wibson Development Team <[email protected]>
 * @notice Wibson Oficial Token, this is an ERC20 standard compliant token.
 * @dev WIBToken token has an initial supply of 9 billion tokens with 9 decimals.
 */
contract WIBToken is StandardToken {
  string public constant name = "WIBSON"; // solium-disable-line uppercase
  string public constant symbol = "WIB"; // solium-disable-line uppercase
  uint8 public constant decimals = 9; // solium-disable-line uppercase

  // solium-disable-next-line zeppelin/no-arithmetic-operations
  uint256 public constant INITIAL_SUPPLY = 9000000000 * (10 ** uint256(decimals));

  constructor() public {
    totalSupply_ = INITIAL_SUPPLY;
    balances[msg.sender] = INITIAL_SUPPLY;
    emit Transfer(address(0), msg.sender, INITIAL_SUPPLY);
  }
}


/**
 * @title DataOrder
 * @author Wibson Development Team <[email protected]>
 * @notice `DataOrder` is the contract between a given buyer and a set of sellers.
 *         This holds the information about the "deal" between them and how the
 *         transaction has evolved.
 */
contract DataOrder is Ownable {
  modifier validAddress(address addr) {
    require(addr != address(0));
    require(addr != address(this));
    _;
  }

  enum OrderStatus {
    OrderCreated,
    NotaryAdded,
    TransactionCompleted
  }

  enum DataResponseStatus {
    DataResponseAdded,
    RefundedToBuyer,
    TransactionCompleted
  }

  // --- Notary Information ---
  struct NotaryInfo {
    uint256 responsesPercentage;
    uint256 notarizationFee;
    string notarizationTermsOfService;
    uint32 addedAt;
  }

  // --- Seller Information ---
  struct SellerInfo {
    address notary;
    string dataHash;
    uint32 createdAt;
    uint32 closedAt;
    DataResponseStatus status;
  }

  address public buyer;
  string public filters;
  string public dataRequest;
  uint256 public price;
  string public termsAndConditions;
  string public buyerURL;
  string public buyerPublicKey;
  uint32 public createdAt;
  uint32 public transactionCompletedAt;
  OrderStatus public orderStatus;

  mapping(address => SellerInfo) public sellerInfo;
  mapping(address => NotaryInfo) internal notaryInfo;

  address[] public sellers;
  address[] public notaries;

  /**
   * @notice Contract's constructor.
   * @param _buyer Buyer address
   * @param _filters Target audience of the order.
   * @param _dataRequest Requested data type (Geolocation, Facebook, etc).
   * @param _price Price per added Data Response.
   * @param _termsAndConditions Copy of the terms and conditions for the order.
   * @param _buyerURL Public URL of the buyer where the data must be sent.
   * @param _buyerPublicKey Public Key of the buyer, which will be used to encrypt the
   *        data to be sent.
   */
  constructor(
    address _buyer,
    string _filters,
    string _dataRequest,
    uint256 _price,
    string _termsAndConditions,
    string _buyerURL,
    string _buyerPublicKey
  ) public validAddress(_buyer) {
    require(bytes(_buyerURL).length > 0);
    require(bytes(_buyerPublicKey).length > 0);

    buyer = _buyer;
    filters = _filters;
    dataRequest = _dataRequest;
    price = _price;
    termsAndConditions = _termsAndConditions;
    buyerURL = _buyerURL;
    buyerPublicKey = _buyerPublicKey;
    orderStatus = OrderStatus.OrderCreated;
    createdAt = uint32(block.timestamp);
    transactionCompletedAt = 0;
  }

  /**
   * @notice Adds a notary to the Data Order.
   * @param notary Notary's address.
   * @param responsesPercentage Percentage of DataResponses to audit per DataOrder.
            Value must be between 0 and 100.
   * @param notarizationFee Fee to be charged per validation done.
   * @param notarizationTermsOfService Notary's terms and conditions for the order.
   * @return true if the Notary was added successfully, reverts otherwise.
   */
  function addNotary(
    address notary,
    uint256 responsesPercentage,
    uint256 notarizationFee,
    string notarizationTermsOfService
  ) public onlyOwner validAddress(notary) returns (bool) {
    require(transactionCompletedAt == 0);
    require(responsesPercentage <= 100);
    require(!hasNotaryBeenAdded(notary));

    notaryInfo[notary] = NotaryInfo(
      responsesPercentage,
      notarizationFee,
      notarizationTermsOfService,
      uint32(block.timestamp)
    );
    notaries.push(notary);
    orderStatus = OrderStatus.NotaryAdded;
    return true;
  }

   /**
    * @notice Adds a new DataResponse.
    * @param seller Address of the Seller.
    * @param notary Notary address that the Seller chooses to use as notary,
    *        this must be one within the allowed notaries and within the
    *         DataOrder's notaries.
    * @param dataHash Hash of the data that must be sent, this is a SHA256.
    * @return true if the DataResponse was added successfully, reverts otherwise.
    */
  function addDataResponse(
    address seller,
    address notary,
    string dataHash
  ) public onlyOwner validAddress(seller) validAddress(notary) returns (bool) {
    require(orderStatus == OrderStatus.NotaryAdded);
    require(transactionCompletedAt == 0);
    require(!hasSellerBeenAccepted(seller));
    require(hasNotaryBeenAdded(notary));

    sellerInfo[seller] = SellerInfo(
      notary,
      dataHash,
      uint32(block.timestamp),
      0,
      DataResponseStatus.DataResponseAdded
    );

    sellers.push(seller);

    return true;
  }

  /**
   * @notice Closes a DataResponse.
   * @dev Once the buyer receives the seller's data and checks that it is valid
   *      or not, he must signal  DataResponse as completed.
   * @param seller Seller address.
   * @param transactionCompleted True, if the seller got paid for his/her data.
   * @return true if DataResponse was successfully closed, reverts otherwise.
   */
  function closeDataResponse(
    address seller,
    bool transactionCompleted
  ) public onlyOwner validAddress(seller) returns (bool) {
    require(orderStatus != OrderStatus.TransactionCompleted);
    require(transactionCompletedAt == 0);
    require(hasSellerBeenAccepted(seller));
    require(sellerInfo[seller].status == DataResponseStatus.DataResponseAdded);

    sellerInfo[seller].status = transactionCompleted
      ? DataResponseStatus.TransactionCompleted
      : DataResponseStatus.RefundedToBuyer;
    sellerInfo[seller].closedAt = uint32(block.timestamp);
    return true;
  }

  /**
   * @notice Closes the Data order.
   * @dev Once the DataOrder is closed it will no longer accept new DataResponses.
   * @return true if the DataOrder was successfully closed, reverts otherwise.
   */
  function close() public onlyOwner returns (bool) {
    require(orderStatus != OrderStatus.TransactionCompleted);
    require(transactionCompletedAt == 0);
    orderStatus = OrderStatus.TransactionCompleted;
    transactionCompletedAt = uint32(block.timestamp);
    return true;
  }

  /**
   * @notice Checks if a DataResponse for a given seller has been accepted.
   * @param seller Seller address.
   * @return true if the DataResponse was accepted, false otherwise.
   */
  function hasSellerBeenAccepted(
    address seller
  ) public view validAddress(seller) returns (bool) {
    return sellerInfo[seller].createdAt != 0;
  }

  /**
   * @notice Checks if the given notary was added to notarize this DataOrder.
   * @param notary Notary address to check.
   * @return true if the Notary was added, false otherwise.
   */
  function hasNotaryBeenAdded(
    address notary
  ) public view validAddress(notary) returns (bool) {
    return notaryInfo[notary].addedAt != 0;
  }

  /**
   * @notice Gets the notary information.
   * @param notary Notary address to get info for.
   * @return Notary information (address, responsesPercentage, notarizationFee,
   *         notarizationTermsOfService, addedAt)
   */
  function getNotaryInfo(
    address notary
  ) public view validAddress(notary) returns (
    address,
    uint256,
    uint256,
    string,
    uint32
  ) {
    require(hasNotaryBeenAdded(notary));
    NotaryInfo memory info = notaryInfo[notary];
    return (
      notary,
      info.responsesPercentage,
      info.notarizationFee,
      info.notarizationTermsOfService,
      uint32(info.addedAt)
    );
  }

  /**
   * @notice Gets the seller information.
   * @param seller Seller address to get info for.
   * @return Seller information (address, notary, dataHash, createdAt, closedAt,
   *         status)
   */
  function getSellerInfo(
    address seller
  ) public view validAddress(seller) returns (
    address,
    address,
    string,
    uint32,
    uint32,
    bytes32
  ) {
    require(hasSellerBeenAccepted(seller));
    SellerInfo memory info = sellerInfo[seller];
    return (
      seller,
      info.notary,
      info.dataHash,
      uint32(info.createdAt),
      uint32(info.closedAt),
      getDataResponseStatusAsString(info.status)
    );
  }

  /**
   * @notice Gets the selected notary for the given seller.
   * @param seller Seller address.
   * @return Address of the notary assigned to the given seller.
   */
  function getNotaryForSeller(
    address seller
  ) public view validAddress(seller) returns (address) {
    require(hasSellerBeenAccepted(seller));
    SellerInfo memory info = sellerInfo[seller];
    return info.notary;
  }

  function getDataResponseStatusAsString(
    DataResponseStatus drs
  ) internal pure returns (bytes32) {
    if (drs == DataResponseStatus.DataResponseAdded) {
      return bytes32("DataResponseAdded");
    }

    if (drs == DataResponseStatus.RefundedToBuyer) {
      return bytes32("RefundedToBuyer");
    }

    if (drs == DataResponseStatus.TransactionCompleted) {
      return bytes32("TransactionCompleted");
    }

    throw; // solium-disable-line security/no-throw
  }

}


/**
 * @title MultiMap
 * @author Wibson Development Team <[email protected]>
 * @notice An address `MultiMap`.
 * @dev `MultiMap` is useful when you need to keep track of a set of addresses.
 */
library MultiMap {

  struct MapStorage {
    mapping(address => uint) addressToIndex;
    address[] addresses;
  }

  /**
   * @notice Retrieves a address from the given `MapStorage` using a index Key.
   * @param self `MapStorage` where the index must be searched.
   * @param index Index to find.
   * @return Address of the given Index.
   */
  function get(
    MapStorage storage self,
    uint index
  ) public view returns (address) {
    require(index < self.addresses.length);
    return self.addresses[index];
  }

  /**
   * @notice Checks if the given address exists in the storage.
   * @param self `MapStorage` where the key must be searched.
   * @param _key Address to find.
   * @return true if `_key` exists in the storage, false otherwise.
   */
  function exist(
    MapStorage storage self,
    address _key
  ) public view returns (bool) {
    if (_key != address(0)) {
      uint targetIndex = self.addressToIndex[_key];
      return targetIndex < self.addresses.length && self.addresses[targetIndex] == _key;
    } else {
      return false;
    }
  }

  /**
   * @notice Inserts a new address within the given storage.
   * @param self `MapStorage` where the key must be inserted.
   * @param _key Address to insert.
   * @return true if `_key` was added, reverts otherwise.
   */
  function insert(
    MapStorage storage self,
    address _key
  ) public returns (bool) {
    require(_key != address(0));
    if (exist(self, _key)) {
      return true;
    }

    self.addressToIndex[_key] = self.addresses.length;
    self.addresses.push(_key);

    return true;
  }

  /**
   * @notice Removes the given index from the storage.
   * @param self MapStorage` where the index lives.
   * @param index Index to remove.
   * @return true if address at `index` was removed, false otherwise.
   */
  function removeAt(MapStorage storage self, uint index) public returns (bool) {
    return remove(self, self.addresses[index]);
  }

  /**
   * @notice Removes the given address from the storage.
   * @param self `MapStorage` where the address lives.
   * @param _key Address to remove.
   * @return true if `_key` was removed, false otherwise.
   */
  function remove(MapStorage storage self, address _key) public returns (bool) {
    require(_key != address(0));
    if (!exist(self, _key)) {
      return false;
    }

    uint currentIndex = self.addressToIndex[_key];

    uint lastIndex = SafeMath.sub(self.addresses.length, 1);
    address lastAddress = self.addresses[lastIndex];
    self.addressToIndex[lastAddress] = currentIndex;
    self.addresses[currentIndex] = lastAddress;

    delete self.addresses[lastIndex];
    delete self.addressToIndex[_key];

    self.addresses.length--;
    return true;
  }

  /**
   * @notice Gets the current length of the Map.
   * @param self `MapStorage` to get the length from.
   * @return The length of the MultiMap.
   */
  function length(MapStorage storage self) public view returns (uint) {
    return self.addresses.length;
  }
}


/**
 * @title CryptoUtils
 * @author Wibson Development Team <[email protected]>
 * @notice Cryptographic utilities used by the Wibson protocol.
 * @dev In order to get the same hashes using `Web3` upon which the signatures
 *      are checked, you must use `web3.utils.soliditySha3` in v1.0 (or the
 *      homonymous function in the `web3-utils` package)
 *      http://web3js.readthedocs.io/en/1.0/web3-utils.html#utils-soliditysha3
 */
library CryptoUtils {

  /**
   * @notice Checks if the signature was created by the signer.
   * @param hash Hash of the data using the `keccak256` algorithm.
   * @param signer Signer address.
   * @param signature Signature over the hash.
   * @return true if `signer` is the one who signed the `hash`, false otherwise.
   */
  function isSignedBy(
    bytes32 hash,
    address signer,
    bytes signature
  ) private pure returns (bool) {
    require(signer != address(0));
    bytes32 prefixedHash = ECRecovery.toEthSignedMessageHash(hash);
    address recovered = ECRecovery.recover(prefixedHash, signature);
    return recovered == signer;
  }

  /**
   * @notice Checks if the notary's signature to be added to the DataOrder is valid.
   * @param order Order address.
   * @param notary Notary address.
   * @param responsesPercentage Percentage of DataResponses to audit per DataOrder.
   * @param notarizationFee Fee to be charged per validation done.
   * @param notarizationTermsOfService Notary terms and conditions for the order.
   * @param notarySignature Off-chain Notary signature.
   * @return true if `notarySignature` is valid, false otherwise.
   */
  function isNotaryAdditionValid(
    address order,
    address notary,
    uint256 responsesPercentage,
    uint256 notarizationFee,
    string notarizationTermsOfService,
    bytes notarySignature
  ) public pure returns (bool) {
    require(order != address(0));
    require(notary != address(0));
    bytes32 hash = keccak256(
      abi.encodePacked(
        order,
        responsesPercentage,
        notarizationFee,
        notarizationTermsOfService
      )
    );

    return isSignedBy(hash, notary, notarySignature);
  }

  /**
   * @notice Checks if the parameters passed correspond to the seller's signature used.
   * @param order Order address.
   * @param seller Seller address.
   * @param notary Notary address.
   * @param dataHash Hash of the data that must be sent, this is a SHA256.
   * @param signature Signature of DataResponse.
   * @return true if arguments are signed by the `seller`, false otherwise.
   */
  function isDataResponseValid(
    address order,
    address seller,
    address notary,
    string dataHash,
    bytes signature
  ) public pure returns (bool) {
    require(order != address(0));
    require(seller != address(0));
    require(notary != address(0));

    bytes memory packed = bytes(dataHash).length > 0
      ? abi.encodePacked(order, notary, dataHash)
      : abi.encodePacked(order, notary);

    bytes32 hash = keccak256(packed);
    return isSignedBy(hash, seller, signature);
  }

  /**
   * @notice Checks if the notary's signature to close the `DataResponse` is valid.
   * @param order Order address.
   * @param seller Seller address.
   * @param notary Notary address.
   * @param wasAudited Indicates whether the data was audited or not.
   * @param isDataValid Indicates the result of the audit, if happened.
   * @param notarySignature Off-chain Notary signature.
   * @return true if `notarySignature` is valid, false otherwise.
   */
  function isNotaryVeredictValid(
    address order,
    address seller,
    address notary,
    bool wasAudited,
    bool isDataValid,
    bytes notarySignature
  ) public pure returns (bool) {
    require(order != address(0));
    require(seller != address(0));
    require(notary != address(0));
    bytes32 hash = keccak256(
      abi.encodePacked(
        order,
        seller,
        wasAudited,
        isDataValid
      )
    );

    return isSignedBy(hash, notary, notarySignature);
  }
}



/**
 * @title DataExchange
 * @author Wibson Development Team <[email protected]>
 * @notice `DataExchange` is the core contract of the Wibson Protocol.
 *         This allows the creation, management, and tracking of DataOrders.
 * @dev This contract also contains some helper methods to access the data
 *      needed by the different parties involved in the Protocol.
 */
contract DataExchange is TokenDestructible, Pausable {
  using SafeMath for uint256;
  using MultiMap for MultiMap.MapStorage;

  event NotaryRegistered(address indexed notary);
  event NotaryUpdated(address indexed notary);
  event NotaryUnregistered(address indexed notary);

  event NewOrder(address indexed orderAddr);
  event NotaryAddedToOrder(address indexed orderAddr, address indexed notary);
  event DataAdded(address indexed orderAddr, address indexed seller);
  event TransactionCompleted(address indexed orderAddr, address indexed seller);
  event RefundedToBuyer(address indexed orderAddr, address indexed buyer);
  event OrderClosed(address indexed orderAddr);

  struct NotaryInfo {
    address addr;
    string name;
    string notaryUrl;
    string publicKey;
  }

  MultiMap.MapStorage openOrders;
  MultiMap.MapStorage allowedNotaries;

  mapping(address => address[]) public ordersBySeller;
  mapping(address => address[]) public ordersByNotary;
  mapping(address => address[]) public ordersByBuyer;
  mapping(address => NotaryInfo) internal notaryInfo;
  // Tracks the orders created by this contract.
  mapping(address => bool) private orders;

  // @dev buyerBalance Keeps track of the buyer's balance per order-seller.
  // TODO: Is there a better way to do this?
  mapping(
    address => mapping(address => mapping(address => uint256))
  ) public buyerBalance;

  // @dev buyerRemainingBudgetForAudits Keeps track of the buyer's remaining
  // budget from the initial one set on the `DataOrder`
  mapping(address => mapping(address => uint256)) public buyerRemainingBudgetForAudits;

  modifier validAddress(address addr) {
    require(addr != address(0));
    require(addr != address(this));
    _;
  }

  modifier isOrderLegit(address order) {
    require(orders[order]);
    _;
  }

  // @dev token A WIBToken implementation of an ERC20 standard token.
  WIBToken token;

  // @dev The minimum for initial budget for audits per `DataOrder`.
  uint256 public minimumInitialBudgetForAudits;

  /**
   * @notice Contract constructor.
   * @param tokenAddress Address of the WIBToken token address.
   * @param ownerAddress Address of the DataExchange owner.
   */
  constructor(
    address tokenAddress,
    address ownerAddress
  ) public validAddress(tokenAddress) validAddress(ownerAddress) {
    require(tokenAddress != ownerAddress);

    token = WIBToken(tokenAddress);
    minimumInitialBudgetForAudits = 0;
    transferOwnership(ownerAddress);
  }

  /**
   * @notice Registers a new notary or replaces an already existing one.
   * @dev At least one notary is needed to enable `DataExchange` operation.
   * @param notary Address of a Notary to add.
   * @param name Name Of the Notary.
   * @param notaryUrl Public URL of the notary where the data must be sent.
   * @param publicKey PublicKey used by the Notary.
   * @return true if the notary was successfully registered, reverts otherwise.
   */
  function registerNotary(
    address notary,
    string name,
    string notaryUrl,
    string publicKey
  ) public onlyOwner whenNotPaused validAddress(notary) returns (bool) {
    bool isNew = notaryInfo[notary].addr == address(0);

    require(allowedNotaries.insert(notary));
    notaryInfo[notary] = NotaryInfo(
      notary,
      name,
      notaryUrl,
      publicKey
    );

    if (isNew) {
      emit NotaryRegistered(notary);
    } else {
      emit NotaryUpdated(notary);
    }
    return true;
  }

  /**
   * @notice Unregisters an existing notary.
   * @param notary Address of a Notary to unregister.
   * @return true if the notary was successfully unregistered, reverts otherwise.
   */
  function unregisterNotary(
    address notary
  ) public onlyOwner whenNotPaused validAddress(notary) returns (bool) {
    require(allowedNotaries.remove(notary));

    emit NotaryUnregistered(notary);
    return true;
  }

  /**
   * @notice Sets the minimum initial budget for audits to be placed by a buyer
   * on DataOrder creation.
   * @dev The initial budget for audit is used as a preventive method to reduce
   *      spam DataOrders in the network.
   * @param _minimumInitialBudgetForAudits The new minimum for initial budget for
   * audits per DataOrder.
   * @return true if the value was successfully set, reverts otherwise.
   */
  function setMinimumInitialBudgetForAudits(
    uint256 _minimumInitialBudgetForAudits
  ) public onlyOwner whenNotPaused returns (bool) {
    minimumInitialBudgetForAudits = _minimumInitialBudgetForAudits;
    return true;
  }

  /**
   * @notice Creates a new DataOrder.
   * @dev The `msg.sender` will become the buyer of the order.
   * @param filters Target audience of the order.
   * @param dataRequest Requested data type (Geolocation, Facebook, etc).
   * @param price Price per added Data Response.
   * @param initialBudgetForAudits The initial budget set for future audits.
   * @param termsAndConditions Buyer's terms and conditions for the order.
   * @param buyerURL Public URL of the buyer where the data must be sent.
   * @param publicKey Public Key of the buyer, which will be used to encrypt the
   *        data to be sent.
   * @return The address of the newly created DataOrder. If the DataOrder could
   *         not be created, reverts.
   */
  function newOrder(
    string filters,
    string dataRequest,
    uint256 price,
    uint256 initialBudgetForAudits,
    string termsAndConditions,
    string buyerURL,
    string publicKey
  ) public whenNotPaused returns (address) {
    require(initialBudgetForAudits >= minimumInitialBudgetForAudits);
    require(token.allowance(msg.sender, this) >= initialBudgetForAudits);

    address newOrderAddr = new DataOrder(
      msg.sender,
      filters,
      dataRequest,
      price,
      termsAndConditions,
      buyerURL,
      publicKey
    );

    token.transferFrom(msg.sender, this, initialBudgetForAudits);
    buyerRemainingBudgetForAudits[msg.sender][newOrderAddr] = initialBudgetForAudits;

    ordersByBuyer[msg.sender].push(newOrderAddr);
    orders[newOrderAddr] = true;

    emit NewOrder(newOrderAddr);
    return newOrderAddr;
  }

  /**
   * @notice Adds a notary to the Data Order.
   * @dev The `msg.sender` must be the buyer.
   * @param orderAddr Order Address to accept notarize.
   * @param notary Notary address.
   * @param responsesPercentage Percentage of `DataResponses` to audit per DataOrder.
   *        Value must be between 0 and 100.
   * @param notarizationFee Fee to be charged per validation done.
   * @param notarizationTermsOfService Notary's terms and conditions for the order.
   * @param notarySignature Notary's signature over the other arguments.
   * @return true if the Notary was added successfully, reverts otherwise.
   */
  function addNotaryToOrder(
    address orderAddr,
    address notary,
    uint256 responsesPercentage,
    uint256 notarizationFee,
    string notarizationTermsOfService,
    bytes notarySignature
  ) public whenNotPaused isOrderLegit(orderAddr) validAddress(notary) returns (bool) {
    DataOrder order = DataOrder(orderAddr);
    address buyer = order.buyer();
    require(msg.sender == buyer);

    require(!order.hasNotaryBeenAdded(notary));
    require(allowedNotaries.exist(notary));

    require(
      CryptoUtils.isNotaryAdditionValid(
        orderAddr,
        notary,
        responsesPercentage,
        notarizationFee,
        notarizationTermsOfService,
        notarySignature
      )
    );

    bool okay = order.addNotary(
      notary,
      responsesPercentage,
      notarizationFee,
      notarizationTermsOfService
    );

    if (okay) {
      openOrders.insert(orderAddr);
      ordersByNotary[notary].push(orderAddr);
      emit NotaryAddedToOrder(order, notary);
    }
    return okay;
  }

  /**
   * @notice Adds a new DataResponse to the given order.
   * @dev 1. The `msg.sender` must be the buyer of the order.
   *      2. The buyer must allow the DataExchange to withdraw the price of the
   *         order.
   * @param orderAddr Order address where the DataResponse must be added.
   * @param seller Address of the Seller.
   * @param notary Notary address that the Seller chose to use as notarizer,
   *        this must be one within the allowed notaries and within the
   *        DataOrder's notaries.
   * @param dataHash Hash of the data that must be sent, this is a SHA256.
   * @param signature Signature of DataResponse.
   * @return true if the DataResponse was set successfully, reverts otherwise.
   */
  function addDataResponseToOrder(
    address orderAddr,
    address seller,
    address notary,
    string dataHash,
    bytes signature
  ) public whenNotPaused isOrderLegit(orderAddr) returns (bool) {
    DataOrder order = DataOrder(orderAddr);
    address buyer = order.buyer();
    require(msg.sender == buyer);
    allDistinct(
      [
        orderAddr,
        buyer,
        seller,
        notary,
        address(this)
      ]
    );
    require(order.hasNotaryBeenAdded(notary));

    require(
      CryptoUtils.isDataResponseValid(
        orderAddr,
        seller,
        notary,
        dataHash,
        signature
      )
    );

    bool okay = order.addDataResponse(
      seller,
      notary,
      dataHash
    );
    require(okay);

    chargeBuyer(order, seller);

    ordersBySeller[seller].push(orderAddr);
    emit DataAdded(order, seller);
    return true;
  }

  /**
   * @notice Closes a DataResponse.
   * @dev Once the buyer receives the seller's data and checks that it is valid
   *      or not, he must close the DataResponse signaling the result.
   *        1. This method requires an offline signature from the notary set in
   *           the DataResponse, which will indicate the audit result or if
   *           the data was not audited at all.
   *             - If the notary did not audit the data or it verifies that it was
   *               valid, funds will be sent to the Seller.
   *             - If the notary signals the data as invalid, funds will be
   *               handed back to the Buyer.
   *             - Otherwise, funds will be locked at the `DataExchange` contract
   *               until the issue is solved.
   *        2. This also works as a pause mechanism in case the system is
   *           working under abnormal scenarios while allowing the parties to keep
   *           exchanging information without losing their funds until the system
   *           is back up.
   *        3. The `msg.sender` must be the buyer or the notary in case the
   *           former does not show up. Only through the notary's signature it is
   *           decided who must receive the funds.
   * @param orderAddr Order address where the DataResponse belongs to.
   * @param seller Seller address.
   * @param wasAudited Indicates whether the data was audited or not.
   * @param isDataValid Indicates the result of the audit, if happened.
   * @param notarySignature Off-chain Notary signature
   * @return true if the DataResponse was successfully closed, reverts otherwise.
   */
  function closeDataResponse(
    address orderAddr,
    address seller,
    bool wasAudited,
    bool isDataValid,
    bytes notarySignature
  ) public whenNotPaused isOrderLegit(orderAddr) returns (bool) {
    DataOrder order = DataOrder(orderAddr);
    address buyer = order.buyer();
    require(order.hasSellerBeenAccepted(seller));

    address notary = order.getNotaryForSeller(seller);
    require(msg.sender == buyer || msg.sender == notary);
    require(
      CryptoUtils.isNotaryVeredictValid(
        orderAddr,
        seller,
        notary,
        wasAudited,
        isDataValid,
        notarySignature
      )
    );
    bool transactionCompleted = !wasAudited || isDataValid;
    require(order.closeDataResponse(seller, transactionCompleted));
    payPlayers(
      order,
      buyer,
      seller,
      notary,
      wasAudited,
      isDataValid
    );

    if (transactionCompleted) {
      emit TransactionCompleted(order, seller);
    } else {
      emit RefundedToBuyer(order, buyer);
    }
    return true;
  }

  /**
   * @notice Closes the DataOrder.
   * @dev Onces the data is closed it will no longer accept new DataResponses.
   *      The `msg.sender` must be the buyer of the order or the owner of the
   *      contract in a emergency case.
   * @param orderAddr Order address to close.
   * @return true if the DataOrder was successfully closed, reverts otherwise.
   */
  function closeOrder(
    address orderAddr
  ) public whenNotPaused isOrderLegit(orderAddr) returns (bool) {
    require(openOrders.exist(orderAddr));
    DataOrder order = DataOrder(orderAddr);
    address buyer = order.buyer();
    require(msg.sender == buyer || msg.sender == owner);

    bool okay = order.close();
    if (okay) {
      // remaining budget for audits go back to buyer.
      uint256 remainingBudget = buyerRemainingBudgetForAudits[buyer][order];
      buyerRemainingBudgetForAudits[buyer][order] = 0;
      require(token.transfer(buyer, remainingBudget));

      openOrders.remove(orderAddr);
      emit OrderClosed(orderAddr);
    }

    return okay;
  }

  /**
   * @notice Gets all the data orders associated with a notary.
   * @param notary Notary address to get orders for.
   * @return A list of DataOrder addresses.
   */
  function getOrdersForNotary(
    address notary
  ) public view validAddress(notary) returns (address[]) {
    return ordersByNotary[notary];
  }

  /**
   * @notice Gets all the data orders associated with a seller.
   * @param seller Seller address to get orders for.
   * @return List of DataOrder addresses.
   */
  function getOrdersForSeller(
    address seller
  ) public view validAddress(seller) returns (address[]) {
    return ordersBySeller[seller];
  }

  /**
   * @notice Gets all the data orders associated with a buyer.
   * @param buyer Buyer address to get orders for.
   * @return List of DataOrder addresses.
   */
  function getOrdersForBuyer(
    address buyer
  ) public view validAddress(buyer) returns (address[]) {
    return ordersByBuyer[buyer];
  }

  /**
   * @notice Gets all the open data orders, that is all the DataOrders that are
   *         still receiving new DataResponses.
   * @return List of DataOrder addresses.
   */
  function getOpenOrders() public view returns (address[]) {
    return openOrders.addresses;
  }

  /**
   * @dev Gets the list of allowed notaries.
   * @return List of notary addresses.
   */
  function getAllowedNotaries() public view returns (address[]) {
    return allowedNotaries.addresses;
  }

  /**
   * @dev Gets information about a give notary.
   * @param notary Notary address to get info for.
   * @return Notary information (address, name, notaryUrl, publicKey, isActive).
   */
  function getNotaryInfo(
    address notary
  ) public view validAddress(notary) returns (address, string, string, string, bool) {
    NotaryInfo memory info = notaryInfo[notary];

    return (
      info.addr,
      info.name,
      info.notaryUrl,
      info.publicKey,
      allowedNotaries.exist(notary)
    );
  }

  /**
   * @dev Requires that five addresses are distinct between themselves and zero.
   * @param addresses array of five addresses to explore.
   */
  function allDistinct(address[5] addresses) private pure {
    for (uint i = 0; i < addresses.length; i++) {
      require(addresses[i] != address(0));
      for (uint j = i + 1; j < addresses.length; j++) { // solium-disable-line zeppelin/no-arithmetic-operations
        require(addresses[i] != addresses[j]);
      }
    }
  }

  /**
   * @dev Charges a buyer the final charges for a given `DataResponse`.
   * @notice 1. Tokens are held in the DataExchange contract until players are paid.
   *         2. This function follows a basic invoice flow:
   *
   *               DataOrder price
   *            + Notarization fee
   *            ------------------
   *                 Total charges
   *            -  Prepaid charges (Minimum between Notarization fee and Buyer remaining budget)
   *            ------------------
   *                 Final charges
   *
   * @param order DataOrder to which the DataResponse applies.
   * @param seller Address of the Seller.
   */
  function chargeBuyer(DataOrder order, address seller) private whenNotPaused {
    address buyer = order.buyer();
    address notary = order.getNotaryForSeller(seller);
    uint256 remainingBudget = buyerRemainingBudgetForAudits[buyer][order];

    uint256 orderPrice = order.price();
    (,, uint256 notarizationFee,,) = order.getNotaryInfo(notary);
    uint256 totalCharges = orderPrice.add(notarizationFee);

    uint256 prePaid = Math.min256(notarizationFee, remainingBudget);
    uint256 finalCharges = totalCharges.sub(prePaid);

    buyerRemainingBudgetForAudits[buyer][order] = remainingBudget.sub(prePaid);
    require(token.transferFrom(buyer, this, finalCharges));

    // Bookkeeping of the available tokens paid by the Buyer and now in control
    // of the DataExchange takes into account the total charges (final + pre-paid)
    buyerBalance[buyer][order][seller] = buyerBalance[buyer][order][seller].add(totalCharges);
  }

  /**
   * @dev Pays the seller, notary and/or buyer according to the notary's veredict.
   * @param order DataOrder to which the payments apply.
   * @param buyer Address of the Buyer.
   * @param seller Address of the Seller.
   * @param notary Address of the Notary.
   * @param wasAudited Indicates whether the data was audited or not.
   * @param isDataValid Indicates the result of the audit, if happened.
   */
  function payPlayers(
    DataOrder order,
    address buyer,
    address seller,
    address notary,
    bool wasAudited,
    bool isDataValid
  ) private whenNotPaused {
    uint256 orderPrice = order.price();
    (,, uint256 notarizationFee,,) = order.getNotaryInfo(notary);
    uint256 totalCharges = orderPrice.add(notarizationFee);

    require(buyerBalance[buyer][order][seller] >= totalCharges);
    buyerBalance[buyer][order][seller] = buyerBalance[buyer][order][seller].sub(totalCharges);

    // if no notarization was done, notarization fee tokens go back to buyer.
    address notarizationFeeReceiver = wasAudited ? notary : buyer;

    // if no notarization was done or data is valid, tokens go to the seller
    address orderPriceReceiver = (!wasAudited || isDataValid) ? seller : buyer;

    require(token.transfer(notarizationFeeReceiver, notarizationFee));
    require(token.transfer(orderPriceReceiver, orderPrice));
  }

}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"name":"seller","type":"address"}],"name":"getOrdersForSeller","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"},{"name":"","type":"address"}],"name":"buyerBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"ordersByBuyer","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"buyerRemainingBudgetForAudits","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_minimumInitialBudgetForAudits","type":"uint256"}],"name":"setMinimumInitialBudgetForAudits","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"notary","type":"address"}],"name":"getNotaryInfo","outputs":[{"name":"","type":"address"},{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"orderAddr","type":"address"},{"name":"seller","type":"address"},{"name":"notary","type":"address"},{"name":"dataHash","type":"string"},{"name":"signature","type":"bytes"}],"name":"addDataResponseToOrder","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"notary","type":"address"}],"name":"getOrdersForNotary","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"orderAddr","type":"address"},{"name":"seller","type":"address"},{"name":"wasAudited","type":"bool"},{"name":"isDataValid","type":"bool"},{"name":"notarySignature","type":"bytes"}],"name":"closeDataResponse","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"pause","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":"orderAddr","type":"address"}],"name":"closeOrder","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"orderAddr","type":"address"},{"name":"notary","type":"address"},{"name":"responsesPercentage","type":"uint256"},{"name":"notarizationFee","type":"uint256"},{"name":"notarizationTermsOfService","type":"string"},{"name":"notarySignature","type":"bytes"}],"name":"addNotaryToOrder","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"buyer","type":"address"}],"name":"getOrdersForBuyer","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAllowedNotaries","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"ordersByNotary","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"tokens","type":"address[]"}],"name":"destroy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"notary","type":"address"},{"name":"name","type":"string"},{"name":"notaryUrl","type":"string"},{"name":"publicKey","type":"string"}],"name":"registerNotary","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"ordersBySeller","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getOpenOrders","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"filters","type":"string"},{"name":"dataRequest","type":"string"},{"name":"price","type":"uint256"},{"name":"initialBudgetForAudits","type":"uint256"},{"name":"termsAndConditions","type":"string"},{"name":"buyerURL","type":"string"},{"name":"publicKey","type":"string"}],"name":"newOrder","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"minimumInitialBudgetForAudits","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"notary","type":"address"}],"name":"unregisterNotary","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"tokenAddress","type":"address"},{"name":"ownerAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"notary","type":"address"}],"name":"NotaryRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"notary","type":"address"}],"name":"NotaryUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"notary","type":"address"}],"name":"NotaryUnregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"orderAddr","type":"address"}],"name":"NewOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"orderAddr","type":"address"},{"indexed":true,"name":"notary","type":"address"}],"name":"NotaryAddedToOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"orderAddr","type":"address"},{"indexed":true,"name":"seller","type":"address"}],"name":"DataAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"orderAddr","type":"address"},{"indexed":true,"name":"seller","type":"address"}],"name":"TransactionCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"orderAddr","type":"address"},{"indexed":true,"name":"buyer","type":"address"}],"name":"RefundedToBuyer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"orderAddr","type":"address"}],"name":"OrderClosed","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","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"}]

60806040526000805460a060020a60ff02191690553480156200002157600080fd5b506040516040806200587a83398101604052805160209091015160008054600160a060020a0319163317905581600160a060020a03811615156200006457600080fd5b600160a060020a0381163014156200007b57600080fd5b81600160a060020a03811615156200009257600080fd5b600160a060020a038116301415620000a957600080fd5b600160a060020a038481169084161415620000c357600080fd5b600c8054600160a060020a031916600160a060020a0386161790556000600d55620000f78364010000000062000101810204565b50505050620001a1565b600054600160a060020a031633146200011957600080fd5b6200012d8164010000000062000130810204565b50565b600160a060020a03811615156200014657600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360008054600160a060020a031916600160a060020a0392909216919091179055565b6156c980620001b16000396000f300608060405260043610620001615763ffffffff60e060020a6000350416630636d7ac8114620001665780630aa4b3be14620001dc578063319fa887146200021e578063373dfb1414620002615780633cedd004146200028b5780633f4ba83a14620002ba57806343ca78a214620002d457806352748cfe14620004695780635ac31e68146200051c5780635c975abb146200054057806360909c511462000558578063715018a614620005d65780638456cb5914620005ee5780638da5cb5b146200060657806390e72127146200061e5780639e2d04781462000642578063ac70066514620006fa578063b7915e39146200071e578063c106f2671462000736578063c6786e5a146200075d578063c83abb4014620007b5578063d9ec338a146200089b578063dbe5bab514620008c2578063e0ffe8e314620008da578063e411c71f1462000a3b578063f2fde38b1462000a53578063fdc990641462000a77575b600080fd5b3480156200017357600080fd5b506200018a600160a060020a036004351662000a9b565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015620001c8578181015183820152602001620001ae565b505050509050019250505060405180910390f35b348015620001e957600080fd5b506200020c600160a060020a036004358116906024358116906044351662000b42565b60408051918252519081900360200190f35b3480156200022b57600080fd5b5062000245600160a060020a036004351660243562000b65565b60408051600160a060020a039092168252519081900360200190f35b3480156200026e57600080fd5b506200020c600160a060020a036004358116906024351662000b9d565b3480156200029857600080fd5b50620002a660043562000bba565b604080519115158252519081900360200190f35b348015620002c757600080fd5b50620002d262000bf4565b005b348015620002e157600080fd5b50620002f8600160a060020a036004351662000c6c565b6040518086600160a060020a0316600160a060020a0316815260200180602001806020018060200185151515158152602001848103845288818151815260200191508051906020019080838360005b838110156200036157818101518382015260200162000347565b50505050905090810190601f1680156200038f5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015620003c4578181015183820152602001620003aa565b50505050905090810190601f168015620003f25780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015620004275781810151838201526020016200040d565b50505050905090810190601f168015620004555780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390f35b3480156200047657600080fd5b50604080516020601f606435600481810135928301849004840285018401909552818452620002a694600160a060020a03813581169560248035831696604435909316953695608494920191819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975062000f6a9650505050505050565b3480156200052957600080fd5b506200018a600160a060020a03600435166200146b565b3480156200054d57600080fd5b50620002a662001510565b3480156200056557600080fd5b50604080516020601f608435600481810135928301849004840285018401909552818452620002a694600160a060020a038135811695602480359092169560443515159560643515159536959460a49493910191908190840183828082843750949750620015209650505050505050565b348015620005e357600080fd5b50620002d2620019f3565b348015620005fb57600080fd5b50620002d262001a60565b3480156200061357600080fd5b506200024562001add565b3480156200062b57600080fd5b50620002a6600160a060020a036004351662001aec565b3480156200064f57600080fd5b50604080516020601f608435600481810135928301849004840285018401909552818452620002a694600160a060020a0381358116956024803590921695604435956064359536959460a4949391019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975062001e9e9650505050505050565b3480156200070757600080fd5b506200018a600160a060020a036004351662002510565b3480156200072b57600080fd5b506200018a620025b5565b3480156200074357600080fd5b5062000245600160a060020a03600435166024356200261d565b3480156200076a57600080fd5b5060408051602060048035808201358381028086018501909652808552620002d295369593946024949385019291829185019084908082843750949750620026399650505050505050565b348015620007c257600080fd5b5060408051602060046024803582810135601f8101859004850286018501909652858552620002a6958335600160a060020a031695369560449491939091019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750620027b49650505050505050565b348015620008a857600080fd5b5062000245600160a060020a036004351660243562002a1c565b348015620008cf57600080fd5b506200018a62002a38565b348015620008e757600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526200024594369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020888301358a018035601f8101839004830284018301909452838352979a89359a8a8301359a9199909850606090910196509194509081019250819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975062002a9c9650505050505050565b34801562000a4857600080fd5b506200020c62002f1b565b34801562000a6057600080fd5b50620002d2600160a060020a036004351662002f21565b34801562000a8457600080fd5b50620002a6600160a060020a036004351662002f47565b606081600160a060020a038116151562000ab457600080fd5b600160a060020a03811630141562000acb57600080fd5b600160a060020a0383166000908152600560209081526040918290208054835181840281018401909452808452909183018282801562000b3557602002820191906000526020600020905b8154600160a060020a0316815260019091019060200180831162000b16575b5050505050915050919050565b600a60209081526000938452604080852082529284528284209052825290205481565b60076020528160005260406000208181548110151562000b8157fe5b600091825260209091200154600160a060020a03169150829050565b600b60209081526000928352604080842090915290825290205481565b60008054600160a060020a0316331462000bd357600080fd5b60005460a060020a900460ff161562000beb57600080fd5b50600d55600190565b600054600160a060020a0316331462000c0c57600080fd5b60005460a060020a900460ff16151562000c2557600080fd5b6000805474ff0000000000000000000000000000000000000000191681556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b339190a1565b60006060806060600062000c7f62003b0e565b86600160a060020a038116151562000c9657600080fd5b600160a060020a03811630141562000cad57600080fd5b600160a060020a03888116600090815260086020908152604091829020825160808101845281549094168452600180820180548551600261010094831615949094026000190190911692909204601f810185900485028301850190955284825291938584019391929183018282801562000d6b5780601f1062000d3f5761010080835404028352916020019162000d6b565b820191906000526020600020905b81548152906001019060200180831162000d4d57829003601f168201915b5050509183525050600282810180546040805160206001841615610100026000190190931694909404601f8101839004830285018301909152808452938101939083018282801562000e015780601f1062000dd55761010080835404028352916020019162000e01565b820191906000526020600020905b81548152906001019060200180831162000de357829003601f168201915b505050918352505060038201805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815293820193929183018282801562000e995780601f1062000e6d5761010080835404028352916020019162000e99565b820191906000526020600020905b81548152906001019060200180831162000e7b57829003601f168201915b5050505050815250509150816000015182602001518360400151846060015160037372ae13d70f65c56e59eb63993605abef1ecb9c416375ce4ef990918e6040518363ffffffff1660e060020a0281526004018083815260200182600160a060020a0316600160a060020a031681526020019250505060206040518083038186803b15801562000f2857600080fd5b505af415801562000f3d573d6000803e3d6000fd5b505050506040513d602081101562000f5457600080fd5b5051939c929b5090995097509095509350505050565b6000805481908190819060a060020a900460ff161562000f8957600080fd5b600160a060020a038916600090815260096020526040902054899060ff16151562000fb357600080fd5b89935083600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562000ff557600080fd5b505af11580156200100a573d6000803e3d6000fd5b505050506040513d60208110156200102157600080fd5b5051925033600160a060020a038416146200103b57600080fd5b6040805160a081018252600160a060020a03808d16825285811660208301528b81169282019290925290891660608201523060808201526200107d9062003098565b83600160a060020a03166343dcbc86896040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015620010d957600080fd5b505af1158015620010ee573d6000803e3d6000fd5b505050506040513d60208110156200110557600080fd5b505115156200111357600080fd5b7348819464877341cb7e0bbd91e0c268016ae5e6ad6324c91c1b8b8b8b8b8b6040518663ffffffff1660e060020a0281526004018086600160a060020a0316600160a060020a0316815260200185600160a060020a0316600160a060020a0316815260200184600160a060020a0316600160a060020a031681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015620011cf578181015183820152602001620011b5565b50505050905090810190601f168015620011fd5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156200123257818101518382015260200162001218565b50505050905090810190601f168015620012605780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b1580156200128357600080fd5b505af415801562001298573d6000803e3d6000fd5b505050506040513d6020811015620012af57600080fd5b50511515620012bd57600080fd5b6040517fffaef25e000000000000000000000000000000000000000000000000000000008152600160a060020a038a8116600483019081528a821660248401526060604484019081528a5160648501528a519288169363ffaef25e938e938e938e939192909160840190602085019080838360005b838110156200134c57818101518382015260200162001332565b50505050905090810190601f1680156200137a5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156200139c57600080fd5b505af1158015620013b1573d6000803e3d6000fd5b505050506040513d6020811015620013c857600080fd5b50519150811515620013d957600080fd5b620013e5848a6200313b565b600160a060020a0389811660008181526005602090815260408083208054600181018255908452918320909101805473ffffffffffffffffffffffffffffffffffffffff19168f86161790555191928716917f96a360ee9d47dddc23543ca7e1b847174c225dc8f968677e1d5b6f35f978108f9190a35060019998505050505050505050565b606081600160a060020a03811615156200148457600080fd5b600160a060020a0381163014156200149b57600080fd5b600160a060020a0383166000908152600660209081526040918290208054835181840281018401909452808452909183018282801562000b3557602002820191906000526020600020908154600160a060020a0316815260019091019060200180831162000b16575050505050915050919050565b60005460a060020a900460ff1681565b60008054819081908190819060a060020a900460ff16156200154157600080fd5b600160a060020a038a166000908152600960205260409020548a9060ff1615156200156b57600080fd5b8a945084600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015620015ad57600080fd5b505af1158015620015c2573d6000803e3d6000fd5b505050506040513d6020811015620015d957600080fd5b5051604080517fc081efc1000000000000000000000000000000000000000000000000000000008152600160a060020a038d8116600483015291519296509087169163c081efc1916024808201926020929091908290030181600087803b1580156200164457600080fd5b505af115801562001659573d6000803e3d6000fd5b505050506040513d60208110156200167057600080fd5b505115156200167e57600080fd5b84600160a060020a0316634372df998b6040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015620016da57600080fd5b505af1158015620016ef573d6000803e3d6000fd5b505050506040513d60208110156200170657600080fd5b5051925033600160a060020a03851614806200172a575033600160a060020a038416145b15156200173657600080fd5b7348819464877341cb7e0bbd91e0c268016ae5e6ad636c7e02368c8c868d8d8d6040518763ffffffff1660e060020a0281526004018087600160a060020a0316600160a060020a0316815260200186600160a060020a0316600160a060020a0316815260200185600160a060020a0316600160a060020a03168152602001841515151581526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b8381101562001803578181015183820152602001620017e9565b50505050905090810190601f168015620018315780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b1580156200185457600080fd5b505af415801562001869573d6000803e3d6000fd5b505050506040513d60208110156200188057600080fd5b505115156200188e57600080fd5b881580620018995750875b604080517f96661b04000000000000000000000000000000000000000000000000000000008152600160a060020a038d8116600483015283151560248301529151929450908716916396661b04916044808201926020929091908290030181600087803b1580156200190a57600080fd5b505af11580156200191f573d6000803e3d6000fd5b505050506040513d60208110156200193657600080fd5b505115156200194457600080fd5b6200195485858c868d8d6200360b565b8115620019a15789600160a060020a031685600160a060020a03167fcc3f610635149ab98af5df8f627c661ab8d314e273ae1ab29a88bac48d90b68e60405160405180910390a3620019e2565b83600160a060020a031685600160a060020a03167ff692f1409d5d399fd8f4bd35525ad35edd52de67ca7e2767a65c8e1fe7ec9cf160405160405180910390a35b5060019a9950505050505050505050565b600054600160a060020a0316331462001a0b57600080fd5b60008054604051600160a060020a03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600054600160a060020a0316331462001a7857600080fd5b60005460a060020a900460ff161562001a9057600080fd5b6000805474ff0000000000000000000000000000000000000000191660a060020a1781556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff6259190a1565b600054600160a060020a031681565b60008054819081908190819060a060020a900460ff161562001b0d57600080fd5b600160a060020a038616600090815260096020526040902054869060ff16151562001b3757600080fd5b604080517f75ce4ef900000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038916602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c41916375ce4ef9916044808301926020929190829003018186803b15801562001bb257600080fd5b505af415801562001bc7573d6000803e3d6000fd5b505050506040513d602081101562001bde57600080fd5b5051151562001bec57600080fd5b86945084600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562001c2e57600080fd5b505af115801562001c43573d6000803e3d6000fd5b505050506040513d602081101562001c5a57600080fd5b5051935033600160a060020a038516148062001c805750600054600160a060020a031633145b151562001c8c57600080fd5b84600160a060020a03166343d726d66040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562001ccb57600080fd5b505af115801562001ce0573d6000803e3d6000fd5b505050506040513d602081101562001cf757600080fd5b50519250821562001e9357600160a060020a038481166000818152600b602090815260408083208a861684528252808320805490849055600c54825160e060020a63a9059cbb028152600481019690965260248601829052915190975094169363a9059cbb93604480820194918390030190829087803b15801562001d7b57600080fd5b505af115801562001d90573d6000803e3d6000fd5b505050506040513d602081101562001da757600080fd5b5051151562001db557600080fd5b604080517f7d98ebde00000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038916602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c4191637d98ebde916044808301926020929190829003018186803b15801562001e3057600080fd5b505af415801562001e45573d6000803e3d6000fd5b505050506040513d602081101562001e5c57600080fd5b5050604051600160a060020a038816907fc674f2738d835a5ee10ac4c9fc95355170bec02f7b438d737c8821ca222640f990600090a25b509095945050505050565b6000805481908190819060a060020a900460ff161562001ebd57600080fd5b600160a060020a038a166000908152600960205260409020548a9060ff16151562001ee757600080fd5b89600160a060020a038116151562001efe57600080fd5b600160a060020a03811630141562001f1557600080fd5b8b945084600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562001f5757600080fd5b505af115801562001f6c573d6000803e3d6000fd5b505050506040513d602081101562001f8357600080fd5b5051935033600160a060020a0385161462001f9d57600080fd5b84600160a060020a03166343dcbc868c6040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801562001ff957600080fd5b505af11580156200200e573d6000803e3d6000fd5b505050506040513d60208110156200202557600080fd5b5051156200203257600080fd5b604080517f75ce4ef900000000000000000000000000000000000000000000000000000000815260036004820152600160a060020a038d16602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c41916375ce4ef9916044808301926020929190829003018186803b158015620020ad57600080fd5b505af4158015620020c2573d6000803e3d6000fd5b505050506040513d6020811015620020d957600080fd5b50511515620020e757600080fd5b7348819464877341cb7e0bbd91e0c268016ae5e6ad634ae90a408d8d8d8d8d8d6040518763ffffffff1660e060020a0281526004018087600160a060020a0316600160a060020a0316815260200186600160a060020a0316600160a060020a031681526020018581526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015620021985781810151838201526020016200217e565b50505050905090810190601f168015620021c65780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015620021fb578181015183820152602001620021e1565b50505050905090810190601f168015620022295780820380516001836020036101000a031916815260200191505b509850505050505050505060206040518083038186803b1580156200224d57600080fd5b505af415801562002262573d6000803e3d6000fd5b505050506040513d60208110156200227957600080fd5b505115156200228757600080fd5b84600160a060020a031663502341738c8c8c8c6040518563ffffffff1660e060020a0281526004018085600160a060020a0316600160a060020a0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156200230f578181015183820152602001620022f5565b50505050905090810190601f1680156200233d5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b1580156200236057600080fd5b505af115801562002375573d6000803e3d6000fd5b505050506040513d60208110156200238c57600080fd5b5051925082156200250057604080517fb57ab3ac00000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038e16602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c419163b57ab3ac916044808301926020929190829003018186803b1580156200241257600080fd5b505af415801562002427573d6000803e3d6000fd5b505050506040513d60208110156200243e57600080fd5b810190808051906020019092919050505050600660008c600160a060020a0316600160a060020a031681526020019081526020016000208c90806001815401808255809150509060018203906000526020600020016000909192909190916101000a815481600160a060020a030219169083600160a060020a03160217905550508a600160a060020a031685600160a060020a03167f83cce77ef1950fd47994e9ab4fa3263f250200e45f9133f74375d8c1fd072fd860405160405180910390a35b50909a9950505050505050505050565b606081600160a060020a03811615156200252957600080fd5b600160a060020a0381163014156200254057600080fd5b600160a060020a0383166000908152600760209081526040918290208054835181840281018401909452808452909183018282801562000b3557602002820191906000526020600020908154600160a060020a0316815260019091019060200180831162000b16575050505050915050919050565b606060036001018054806020026020016040519081016040528092919081815260200182805480156200261257602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311620025f3575b505050505090505b90565b60066020528160005260406000208181548110151562000b8157fe5b6000805481908190600160a060020a031633146200265657600080fd5b600092505b8351831015620027a65783838151811015156200267457fe5b6020908102909101810151604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051919450600160a060020a038516926370a08231926024808401938290030181600087803b158015620026df57600080fd5b505af1158015620026f4573d6000803e3d6000fd5b505050506040513d60208110156200270b57600080fd5b5051600080546040805160e060020a63a9059cbb028152600160a060020a0392831660048201526024810185905290519394509085169263a9059cbb92604480840193602093929083900390910190829087803b1580156200276c57600080fd5b505af115801562002781573d6000803e3d6000fd5b505050506040513d60208110156200279857600080fd5b50506001909201916200265b565b600054600160a060020a0316ff5b600080548190600160a060020a03163314620027cf57600080fd5b60005460a060020a900460ff1615620027e757600080fd5b85600160a060020a0381161515620027fe57600080fd5b600160a060020a0381163014156200281557600080fd5b600160a060020a038781166000818152600860209081526040918290205482517fb57ab3ac0000000000000000000000000000000000000000000000000000000081526003600482015260248101949094529151919093161594507372ae13d70f65c56e59eb63993605abef1ecb9c419263b57ab3ac9260448082019391829003018186803b158015620028a857600080fd5b505af4158015620028bd573d6000803e3d6000fd5b505050506040513d6020811015620028d457600080fd5b50511515620028e257600080fd5b60408051608081018252600160a060020a0389811680835260208084018b81528486018b9052606085018a9052600092835260088252949091208351815473ffffffffffffffffffffffffffffffffffffffff19169316929092178255925180519293919262002959926001850192019062003b40565b50604082015180516200297791600284019160209091019062003b40565b50606082015180516200299591600384019160209091019062003b40565b509050508115620029da57604051600160a060020a038816907f1e59e06fbc9b065c65d072c1f7a2ed1d81154e6e57768747c6c082207dca730890600090a262002a0f565b604051600160a060020a038816907f9db0a73cad02bbf95f84090f7c99969d3a1cf17d5da896752289967f9f80a58490600090a25b5060019695505050505050565b60056020528160005260406000208181548110151562000b8157fe5b6060600180018054806020026020016040519081016040528092919081815260200182805480156200261257602002820191906000526020600020908154600160a060020a03168152600190910190602001808311620025f3575050505050905090565b60008054819060a060020a900460ff161562002ab757600080fd5b600d5486101562002ac757600080fd5b600c54604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815233600482015230602482015290518892600160a060020a03169163dd62ed3e9160448083019260209291908290030181600087803b15801562002b3357600080fd5b505af115801562002b48573d6000803e3d6000fd5b505050506040513d602081101562002b5f57600080fd5b5051101562002b6d57600080fd5b3389898988888862002b7e62003bc5565b8088600160a060020a0316600160a060020a03168152602001806020018060200187815260200180602001806020018060200186810386528c818151815260200191508051906020019080838360005b8381101562002be857818101518382015260200162002bce565b50505050905090810190601f16801562002c165780820380516001836020036101000a031916815260200191505b5086810385528b5181528b516020918201918d019080838360005b8381101562002c4b57818101518382015260200162002c31565b50505050905090810190601f16801562002c795780820380516001836020036101000a031916815260200191505b5086810384528951815289516020918201918b019080838360005b8381101562002cae57818101518382015260200162002c94565b50505050905090810190601f16801562002cdc5780820380516001836020036101000a031916815260200191505b5086810383528851815288516020918201918a019080838360005b8381101562002d1157818101518382015260200162002cf7565b50505050905090810190601f16801562002d3f5780820380516001836020036101000a031916815260200191505b50868103825287518152875160209182019189019080838360005b8381101562002d7457818101518382015260200162002d5a565b50505050905090810190601f16801562002da25780820380516001836020036101000a031916815260200191505b509c50505050505050505050505050604051809103906000f08015801562002dce573d6000803e3d6000fd5b50600c54604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018a90529051929350600160a060020a03909116916323b872dd916064808201926020929091908290030181600087803b15801562002e4657600080fd5b505af115801562002e5b573d6000803e3d6000fd5b505050506040513d602081101562002e7257600080fd5b5050336000818152600b60209081526040808320600160a060020a0386168085529083528184208b90559383526007825280832080546001818101835591855283852001805473ffffffffffffffffffffffffffffffffffffffff1916861790558484526009909252808320805460ff1916909217909155517fcf6ea478d30b7e2b0d188cd4bc726f7e42c48dd94081b929ae8f03b8743f02d99190a298975050505050505050565b600d5481565b600054600160a060020a0316331462002f3957600080fd5b62002f448162003a4f565b50565b60008054600160a060020a0316331462002f6057600080fd5b60005460a060020a900460ff161562002f7857600080fd5b81600160a060020a038116151562002f8f57600080fd5b600160a060020a03811630141562002fa657600080fd5b604080517f7d98ebde00000000000000000000000000000000000000000000000000000000815260036004820152600160a060020a038516602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c4191637d98ebde916044808301926020929190829003018186803b1580156200302157600080fd5b505af415801562003036573d6000803e3d6000fd5b505050506040513d60208110156200304d57600080fd5b505115156200305b57600080fd5b604051600160a060020a038416907fd2df117cdff329511dba7edac459dd05c2b14dc4c88ea1faf058c15de773b43390600090a250600192915050565b6000805b600582101562003136576000838360058110620030b557fe5b6020020151600160a060020a03161415620030cf57600080fd5b50600181015b60058110156200312a57828160058110620030ec57fe5b6020020151600160a060020a03168383600581106200310757fe5b6020020151600160a060020a031614156200312157600080fd5b600101620030d5565b6001909101906200309c565b505050565b600080600080600080600080600060149054906101000a900460ff161515156200316457600080fd5b89600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015620031a357600080fd5b505af1158015620031b8573d6000803e3d6000fd5b505050506040513d6020811015620031cf57600080fd5b5051604080517f4372df99000000000000000000000000000000000000000000000000000000008152600160a060020a038c811660048301529151929a50908c1691634372df99916024808201926020929091908290030181600087803b1580156200323a57600080fd5b505af11580156200324f573d6000803e3d6000fd5b505050506040513d60208110156200326657600080fd5b5051600160a060020a03808a166000908152600b60209081526040808320938f168084529382528083205481517fa035b1fe0000000000000000000000000000000000000000000000000000000081529151959c509a50929363a035b1fe93600480820194918390030190829087803b158015620032e357600080fd5b505af1158015620032f8573d6000803e3d6000fd5b505050506040513d60208110156200330f57600080fd5b5051604080517f43ca78a2000000000000000000000000000000000000000000000000000000008152600160a060020a038a811660048301529151929750908c16916343ca78a29160248082019260009290919082900301818387803b1580156200337957600080fd5b505af11580156200338e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260a0811015620033b857600080fd5b8151602083015160408401516060850180519395929491939183019291640100000000811115620033e857600080fd5b82016020810184811115620033fc57600080fd5b81516401000000008111828201871017156200341757600080fd5b50949a506200343896508b95508a94505063ffffffff62003acd1692505050565b925062003446848762003ae1565b91506200345a838363ffffffff62003afb16565b90506200346e868363ffffffff62003afb16565b600b60008a600160a060020a0316600160a060020a0316815260200190815260200160002060008c600160a060020a0316600160a060020a0316815260200190815260200160002081905550600c60009054906101000a9004600160a060020a0316600160a060020a03166323b872dd8930846040518463ffffffff1660e060020a0281526004018084600160a060020a0316600160a060020a0316815260200183600160a060020a0316600160a060020a031681526020018281526020019350505050602060405180830381600087803b1580156200354d57600080fd5b505af115801562003562573d6000803e3d6000fd5b505050506040513d60208110156200357957600080fd5b505115156200358757600080fd5b600160a060020a038089166000908152600a602090815260408083208e851684528252808320938d1683529290522054620035c9908463ffffffff62003acd16565b600160a060020a039889166000908152600a602090815260408083209d8c1683529c81528c82209b909a16815299909852505050959094209290925550505050565b60008054819081908190819060a060020a900460ff16156200362c57600080fd5b8a600160a060020a031663a035b1fe6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156200366b57600080fd5b505af115801562003680573d6000803e3d6000fd5b505050506040513d60208110156200369757600080fd5b5051604080517f43ca78a2000000000000000000000000000000000000000000000000000000008152600160a060020a038b811660048301529151929750908d16916343ca78a29160248082019260009290919082900301818387803b1580156200370157600080fd5b505af115801562003716573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260a08110156200374057600080fd5b81516020830151604084015160608501805193959294919391830192916401000000008111156200377057600080fd5b820160208101848111156200378457600080fd5b81516401000000008111828201871017156200379f57600080fd5b50949a50620037c096508b95508a94505063ffffffff62003acd1692505050565b925082600a60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a0316815260200190815260200160002054101515156200383d57600080fd5b600160a060020a03808b166000908152600a602090815260408083208f851684528252808320938d16835292905220546200387f908463ffffffff62003afb16565b600a60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a031681526020019081526020016000208190555086620038fb5789620038fd565b875b91508615806200390a5750855b62003916578962003918565b885b600c546040805160e060020a63a9059cbb028152600160a060020a03868116600483015260248201899052915193945091169163a9059cbb916044808201926020929091908290030181600087803b1580156200397457600080fd5b505af115801562003989573d6000803e3d6000fd5b505050506040513d6020811015620039a057600080fd5b50511515620039ae57600080fd5b600c546040805160e060020a63a9059cbb028152600160a060020a038481166004830152602482018990529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801562003a0857600080fd5b505af115801562003a1d573d6000803e3d6000fd5b505050506040513d602081101562003a3457600080fd5b5051151562003a4257600080fd5b5050505050505050505050565b600160a060020a038116151562003a6557600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b8181018281101562003adb57fe5b92915050565b600081831062003af2578162003af4565b825b9392505050565b60008282111562003b0857fe5b50900390565b6080604051908101604052806000600160a060020a031681526020016060815260200160608152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1062003b8357805160ff191683800117855562003bb3565b8280016001018555821562003bb3579182015b8281111562003bb357825182559160200191906001019062003b96565b5062003bc192915062003bd6565b5090565b604051611aaa8062003bf483390190565b6200261a91905b8082111562003bc1576000815560010162003bdd560060806040523480156200001157600080fd5b5060405162001aaa38038062001aaa83398101604090815281516020830151918301516060840151608085015160a086015160c087015160008054600160a060020a0319163317905594969586019593840194929391820192908201910186600160a060020a03811615156200008657600080fd5b600160a060020a0381163014156200009d57600080fd5b8251600010620000ac57600080fd5b8151600010620000bb57600080fd5b60018054600160a060020a031916600160a060020a038a161790558651620000eb9060029060208a01906200017d565b508551620001019060039060208901906200017d565b50600485905583516200011c9060059060208701906200017d565b508251620001329060069060208601906200017d565b508151620001489060079060208501906200017d565b50506008805468ff00000000ffffffff19164263ffffffff161767ffffffff0000000019169055506200022295505050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620001c057805160ff1916838001178555620001f0565b82800160010185558215620001f0579182015b82811115620001f0578251825591602001919060010190620001d3565b50620001fe92915062000202565b5090565b6200021f91905b80821115620001fe576000815560010162000209565b90565b61187880620002326000396000f3006080604052600436106101485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632728e28b811461014d5780634372df991461018657806343ca78a2146101c357806343d726d61461029657806343dcbc86146102bf57806350234173146102e0578063600f1f2b1461034c5780636d4b76d51461037a578063715018a6146103925780637150d8ae146103a95780637d4ccb14146103be5780638da5cb5b1461044857806396661b041461045d57806396e8150a14610483578063a035b1fe1461051b578063b1f4ff9014610542578063c081efc114610557578063cee26ed514610578578063cf09e0d014610590578063cf317b7e146105a5578063d778ce3c14610679578063ec9359401461068e578063f2fde38b146106a3578063f678462f146106c4578063ffaef25e146106d9575b600080fd5b34801561015957600080fd5b50610162610748565b6040518082600281111561017257fe5b60ff16815260200191505060405180910390f35b34801561019257600080fd5b506101a7600160a060020a036004351661075d565b60408051600160a060020a039092168252519081900360200190f35b3480156101cf57600080fd5b506101e4600160a060020a03600435166108c0565b6040518086600160a060020a0316600160a060020a03168152602001858152602001848152602001806020018363ffffffff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561025757818101518382015260200161023f565b50505050905090810190601f1680156102845780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b3480156102a257600080fd5b506102ab610a0c565b604080519115158252519081900360200190f35b3480156102cb57600080fd5b506102ab600160a060020a0360043516610aa7565b3480156102ec57600080fd5b50604080516020601f6064356004818101359283018490048402850184019095528184526102ab94600160a060020a038135169460248035956044359536956084949301918190840183828082843750949750610afd9650505050505050565b34801561035857600080fd5b50610361610c86565b6040805163ffffffff9092168252519081900360200190f35b34801561038657600080fd5b506101a7600435610c9a565b34801561039e57600080fd5b506103a7610cc2565b005b3480156103b557600080fd5b506101a7610d2e565b3480156103ca57600080fd5b506103d3610d3d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561040d5781810151838201526020016103f5565b50505050905090810190601f16801561043a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561045457600080fd5b506101a7610dcb565b34801561046957600080fd5b506102ab600160a060020a03600435166024351515610dda565b34801561048f57600080fd5b506104a4600160a060020a0360043516610f54565b60408051600160a060020a038716815263ffffffff80861692820192909252908316606082015260208101608082018360028111156104df57fe5b60ff168152602001828103825286818151815260200191508051906020019080838360008381101561025757818101518382015260200161023f565b34801561052757600080fd5b50610530611033565b60408051918252519081900360200190f35b34801561054e57600080fd5b506103d3611039565b34801561056357600080fd5b506102ab600160a060020a0360043516611091565b34801561058457600080fd5b506101a76004356110e7565b34801561059c57600080fd5b506103616110f5565b3480156105b157600080fd5b506105c6600160a060020a0360043516611101565b60408051600160a060020a038089168252871660208083019190915263ffffffff80871660608401528516608083015260a0820184905260c0928201838152875193830193909352865191929160e084019188019080838360005b83811015610639578181015183820152602001610621565b50505050905090810190601f1680156106665780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390f35b34801561068557600080fd5b506103d361129e565b34801561069a57600080fd5b506103d36112f9565b3480156106af57600080fd5b506103a7600160a060020a0360043516611354565b3480156106d057600080fd5b506103d3611377565b3480156106e557600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102ab948235600160a060020a03908116956024803590921695369594606494929301919081908401838280828437509497506113d29650505050505050565b60085468010000000000000000900460ff1681565b6000610767611758565b82600160a060020a038116151561077d57600080fd5b600160a060020a03811630141561079357600080fd5b61079c84611091565b15156107a757600080fd5b600160a060020a03848116600090815260096020908152604091829020825160a08101845281549094168452600180820180548551600261010094831615949094026000190190911692909204601f81018590048502830185019095528482529193858401939192918301828280156108615780601f1061083657610100808354040283529160200191610861565b820191906000526020600020905b81548152906001019060200180831161084457829003601f168201915b505050918352505060028281015463ffffffff8082166020850152640100000000820416604084015260609092019168010000000000000000900460ff16908111156108a957fe5b60028111156108b457fe5b90525051949350505050565b6000806000606060006108d1611785565b86600160a060020a03811615156108e757600080fd5b600160a060020a0381163014156108fd57600080fd5b61090688610aa7565b151561091157600080fd5b600160a060020a0388166000908152600a6020908152604091829020825160808101845281548152600180830154828501526002808401805487519381161561010002600019011691909104601f810186900486028301860187528083529295939493860193919290918301828280156109cc5780601f106109a1576101008083540402835291602001916109cc565b820191906000526020600020905b8154815290600101906020018083116109af57829003601f168201915b50505091835250506003919091015463ffffffff1660209182015281519082015160408301516060909301519a9b919a9099509197509095509350505050565b60008054600160a060020a03163314610a2457600080fd5b600260085468010000000000000000900460ff166002811115610a4357fe5b1415610a4e57600080fd5b600854640100000000900463ffffffff1615610a6957600080fd5b506008805468ff00000000000000001916680200000000000000001767ffffffff0000000019166401000000004263ffffffff160217905560015b90565b600081600160a060020a0381161515610abf57600080fd5b600160a060020a038116301415610ad557600080fd5b5050600160a060020a03166000908152600a602052604090206003015463ffffffff16151590565b60008054600160a060020a03163314610b1557600080fd5b84600160a060020a0381161515610b2b57600080fd5b600160a060020a038116301415610b4157600080fd5b600854640100000000900463ffffffff1615610b5c57600080fd5b6064851115610b6a57600080fd5b610b7386610aa7565b15610b7d57600080fd5b60408051608081018252868152602080820187815282840187815263ffffffff42166060850152600160a060020a038b166000908152600a845294909420835181559051600182015592518051929392610bdd92600285019201906117b4565b50606091909101516003909101805463ffffffff191663ffffffff909216919091179055600c8054600181810183556000929092527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0389161790556008805468ff000000000000000019166801000000000000000083021790555060019695505050505050565b600854640100000000900463ffffffff1681565b600c805482908110610ca857fe5b600091825260209091200154600160a060020a0316905081565b600054600160a060020a03163314610cd957600080fd5b60008054604051600160a060020a03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600154600160a060020a031681565b6007805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b820191906000526020600020905b815481529060010190602001808311610da657829003601f168201915b505050505081565b600054600160a060020a031681565b60008054600160a060020a03163314610df257600080fd5b82600160a060020a0381161515610e0857600080fd5b600160a060020a038116301415610e1e57600080fd5b600260085468010000000000000000900460ff166002811115610e3d57fe5b1415610e4857600080fd5b600854640100000000900463ffffffff1615610e6357600080fd5b610e6c84611091565b1515610e7757600080fd5b6000600160a060020a038516600090815260096020526040902060029081015468010000000000000000900460ff1690811115610eb057fe5b14610eba57600080fd5b82610ec6576001610ec9565b60025b600160a060020a038516600090815260096020526040902060029081018054909168ff0000000000000000199091169068010000000000000000908490811115610f0f57fe5b0217905550505050600160a060020a03166000908152600960205260409020600201805467ffffffff0000000019166401000000004263ffffffff1602179055600190565b6009602090815260009182526040918290208054600180830180548651600261010094831615949094026000190190911692909204601f8101869004860283018601909652858252600160a060020a03909216949293909290830182828015610ffe5780601f10610fd357610100808354040283529160200191610ffe565b820191906000526020600020905b815481529060010190602001808311610fe157829003601f168201915b5050506002909301549192505063ffffffff8082169164010000000081049091169060ff680100000000000000009091041685565b60045481565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b600081600160a060020a03811615156110a957600080fd5b600160a060020a0381163014156110bf57600080fd5b5050600160a060020a031660009081526009602052604090206002015463ffffffff16151590565b600b805482908110610ca857fe5b60085463ffffffff1681565b60008060606000806000611113611758565b87600160a060020a038116151561112957600080fd5b600160a060020a03811630141561113f57600080fd5b61114889611091565b151561115357600080fd5b600160a060020a03898116600090815260096020908152604091829020825160a08101845281549094168452600180820180548551600261010094831615949094026000190190911692909204601f810185900485028301850190955284825291938584019391929183018282801561120d5780601f106111e25761010080835404028352916020019161120d565b820191906000526020600020905b8154815290600101906020018083116111f057829003601f168201915b505050918352505060028281015463ffffffff8082166020850152640100000000820416604084015260609092019168010000000000000000900460ff169081111561125557fe5b600281111561126057fe5b8152505091508882600001518360200151846040015185606001516112888760800151611628565b949e939d50919b50995097509095509350505050565b6006805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b6003805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b600054600160a060020a0316331461136b57600080fd5b611374816116db565b50565b6005805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b60008054600160a060020a031633146113ea57600080fd5b83600160a060020a038116151561140057600080fd5b600160a060020a03811630141561141657600080fd5b83600160a060020a038116151561142c57600080fd5b600160a060020a03811630141561144257600080fd5b600160085468010000000000000000900460ff16600281111561146157fe5b1461146b57600080fd5b600854640100000000900463ffffffff161561148657600080fd5b61148f86611091565b1561149957600080fd5b6114a285610aa7565b15156114ad57600080fd5b60a06040519081016040528086600160a060020a031681526020018581526020014263ffffffff168152602001600063ffffffff168152602001600060028111156114f457fe5b9052600160a060020a0387811660009081526009602090815260409091208351815473ffffffffffffffffffffffffffffffffffffffff1916931692909217825582810151805161154b92600185019201906117b4565b50604082015160028083018054606086015163ffffffff9081166401000000000267ffffffff00000000199190951663ffffffff199092169190911716929092178083556080850151929168ff00000000000000001990911690680100000000000000009084908111156115bb57fe5b021790555050600b8054600181810183556000929092527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9018054600160a060020a038a1673ffffffffffffffffffffffffffffffffffffffff1990911617905593505050509392505050565b60008082600281111561163757fe5b141561166457507f44617461526573706f6e736541646465640000000000000000000000000000006116d6565b600182600281111561167257fe5b141561169f57507f526566756e646564546f427579657200000000000000000000000000000000006116d6565b60028260028111156116ad57fe5b141561014857507f5472616e73616374696f6e436f6d706c657465640000000000000000000000005b919050565b600160a060020a03811615156116f057600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6040805160a081018252600080825260606020830181905292820181905291810182905290608082015290565b608060405190810160405280600081526020016000815260200160608152602001600063ffffffff1681525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106117f557805160ff1916838001178555611822565b82800160010185558215611822579182015b82811115611822578251825591602001919060010190611807565b5061182e929150611832565b5090565b610aa491905b8082111561182e57600081556001016118385600a165627a7a7230582090b9454469f2b12ba07c11a2c481de23eda8cd46e7fabdcae09b2ea5d54626870029a165627a7a723058208b119373d135bf2e3226c2a7685f7a2296b836fae440567bb8e62bb5532818d200290000000000000000000000003f17dd476faf0a4855572f0b6ed5115d9bba22ad0000000000000000000000000183b6ffc017ac4f767e460886291d09229a848b

Deployed Bytecode

0x608060405260043610620001615763ffffffff60e060020a6000350416630636d7ac8114620001665780630aa4b3be14620001dc578063319fa887146200021e578063373dfb1414620002615780633cedd004146200028b5780633f4ba83a14620002ba57806343ca78a214620002d457806352748cfe14620004695780635ac31e68146200051c5780635c975abb146200054057806360909c511462000558578063715018a614620005d65780638456cb5914620005ee5780638da5cb5b146200060657806390e72127146200061e5780639e2d04781462000642578063ac70066514620006fa578063b7915e39146200071e578063c106f2671462000736578063c6786e5a146200075d578063c83abb4014620007b5578063d9ec338a146200089b578063dbe5bab514620008c2578063e0ffe8e314620008da578063e411c71f1462000a3b578063f2fde38b1462000a53578063fdc990641462000a77575b600080fd5b3480156200017357600080fd5b506200018a600160a060020a036004351662000a9b565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015620001c8578181015183820152602001620001ae565b505050509050019250505060405180910390f35b348015620001e957600080fd5b506200020c600160a060020a036004358116906024358116906044351662000b42565b60408051918252519081900360200190f35b3480156200022b57600080fd5b5062000245600160a060020a036004351660243562000b65565b60408051600160a060020a039092168252519081900360200190f35b3480156200026e57600080fd5b506200020c600160a060020a036004358116906024351662000b9d565b3480156200029857600080fd5b50620002a660043562000bba565b604080519115158252519081900360200190f35b348015620002c757600080fd5b50620002d262000bf4565b005b348015620002e157600080fd5b50620002f8600160a060020a036004351662000c6c565b6040518086600160a060020a0316600160a060020a0316815260200180602001806020018060200185151515158152602001848103845288818151815260200191508051906020019080838360005b838110156200036157818101518382015260200162000347565b50505050905090810190601f1680156200038f5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015620003c4578181015183820152602001620003aa565b50505050905090810190601f168015620003f25780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015620004275781810151838201526020016200040d565b50505050905090810190601f168015620004555780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390f35b3480156200047657600080fd5b50604080516020601f606435600481810135928301849004840285018401909552818452620002a694600160a060020a03813581169560248035831696604435909316953695608494920191819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975062000f6a9650505050505050565b3480156200052957600080fd5b506200018a600160a060020a03600435166200146b565b3480156200054d57600080fd5b50620002a662001510565b3480156200056557600080fd5b50604080516020601f608435600481810135928301849004840285018401909552818452620002a694600160a060020a038135811695602480359092169560443515159560643515159536959460a49493910191908190840183828082843750949750620015209650505050505050565b348015620005e357600080fd5b50620002d2620019f3565b348015620005fb57600080fd5b50620002d262001a60565b3480156200061357600080fd5b506200024562001add565b3480156200062b57600080fd5b50620002a6600160a060020a036004351662001aec565b3480156200064f57600080fd5b50604080516020601f608435600481810135928301849004840285018401909552818452620002a694600160a060020a0381358116956024803590921695604435956064359536959460a4949391019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975062001e9e9650505050505050565b3480156200070757600080fd5b506200018a600160a060020a036004351662002510565b3480156200072b57600080fd5b506200018a620025b5565b3480156200074357600080fd5b5062000245600160a060020a03600435166024356200261d565b3480156200076a57600080fd5b5060408051602060048035808201358381028086018501909652808552620002d295369593946024949385019291829185019084908082843750949750620026399650505050505050565b348015620007c257600080fd5b5060408051602060046024803582810135601f8101859004850286018501909652858552620002a6958335600160a060020a031695369560449491939091019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750620027b49650505050505050565b348015620008a857600080fd5b5062000245600160a060020a036004351660243562002a1c565b348015620008cf57600080fd5b506200018a62002a38565b348015620008e757600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526200024594369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020888301358a018035601f8101839004830284018301909452838352979a89359a8a8301359a9199909850606090910196509194509081019250819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975062002a9c9650505050505050565b34801562000a4857600080fd5b506200020c62002f1b565b34801562000a6057600080fd5b50620002d2600160a060020a036004351662002f21565b34801562000a8457600080fd5b50620002a6600160a060020a036004351662002f47565b606081600160a060020a038116151562000ab457600080fd5b600160a060020a03811630141562000acb57600080fd5b600160a060020a0383166000908152600560209081526040918290208054835181840281018401909452808452909183018282801562000b3557602002820191906000526020600020905b8154600160a060020a0316815260019091019060200180831162000b16575b5050505050915050919050565b600a60209081526000938452604080852082529284528284209052825290205481565b60076020528160005260406000208181548110151562000b8157fe5b600091825260209091200154600160a060020a03169150829050565b600b60209081526000928352604080842090915290825290205481565b60008054600160a060020a0316331462000bd357600080fd5b60005460a060020a900460ff161562000beb57600080fd5b50600d55600190565b600054600160a060020a0316331462000c0c57600080fd5b60005460a060020a900460ff16151562000c2557600080fd5b6000805474ff0000000000000000000000000000000000000000191681556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b339190a1565b60006060806060600062000c7f62003b0e565b86600160a060020a038116151562000c9657600080fd5b600160a060020a03811630141562000cad57600080fd5b600160a060020a03888116600090815260086020908152604091829020825160808101845281549094168452600180820180548551600261010094831615949094026000190190911692909204601f810185900485028301850190955284825291938584019391929183018282801562000d6b5780601f1062000d3f5761010080835404028352916020019162000d6b565b820191906000526020600020905b81548152906001019060200180831162000d4d57829003601f168201915b5050509183525050600282810180546040805160206001841615610100026000190190931694909404601f8101839004830285018301909152808452938101939083018282801562000e015780601f1062000dd55761010080835404028352916020019162000e01565b820191906000526020600020905b81548152906001019060200180831162000de357829003601f168201915b505050918352505060038201805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815293820193929183018282801562000e995780601f1062000e6d5761010080835404028352916020019162000e99565b820191906000526020600020905b81548152906001019060200180831162000e7b57829003601f168201915b5050505050815250509150816000015182602001518360400151846060015160037372ae13d70f65c56e59eb63993605abef1ecb9c416375ce4ef990918e6040518363ffffffff1660e060020a0281526004018083815260200182600160a060020a0316600160a060020a031681526020019250505060206040518083038186803b15801562000f2857600080fd5b505af415801562000f3d573d6000803e3d6000fd5b505050506040513d602081101562000f5457600080fd5b5051939c929b5090995097509095509350505050565b6000805481908190819060a060020a900460ff161562000f8957600080fd5b600160a060020a038916600090815260096020526040902054899060ff16151562000fb357600080fd5b89935083600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562000ff557600080fd5b505af11580156200100a573d6000803e3d6000fd5b505050506040513d60208110156200102157600080fd5b5051925033600160a060020a038416146200103b57600080fd5b6040805160a081018252600160a060020a03808d16825285811660208301528b81169282019290925290891660608201523060808201526200107d9062003098565b83600160a060020a03166343dcbc86896040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015620010d957600080fd5b505af1158015620010ee573d6000803e3d6000fd5b505050506040513d60208110156200110557600080fd5b505115156200111357600080fd5b7348819464877341cb7e0bbd91e0c268016ae5e6ad6324c91c1b8b8b8b8b8b6040518663ffffffff1660e060020a0281526004018086600160a060020a0316600160a060020a0316815260200185600160a060020a0316600160a060020a0316815260200184600160a060020a0316600160a060020a031681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015620011cf578181015183820152602001620011b5565b50505050905090810190601f168015620011fd5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156200123257818101518382015260200162001218565b50505050905090810190601f168015620012605780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b1580156200128357600080fd5b505af415801562001298573d6000803e3d6000fd5b505050506040513d6020811015620012af57600080fd5b50511515620012bd57600080fd5b6040517fffaef25e000000000000000000000000000000000000000000000000000000008152600160a060020a038a8116600483019081528a821660248401526060604484019081528a5160648501528a519288169363ffaef25e938e938e938e939192909160840190602085019080838360005b838110156200134c57818101518382015260200162001332565b50505050905090810190601f1680156200137a5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156200139c57600080fd5b505af1158015620013b1573d6000803e3d6000fd5b505050506040513d6020811015620013c857600080fd5b50519150811515620013d957600080fd5b620013e5848a6200313b565b600160a060020a0389811660008181526005602090815260408083208054600181018255908452918320909101805473ffffffffffffffffffffffffffffffffffffffff19168f86161790555191928716917f96a360ee9d47dddc23543ca7e1b847174c225dc8f968677e1d5b6f35f978108f9190a35060019998505050505050505050565b606081600160a060020a03811615156200148457600080fd5b600160a060020a0381163014156200149b57600080fd5b600160a060020a0383166000908152600660209081526040918290208054835181840281018401909452808452909183018282801562000b3557602002820191906000526020600020908154600160a060020a0316815260019091019060200180831162000b16575050505050915050919050565b60005460a060020a900460ff1681565b60008054819081908190819060a060020a900460ff16156200154157600080fd5b600160a060020a038a166000908152600960205260409020548a9060ff1615156200156b57600080fd5b8a945084600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015620015ad57600080fd5b505af1158015620015c2573d6000803e3d6000fd5b505050506040513d6020811015620015d957600080fd5b5051604080517fc081efc1000000000000000000000000000000000000000000000000000000008152600160a060020a038d8116600483015291519296509087169163c081efc1916024808201926020929091908290030181600087803b1580156200164457600080fd5b505af115801562001659573d6000803e3d6000fd5b505050506040513d60208110156200167057600080fd5b505115156200167e57600080fd5b84600160a060020a0316634372df998b6040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015620016da57600080fd5b505af1158015620016ef573d6000803e3d6000fd5b505050506040513d60208110156200170657600080fd5b5051925033600160a060020a03851614806200172a575033600160a060020a038416145b15156200173657600080fd5b7348819464877341cb7e0bbd91e0c268016ae5e6ad636c7e02368c8c868d8d8d6040518763ffffffff1660e060020a0281526004018087600160a060020a0316600160a060020a0316815260200186600160a060020a0316600160a060020a0316815260200185600160a060020a0316600160a060020a03168152602001841515151581526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b8381101562001803578181015183820152602001620017e9565b50505050905090810190601f168015620018315780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b1580156200185457600080fd5b505af415801562001869573d6000803e3d6000fd5b505050506040513d60208110156200188057600080fd5b505115156200188e57600080fd5b881580620018995750875b604080517f96661b04000000000000000000000000000000000000000000000000000000008152600160a060020a038d8116600483015283151560248301529151929450908716916396661b04916044808201926020929091908290030181600087803b1580156200190a57600080fd5b505af11580156200191f573d6000803e3d6000fd5b505050506040513d60208110156200193657600080fd5b505115156200194457600080fd5b6200195485858c868d8d6200360b565b8115620019a15789600160a060020a031685600160a060020a03167fcc3f610635149ab98af5df8f627c661ab8d314e273ae1ab29a88bac48d90b68e60405160405180910390a3620019e2565b83600160a060020a031685600160a060020a03167ff692f1409d5d399fd8f4bd35525ad35edd52de67ca7e2767a65c8e1fe7ec9cf160405160405180910390a35b5060019a9950505050505050505050565b600054600160a060020a0316331462001a0b57600080fd5b60008054604051600160a060020a03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600054600160a060020a0316331462001a7857600080fd5b60005460a060020a900460ff161562001a9057600080fd5b6000805474ff0000000000000000000000000000000000000000191660a060020a1781556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff6259190a1565b600054600160a060020a031681565b60008054819081908190819060a060020a900460ff161562001b0d57600080fd5b600160a060020a038616600090815260096020526040902054869060ff16151562001b3757600080fd5b604080517f75ce4ef900000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038916602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c41916375ce4ef9916044808301926020929190829003018186803b15801562001bb257600080fd5b505af415801562001bc7573d6000803e3d6000fd5b505050506040513d602081101562001bde57600080fd5b5051151562001bec57600080fd5b86945084600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562001c2e57600080fd5b505af115801562001c43573d6000803e3d6000fd5b505050506040513d602081101562001c5a57600080fd5b5051935033600160a060020a038516148062001c805750600054600160a060020a031633145b151562001c8c57600080fd5b84600160a060020a03166343d726d66040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562001ccb57600080fd5b505af115801562001ce0573d6000803e3d6000fd5b505050506040513d602081101562001cf757600080fd5b50519250821562001e9357600160a060020a038481166000818152600b602090815260408083208a861684528252808320805490849055600c54825160e060020a63a9059cbb028152600481019690965260248601829052915190975094169363a9059cbb93604480820194918390030190829087803b15801562001d7b57600080fd5b505af115801562001d90573d6000803e3d6000fd5b505050506040513d602081101562001da757600080fd5b5051151562001db557600080fd5b604080517f7d98ebde00000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038916602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c4191637d98ebde916044808301926020929190829003018186803b15801562001e3057600080fd5b505af415801562001e45573d6000803e3d6000fd5b505050506040513d602081101562001e5c57600080fd5b5050604051600160a060020a038816907fc674f2738d835a5ee10ac4c9fc95355170bec02f7b438d737c8821ca222640f990600090a25b509095945050505050565b6000805481908190819060a060020a900460ff161562001ebd57600080fd5b600160a060020a038a166000908152600960205260409020548a9060ff16151562001ee757600080fd5b89600160a060020a038116151562001efe57600080fd5b600160a060020a03811630141562001f1557600080fd5b8b945084600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562001f5757600080fd5b505af115801562001f6c573d6000803e3d6000fd5b505050506040513d602081101562001f8357600080fd5b5051935033600160a060020a0385161462001f9d57600080fd5b84600160a060020a03166343dcbc868c6040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801562001ff957600080fd5b505af11580156200200e573d6000803e3d6000fd5b505050506040513d60208110156200202557600080fd5b5051156200203257600080fd5b604080517f75ce4ef900000000000000000000000000000000000000000000000000000000815260036004820152600160a060020a038d16602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c41916375ce4ef9916044808301926020929190829003018186803b158015620020ad57600080fd5b505af4158015620020c2573d6000803e3d6000fd5b505050506040513d6020811015620020d957600080fd5b50511515620020e757600080fd5b7348819464877341cb7e0bbd91e0c268016ae5e6ad634ae90a408d8d8d8d8d8d6040518763ffffffff1660e060020a0281526004018087600160a060020a0316600160a060020a0316815260200186600160a060020a0316600160a060020a031681526020018581526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015620021985781810151838201526020016200217e565b50505050905090810190601f168015620021c65780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015620021fb578181015183820152602001620021e1565b50505050905090810190601f168015620022295780820380516001836020036101000a031916815260200191505b509850505050505050505060206040518083038186803b1580156200224d57600080fd5b505af415801562002262573d6000803e3d6000fd5b505050506040513d60208110156200227957600080fd5b505115156200228757600080fd5b84600160a060020a031663502341738c8c8c8c6040518563ffffffff1660e060020a0281526004018085600160a060020a0316600160a060020a0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156200230f578181015183820152602001620022f5565b50505050905090810190601f1680156200233d5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b1580156200236057600080fd5b505af115801562002375573d6000803e3d6000fd5b505050506040513d60208110156200238c57600080fd5b5051925082156200250057604080517fb57ab3ac00000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038e16602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c419163b57ab3ac916044808301926020929190829003018186803b1580156200241257600080fd5b505af415801562002427573d6000803e3d6000fd5b505050506040513d60208110156200243e57600080fd5b810190808051906020019092919050505050600660008c600160a060020a0316600160a060020a031681526020019081526020016000208c90806001815401808255809150509060018203906000526020600020016000909192909190916101000a815481600160a060020a030219169083600160a060020a03160217905550508a600160a060020a031685600160a060020a03167f83cce77ef1950fd47994e9ab4fa3263f250200e45f9133f74375d8c1fd072fd860405160405180910390a35b50909a9950505050505050505050565b606081600160a060020a03811615156200252957600080fd5b600160a060020a0381163014156200254057600080fd5b600160a060020a0383166000908152600760209081526040918290208054835181840281018401909452808452909183018282801562000b3557602002820191906000526020600020908154600160a060020a0316815260019091019060200180831162000b16575050505050915050919050565b606060036001018054806020026020016040519081016040528092919081815260200182805480156200261257602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311620025f3575b505050505090505b90565b60066020528160005260406000208181548110151562000b8157fe5b6000805481908190600160a060020a031633146200265657600080fd5b600092505b8351831015620027a65783838151811015156200267457fe5b6020908102909101810151604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051919450600160a060020a038516926370a08231926024808401938290030181600087803b158015620026df57600080fd5b505af1158015620026f4573d6000803e3d6000fd5b505050506040513d60208110156200270b57600080fd5b5051600080546040805160e060020a63a9059cbb028152600160a060020a0392831660048201526024810185905290519394509085169263a9059cbb92604480840193602093929083900390910190829087803b1580156200276c57600080fd5b505af115801562002781573d6000803e3d6000fd5b505050506040513d60208110156200279857600080fd5b50506001909201916200265b565b600054600160a060020a0316ff5b600080548190600160a060020a03163314620027cf57600080fd5b60005460a060020a900460ff1615620027e757600080fd5b85600160a060020a0381161515620027fe57600080fd5b600160a060020a0381163014156200281557600080fd5b600160a060020a038781166000818152600860209081526040918290205482517fb57ab3ac0000000000000000000000000000000000000000000000000000000081526003600482015260248101949094529151919093161594507372ae13d70f65c56e59eb63993605abef1ecb9c419263b57ab3ac9260448082019391829003018186803b158015620028a857600080fd5b505af4158015620028bd573d6000803e3d6000fd5b505050506040513d6020811015620028d457600080fd5b50511515620028e257600080fd5b60408051608081018252600160a060020a0389811680835260208084018b81528486018b9052606085018a9052600092835260088252949091208351815473ffffffffffffffffffffffffffffffffffffffff19169316929092178255925180519293919262002959926001850192019062003b40565b50604082015180516200297791600284019160209091019062003b40565b50606082015180516200299591600384019160209091019062003b40565b509050508115620029da57604051600160a060020a038816907f1e59e06fbc9b065c65d072c1f7a2ed1d81154e6e57768747c6c082207dca730890600090a262002a0f565b604051600160a060020a038816907f9db0a73cad02bbf95f84090f7c99969d3a1cf17d5da896752289967f9f80a58490600090a25b5060019695505050505050565b60056020528160005260406000208181548110151562000b8157fe5b6060600180018054806020026020016040519081016040528092919081815260200182805480156200261257602002820191906000526020600020908154600160a060020a03168152600190910190602001808311620025f3575050505050905090565b60008054819060a060020a900460ff161562002ab757600080fd5b600d5486101562002ac757600080fd5b600c54604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815233600482015230602482015290518892600160a060020a03169163dd62ed3e9160448083019260209291908290030181600087803b15801562002b3357600080fd5b505af115801562002b48573d6000803e3d6000fd5b505050506040513d602081101562002b5f57600080fd5b5051101562002b6d57600080fd5b3389898988888862002b7e62003bc5565b8088600160a060020a0316600160a060020a03168152602001806020018060200187815260200180602001806020018060200186810386528c818151815260200191508051906020019080838360005b8381101562002be857818101518382015260200162002bce565b50505050905090810190601f16801562002c165780820380516001836020036101000a031916815260200191505b5086810385528b5181528b516020918201918d019080838360005b8381101562002c4b57818101518382015260200162002c31565b50505050905090810190601f16801562002c795780820380516001836020036101000a031916815260200191505b5086810384528951815289516020918201918b019080838360005b8381101562002cae57818101518382015260200162002c94565b50505050905090810190601f16801562002cdc5780820380516001836020036101000a031916815260200191505b5086810383528851815288516020918201918a019080838360005b8381101562002d1157818101518382015260200162002cf7565b50505050905090810190601f16801562002d3f5780820380516001836020036101000a031916815260200191505b50868103825287518152875160209182019189019080838360005b8381101562002d7457818101518382015260200162002d5a565b50505050905090810190601f16801562002da25780820380516001836020036101000a031916815260200191505b509c50505050505050505050505050604051809103906000f08015801562002dce573d6000803e3d6000fd5b50600c54604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018a90529051929350600160a060020a03909116916323b872dd916064808201926020929091908290030181600087803b15801562002e4657600080fd5b505af115801562002e5b573d6000803e3d6000fd5b505050506040513d602081101562002e7257600080fd5b5050336000818152600b60209081526040808320600160a060020a0386168085529083528184208b90559383526007825280832080546001818101835591855283852001805473ffffffffffffffffffffffffffffffffffffffff1916861790558484526009909252808320805460ff1916909217909155517fcf6ea478d30b7e2b0d188cd4bc726f7e42c48dd94081b929ae8f03b8743f02d99190a298975050505050505050565b600d5481565b600054600160a060020a0316331462002f3957600080fd5b62002f448162003a4f565b50565b60008054600160a060020a0316331462002f6057600080fd5b60005460a060020a900460ff161562002f7857600080fd5b81600160a060020a038116151562002f8f57600080fd5b600160a060020a03811630141562002fa657600080fd5b604080517f7d98ebde00000000000000000000000000000000000000000000000000000000815260036004820152600160a060020a038516602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c4191637d98ebde916044808301926020929190829003018186803b1580156200302157600080fd5b505af415801562003036573d6000803e3d6000fd5b505050506040513d60208110156200304d57600080fd5b505115156200305b57600080fd5b604051600160a060020a038416907fd2df117cdff329511dba7edac459dd05c2b14dc4c88ea1faf058c15de773b43390600090a250600192915050565b6000805b600582101562003136576000838360058110620030b557fe5b6020020151600160a060020a03161415620030cf57600080fd5b50600181015b60058110156200312a57828160058110620030ec57fe5b6020020151600160a060020a03168383600581106200310757fe5b6020020151600160a060020a031614156200312157600080fd5b600101620030d5565b6001909101906200309c565b505050565b600080600080600080600080600060149054906101000a900460ff161515156200316457600080fd5b89600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015620031a357600080fd5b505af1158015620031b8573d6000803e3d6000fd5b505050506040513d6020811015620031cf57600080fd5b5051604080517f4372df99000000000000000000000000000000000000000000000000000000008152600160a060020a038c811660048301529151929a50908c1691634372df99916024808201926020929091908290030181600087803b1580156200323a57600080fd5b505af11580156200324f573d6000803e3d6000fd5b505050506040513d60208110156200326657600080fd5b5051600160a060020a03808a166000908152600b60209081526040808320938f168084529382528083205481517fa035b1fe0000000000000000000000000000000000000000000000000000000081529151959c509a50929363a035b1fe93600480820194918390030190829087803b158015620032e357600080fd5b505af1158015620032f8573d6000803e3d6000fd5b505050506040513d60208110156200330f57600080fd5b5051604080517f43ca78a2000000000000000000000000000000000000000000000000000000008152600160a060020a038a811660048301529151929750908c16916343ca78a29160248082019260009290919082900301818387803b1580156200337957600080fd5b505af11580156200338e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260a0811015620033b857600080fd5b8151602083015160408401516060850180519395929491939183019291640100000000811115620033e857600080fd5b82016020810184811115620033fc57600080fd5b81516401000000008111828201871017156200341757600080fd5b50949a506200343896508b95508a94505063ffffffff62003acd1692505050565b925062003446848762003ae1565b91506200345a838363ffffffff62003afb16565b90506200346e868363ffffffff62003afb16565b600b60008a600160a060020a0316600160a060020a0316815260200190815260200160002060008c600160a060020a0316600160a060020a0316815260200190815260200160002081905550600c60009054906101000a9004600160a060020a0316600160a060020a03166323b872dd8930846040518463ffffffff1660e060020a0281526004018084600160a060020a0316600160a060020a0316815260200183600160a060020a0316600160a060020a031681526020018281526020019350505050602060405180830381600087803b1580156200354d57600080fd5b505af115801562003562573d6000803e3d6000fd5b505050506040513d60208110156200357957600080fd5b505115156200358757600080fd5b600160a060020a038089166000908152600a602090815260408083208e851684528252808320938d1683529290522054620035c9908463ffffffff62003acd16565b600160a060020a039889166000908152600a602090815260408083209d8c1683529c81528c82209b909a16815299909852505050959094209290925550505050565b60008054819081908190819060a060020a900460ff16156200362c57600080fd5b8a600160a060020a031663a035b1fe6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156200366b57600080fd5b505af115801562003680573d6000803e3d6000fd5b505050506040513d60208110156200369757600080fd5b5051604080517f43ca78a2000000000000000000000000000000000000000000000000000000008152600160a060020a038b811660048301529151929750908d16916343ca78a29160248082019260009290919082900301818387803b1580156200370157600080fd5b505af115801562003716573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260a08110156200374057600080fd5b81516020830151604084015160608501805193959294919391830192916401000000008111156200377057600080fd5b820160208101848111156200378457600080fd5b81516401000000008111828201871017156200379f57600080fd5b50949a50620037c096508b95508a94505063ffffffff62003acd1692505050565b925082600a60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a0316815260200190815260200160002054101515156200383d57600080fd5b600160a060020a03808b166000908152600a602090815260408083208f851684528252808320938d16835292905220546200387f908463ffffffff62003afb16565b600a60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a031681526020019081526020016000208190555086620038fb5789620038fd565b875b91508615806200390a5750855b62003916578962003918565b885b600c546040805160e060020a63a9059cbb028152600160a060020a03868116600483015260248201899052915193945091169163a9059cbb916044808201926020929091908290030181600087803b1580156200397457600080fd5b505af115801562003989573d6000803e3d6000fd5b505050506040513d6020811015620039a057600080fd5b50511515620039ae57600080fd5b600c546040805160e060020a63a9059cbb028152600160a060020a038481166004830152602482018990529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801562003a0857600080fd5b505af115801562003a1d573d6000803e3d6000fd5b505050506040513d602081101562003a3457600080fd5b5051151562003a4257600080fd5b5050505050505050505050565b600160a060020a038116151562003a6557600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b8181018281101562003adb57fe5b92915050565b600081831062003af2578162003af4565b825b9392505050565b60008282111562003b0857fe5b50900390565b6080604051908101604052806000600160a060020a031681526020016060815260200160608152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1062003b8357805160ff191683800117855562003bb3565b8280016001018555821562003bb3579182015b8281111562003bb357825182559160200191906001019062003b96565b5062003bc192915062003bd6565b5090565b604051611aaa8062003bf483390190565b6200261a91905b8082111562003bc1576000815560010162003bdd560060806040523480156200001157600080fd5b5060405162001aaa38038062001aaa83398101604090815281516020830151918301516060840151608085015160a086015160c087015160008054600160a060020a0319163317905594969586019593840194929391820192908201910186600160a060020a03811615156200008657600080fd5b600160a060020a0381163014156200009d57600080fd5b8251600010620000ac57600080fd5b8151600010620000bb57600080fd5b60018054600160a060020a031916600160a060020a038a161790558651620000eb9060029060208a01906200017d565b508551620001019060039060208901906200017d565b50600485905583516200011c9060059060208701906200017d565b508251620001329060069060208601906200017d565b508151620001489060079060208501906200017d565b50506008805468ff00000000ffffffff19164263ffffffff161767ffffffff0000000019169055506200022295505050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620001c057805160ff1916838001178555620001f0565b82800160010185558215620001f0579182015b82811115620001f0578251825591602001919060010190620001d3565b50620001fe92915062000202565b5090565b6200021f91905b80821115620001fe576000815560010162000209565b90565b61187880620002326000396000f3006080604052600436106101485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632728e28b811461014d5780634372df991461018657806343ca78a2146101c357806343d726d61461029657806343dcbc86146102bf57806350234173146102e0578063600f1f2b1461034c5780636d4b76d51461037a578063715018a6146103925780637150d8ae146103a95780637d4ccb14146103be5780638da5cb5b1461044857806396661b041461045d57806396e8150a14610483578063a035b1fe1461051b578063b1f4ff9014610542578063c081efc114610557578063cee26ed514610578578063cf09e0d014610590578063cf317b7e146105a5578063d778ce3c14610679578063ec9359401461068e578063f2fde38b146106a3578063f678462f146106c4578063ffaef25e146106d9575b600080fd5b34801561015957600080fd5b50610162610748565b6040518082600281111561017257fe5b60ff16815260200191505060405180910390f35b34801561019257600080fd5b506101a7600160a060020a036004351661075d565b60408051600160a060020a039092168252519081900360200190f35b3480156101cf57600080fd5b506101e4600160a060020a03600435166108c0565b6040518086600160a060020a0316600160a060020a03168152602001858152602001848152602001806020018363ffffffff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561025757818101518382015260200161023f565b50505050905090810190601f1680156102845780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b3480156102a257600080fd5b506102ab610a0c565b604080519115158252519081900360200190f35b3480156102cb57600080fd5b506102ab600160a060020a0360043516610aa7565b3480156102ec57600080fd5b50604080516020601f6064356004818101359283018490048402850184019095528184526102ab94600160a060020a038135169460248035956044359536956084949301918190840183828082843750949750610afd9650505050505050565b34801561035857600080fd5b50610361610c86565b6040805163ffffffff9092168252519081900360200190f35b34801561038657600080fd5b506101a7600435610c9a565b34801561039e57600080fd5b506103a7610cc2565b005b3480156103b557600080fd5b506101a7610d2e565b3480156103ca57600080fd5b506103d3610d3d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561040d5781810151838201526020016103f5565b50505050905090810190601f16801561043a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561045457600080fd5b506101a7610dcb565b34801561046957600080fd5b506102ab600160a060020a03600435166024351515610dda565b34801561048f57600080fd5b506104a4600160a060020a0360043516610f54565b60408051600160a060020a038716815263ffffffff80861692820192909252908316606082015260208101608082018360028111156104df57fe5b60ff168152602001828103825286818151815260200191508051906020019080838360008381101561025757818101518382015260200161023f565b34801561052757600080fd5b50610530611033565b60408051918252519081900360200190f35b34801561054e57600080fd5b506103d3611039565b34801561056357600080fd5b506102ab600160a060020a0360043516611091565b34801561058457600080fd5b506101a76004356110e7565b34801561059c57600080fd5b506103616110f5565b3480156105b157600080fd5b506105c6600160a060020a0360043516611101565b60408051600160a060020a038089168252871660208083019190915263ffffffff80871660608401528516608083015260a0820184905260c0928201838152875193830193909352865191929160e084019188019080838360005b83811015610639578181015183820152602001610621565b50505050905090810190601f1680156106665780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390f35b34801561068557600080fd5b506103d361129e565b34801561069a57600080fd5b506103d36112f9565b3480156106af57600080fd5b506103a7600160a060020a0360043516611354565b3480156106d057600080fd5b506103d3611377565b3480156106e557600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102ab948235600160a060020a03908116956024803590921695369594606494929301919081908401838280828437509497506113d29650505050505050565b60085468010000000000000000900460ff1681565b6000610767611758565b82600160a060020a038116151561077d57600080fd5b600160a060020a03811630141561079357600080fd5b61079c84611091565b15156107a757600080fd5b600160a060020a03848116600090815260096020908152604091829020825160a08101845281549094168452600180820180548551600261010094831615949094026000190190911692909204601f81018590048502830185019095528482529193858401939192918301828280156108615780601f1061083657610100808354040283529160200191610861565b820191906000526020600020905b81548152906001019060200180831161084457829003601f168201915b505050918352505060028281015463ffffffff8082166020850152640100000000820416604084015260609092019168010000000000000000900460ff16908111156108a957fe5b60028111156108b457fe5b90525051949350505050565b6000806000606060006108d1611785565b86600160a060020a03811615156108e757600080fd5b600160a060020a0381163014156108fd57600080fd5b61090688610aa7565b151561091157600080fd5b600160a060020a0388166000908152600a6020908152604091829020825160808101845281548152600180830154828501526002808401805487519381161561010002600019011691909104601f810186900486028301860187528083529295939493860193919290918301828280156109cc5780601f106109a1576101008083540402835291602001916109cc565b820191906000526020600020905b8154815290600101906020018083116109af57829003601f168201915b50505091835250506003919091015463ffffffff1660209182015281519082015160408301516060909301519a9b919a9099509197509095509350505050565b60008054600160a060020a03163314610a2457600080fd5b600260085468010000000000000000900460ff166002811115610a4357fe5b1415610a4e57600080fd5b600854640100000000900463ffffffff1615610a6957600080fd5b506008805468ff00000000000000001916680200000000000000001767ffffffff0000000019166401000000004263ffffffff160217905560015b90565b600081600160a060020a0381161515610abf57600080fd5b600160a060020a038116301415610ad557600080fd5b5050600160a060020a03166000908152600a602052604090206003015463ffffffff16151590565b60008054600160a060020a03163314610b1557600080fd5b84600160a060020a0381161515610b2b57600080fd5b600160a060020a038116301415610b4157600080fd5b600854640100000000900463ffffffff1615610b5c57600080fd5b6064851115610b6a57600080fd5b610b7386610aa7565b15610b7d57600080fd5b60408051608081018252868152602080820187815282840187815263ffffffff42166060850152600160a060020a038b166000908152600a845294909420835181559051600182015592518051929392610bdd92600285019201906117b4565b50606091909101516003909101805463ffffffff191663ffffffff909216919091179055600c8054600181810183556000929092527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0389161790556008805468ff000000000000000019166801000000000000000083021790555060019695505050505050565b600854640100000000900463ffffffff1681565b600c805482908110610ca857fe5b600091825260209091200154600160a060020a0316905081565b600054600160a060020a03163314610cd957600080fd5b60008054604051600160a060020a03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600154600160a060020a031681565b6007805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b820191906000526020600020905b815481529060010190602001808311610da657829003601f168201915b505050505081565b600054600160a060020a031681565b60008054600160a060020a03163314610df257600080fd5b82600160a060020a0381161515610e0857600080fd5b600160a060020a038116301415610e1e57600080fd5b600260085468010000000000000000900460ff166002811115610e3d57fe5b1415610e4857600080fd5b600854640100000000900463ffffffff1615610e6357600080fd5b610e6c84611091565b1515610e7757600080fd5b6000600160a060020a038516600090815260096020526040902060029081015468010000000000000000900460ff1690811115610eb057fe5b14610eba57600080fd5b82610ec6576001610ec9565b60025b600160a060020a038516600090815260096020526040902060029081018054909168ff0000000000000000199091169068010000000000000000908490811115610f0f57fe5b0217905550505050600160a060020a03166000908152600960205260409020600201805467ffffffff0000000019166401000000004263ffffffff1602179055600190565b6009602090815260009182526040918290208054600180830180548651600261010094831615949094026000190190911692909204601f8101869004860283018601909652858252600160a060020a03909216949293909290830182828015610ffe5780601f10610fd357610100808354040283529160200191610ffe565b820191906000526020600020905b815481529060010190602001808311610fe157829003601f168201915b5050506002909301549192505063ffffffff8082169164010000000081049091169060ff680100000000000000009091041685565b60045481565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b600081600160a060020a03811615156110a957600080fd5b600160a060020a0381163014156110bf57600080fd5b5050600160a060020a031660009081526009602052604090206002015463ffffffff16151590565b600b805482908110610ca857fe5b60085463ffffffff1681565b60008060606000806000611113611758565b87600160a060020a038116151561112957600080fd5b600160a060020a03811630141561113f57600080fd5b61114889611091565b151561115357600080fd5b600160a060020a03898116600090815260096020908152604091829020825160a08101845281549094168452600180820180548551600261010094831615949094026000190190911692909204601f810185900485028301850190955284825291938584019391929183018282801561120d5780601f106111e25761010080835404028352916020019161120d565b820191906000526020600020905b8154815290600101906020018083116111f057829003601f168201915b505050918352505060028281015463ffffffff8082166020850152640100000000820416604084015260609092019168010000000000000000900460ff169081111561125557fe5b600281111561126057fe5b8152505091508882600001518360200151846040015185606001516112888760800151611628565b949e939d50919b50995097509095509350505050565b6006805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b6003805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b600054600160a060020a0316331461136b57600080fd5b611374816116db565b50565b6005805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b60008054600160a060020a031633146113ea57600080fd5b83600160a060020a038116151561140057600080fd5b600160a060020a03811630141561141657600080fd5b83600160a060020a038116151561142c57600080fd5b600160a060020a03811630141561144257600080fd5b600160085468010000000000000000900460ff16600281111561146157fe5b1461146b57600080fd5b600854640100000000900463ffffffff161561148657600080fd5b61148f86611091565b1561149957600080fd5b6114a285610aa7565b15156114ad57600080fd5b60a06040519081016040528086600160a060020a031681526020018581526020014263ffffffff168152602001600063ffffffff168152602001600060028111156114f457fe5b9052600160a060020a0387811660009081526009602090815260409091208351815473ffffffffffffffffffffffffffffffffffffffff1916931692909217825582810151805161154b92600185019201906117b4565b50604082015160028083018054606086015163ffffffff9081166401000000000267ffffffff00000000199190951663ffffffff199092169190911716929092178083556080850151929168ff00000000000000001990911690680100000000000000009084908111156115bb57fe5b021790555050600b8054600181810183556000929092527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9018054600160a060020a038a1673ffffffffffffffffffffffffffffffffffffffff1990911617905593505050509392505050565b60008082600281111561163757fe5b141561166457507f44617461526573706f6e736541646465640000000000000000000000000000006116d6565b600182600281111561167257fe5b141561169f57507f526566756e646564546f427579657200000000000000000000000000000000006116d6565b60028260028111156116ad57fe5b141561014857507f5472616e73616374696f6e436f6d706c657465640000000000000000000000005b919050565b600160a060020a03811615156116f057600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6040805160a081018252600080825260606020830181905292820181905291810182905290608082015290565b608060405190810160405280600081526020016000815260200160608152602001600063ffffffff1681525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106117f557805160ff1916838001178555611822565b82800160010185558215611822579182015b82811115611822578251825591602001919060010190611807565b5061182e929150611832565b5090565b610aa491905b8082111561182e57600081556001016118385600a165627a7a7230582090b9454469f2b12ba07c11a2c481de23eda8cd46e7fabdcae09b2ea5d54626870029a165627a7a723058208b119373d135bf2e3226c2a7685f7a2296b836fae440567bb8e62bb5532818d20029

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

0000000000000000000000003f17dd476faf0a4855572f0b6ed5115d9bba22ad0000000000000000000000000183b6ffc017ac4f767e460886291d09229a848b

-----Decoded View---------------
Arg [0] : tokenAddress (address): 0x3F17Dd476faF0a4855572F0B6ed5115D9bBA22AD
Arg [1] : ownerAddress (address): 0x0183b6fFC017AC4F767E460886291D09229a848b

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000003f17dd476faf0a4855572f0b6ed5115d9bba22ad
Arg [1] : 0000000000000000000000000183b6ffc017ac4f767e460886291d09229a848b


Libraries Used


Swarm Source

bzzr://8b119373d135bf2e3226c2a7685f7a2296b836fae440567bb8e62bb5532818d2

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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