Contract Overview
Balance: 0 Ether
Ether Value: $0
Transactions: 34510 txns
Misc:
Address Watch: Add To Watch List
Contract Creator: 0x1bbda03ff0d7dea036df31bdda8e4d6b0f0d5b83at txn 0x8a2f651d28ec70881bb458d789c64fadbd6ee359a4c8bec5f3c7f63801ac6af5
Token Balance:
 Latest 25 transactions from a total of 34510 transactions

TxHash Age From To Value [TxFee]
0x8538003008a85d023441f43efbe49a2c65898c2c4a7a7e0f8727817aaab2ef3747 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387848
0x3143529f699000c9ee09e30485d07ef072b9cbcb8c1743394f7501ede345ae2548 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387568
0x5fc18c17b816193fc4cb60f351db99fae668885836d24436034360560f6c474c49 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.00400869
0x0678e008d0a6cb5e2b7b1126614a276f663f8e6e256e64659d49b632503a75de50 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.00400869
0x463f34b4f1699bd63ee9944bc5aa17231e5dd21d4204cb85de0084591570591051 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387568
0xcf98d024608157c1792cde1645704bef22cfbf1ea97e66c0e2444afa250e3cff52 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.00400897
0x2589d657c20db69a0d26d35d42e0d53b49223c2683741c4cfffac8b0037fc6d11 hr 9 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387568
0x946d515de529f42e88084d394ba792de02e9c73de174f42a6d09e57aa8ed0c5b1 hr 10 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.004008074
0xf55d3f8799d2e908f03fdb8a26d839534acd1e8347a27e7743122b8720de45c41 hr 14 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387568
0x82ab152735a977f13a802a08744dcda64ae2c7a675558363caea5bc041909c661 hr 15 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.00400869
0x3a5c78fca361252d5a3ce4dcd341e82bab5618a385482d902bf884e342b193791 hr 16 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387568
0xf0f9df7dff1dbae871cc5f42d7888eb6022bc44ddc8afcbb308e668f5c4759041 hr 17 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.00400869
0x02c6b92e9f2bd673638e6da136430d0daac0ac25ce1288eeeaf0b36316a2543a1 hr 21 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387848
0x48d561b355bef9150f8c4f942efbfb3cb2fbc615846e4d21f78e518765de1a281 hr 21 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387568
0x64fdfb11bd954c5f321318084b5ad7b26b1df2323b619d62fc7ab09ab556a2c01 hr 22 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.00400869
0xb09c128314cba612bfa83d24ee4c416337f88a5c23846c2eb1b913ee76aaa60b1 hr 22 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.004007178
0x167c0e35ccdbb2e286c6fe4eac75670754f08629a3117ae6d4644b61e37d901d1 hr 24 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387848
0x60b5f5abf5107ef81c4cdbc1b7003287735a2cabcc043ec550e234d362d24be21 hr 24 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.00400897
0x07b875f374e8f5b223b581ae9e1e2c971229741c07f93c73ce5c317c4e4c4cad1 hr 29 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387568
0x1ec3ef0b8e2a184144266f96641ece15d93b62939b53ad9faeafc7ae83e4e51c1 hr 29 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.00400869
0x616b4041febd1cb998e2da737ac10db6f00fa4dca1cb991ca7e7b34226d2ff8e1 hr 35 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387848
0xa5ca026b2c5b0adae186100bf03e3dce01b5fcf087d7c9c4857b95cb1b9a78c91 hr 35 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.004007794
0x4804aa1326963c02a9ce258792bd0dc3df4c72e697eb197e8f123714cc8e71872 hrs 12 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001387568
0x7ca9551d4c56e9361288cf46fda363f4c996525f8aca884bd2673d11df63337d2 hrs 12 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.00400869
0x1bf4984ab31b3e653cb90e52b8398656d4de98051cef229a33861e7d7e33338c2 hrs 26 mins ago0x6d27d82d7d6f0ae00ba6cdfe53aa9d0097952222  IN   0xd077c09a7e65c4cca490a776d5e395fb4fe7179a0 Ether0.001386672
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
 Latest 25 Internal Txns, Click here To View More View All
ParentTxHash Block Age From To Value
0x472a120c14f4263e0bbbc8fc8d95a3feefe8e7550024a5c29f6885a481505b8068622641 day 1 hr ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0xb86240dd6504a21be3f18194ead1f52ff763fccdc4d86fd3c9fbe4877254b38d68435634 days 3 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x39967c6e19e258dca944e484a3318979de07648df240bd035abf1e4af38c4c8568325465 days 23 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0xd55f560e14a63f3e2d0e54123815fdc30223f0ed16ee9c65a8868e379185690468260717 days 1 hr ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x4a8b53e882630097bce7d6f811e96c22d4b7254c9c78a36e094f91bda4809dbe680157411 days 2 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x98d4e85a9bba9827cd36fb32edd7f339f1725b4e66dffeab971b54cfdb60aef5679008712 days 23 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x770a6e6bc8246d6110558d09928e164ed467726dd64f6b6fc7f0f818b556e783677808014 days 23 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x1d6b0a83925171b00fde4b020098d48a58adc114a1dcfdf227026bb8c331114c675954518 days 29 mins ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0xc52f74c858a418b50b7738cdb57aa35cde91e871fbfd79f0778a77b244819a01674684920 days 2 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0xaefb657df87d55f3d13e8e7f7bde3d885dc3c1a756cf19ca1956ec76134f4453671723624 days 23 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x0759f375eeb306a23deac41c04009087e5d7a0d805692b73021f71a8887cfcdd670458627 days 51 mins ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x5b0ef612bfca006b4448125b1cc1211ceed2541870436f0c2e519b486a95fef5669153229 days 4 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x81278f1752da86d433fa9c886ec7a469b5b108f9f15162674b4b2a46b340daec667322932 days 4 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0xf564a49c2f2a0bd367a0212e5c4a2a1ea0f7c9bd3d452da5eaa7ad8c26da173a666211733 days 23 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x168469379a9217f6574d6df74815be46264dc1a9250202d3e88fab5258a6bfe2662438340 days 4 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x7a4369cc7d7187acfb82c83b92fcea40356ece7474164511eacf23720e54a9d4657701547 days 22 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x603100e19aea2398a7c9ea4bcd9b51b322b36632ebe6059ba952446cae58695d650361459 days 21 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x540553e2e2600d0a0a407f8f5d2e10c4feedd90313f7e0474b45ac019b41f341647857963 days 23 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0xa672a6c85f5aa100271ea6a9aa1a746956d27d80d794dee64765d0e0cfa92eaa641778873 days 20 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x89cf13c748b5c9fd0ae092d8bf02e29dd99440baadf50b1ddd5a1c43fecf0e62641777173 days 21 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x74724cf223761f88e3dc74f54775aeac1601f2ad4a4ffe498978fdc7adfa4eee641768573 days 21 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x33f043261aa7d6275a2594f34c517a4f28cc6ba48ecb4b42a86fb44d8e1503bc641765673 days 21 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x9ba7a4b4a54635f5afa48a8160307f417902d6ff298ebabdd1afabb225162a9d641728773 days 22 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x1f0a70876723acec79d0198b70792f9a2a8216b21fc4b99e0836673a18d848fd641191474 days 20 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
0x171fbe1079b6937e91f13e7e994eb785ad6a7d11b62179037e78657c593d0fc6636727582 days 4 hrs ago0xd077c09a7e65c4cca490a776d5e395fb4fe7179a  Contract Creation0 Ether
[ Download CSV Export  ] 
Warning: The Compiled Contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity) SolidityCompiler Bugs.

Contract Source Code Verified (Exact Match)
Contract Name: DataExchange
Compiler Text: v0.4.24+commit.e67f0147
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

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 <[email protected]π.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 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"}]

  Contract Creation Code Switch To Opcodes View
60806040526000805460a060020a60ff02191690553480156200002157600080fd5b506040516040806200587a83398101604052805160209091015160008054600160a060020a0319163317905581600160a060020a03811615156200006457600080fd5b600160a060020a0381163014156200007b57600080fd5b81600160a060020a03811615156200009257600080fd5b600160a060020a038116301415620000a957600080fd5b600160a060020a038481169084161415620000c357600080fd5b600c8054600160a060020a031916600160a060020a0386161790556000600d55620000f78364010000000062000101810204565b50505050620001a1565b600054600160a060020a031633146200011957600080fd5b6200012d8164010000000062000130810204565b50565b600160a060020a03811615156200014657600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360008054600160a060020a031916600160a060020a0392909216919091179055565b6156c980620001b16000396000f300608060405260043610620001615763ffffffff60e060020a6000350416630636d7ac8114620001665780630aa4b3be14620001dc578063319fa887146200021e578063373dfb1414620002615780633cedd004146200028b5780633f4ba83a14620002ba57806343ca78a214620002d457806352748cfe14620004695780635ac31e68146200051c5780635c975abb146200054057806360909c511462000558578063715018a614620005d65780638456cb5914620005ee5780638da5cb5b146200060657806390e72127146200061e5780639e2d04781462000642578063ac70066514620006fa578063b7915e39146200071e578063c106f2671462000736578063c6786e5a146200075d578063c83abb4014620007b5578063d9ec338a146200089b578063dbe5bab514620008c2578063e0ffe8e314620008da578063e411c71f1462000a3b578063f2fde38b1462000a53578063fdc990641462000a77575b600080fd5b3480156200017357600080fd5b506200018a600160a060020a036004351662000a9b565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015620001c8578181015183820152602001620001ae565b505050509050019250505060405180910390f35b348015620001e957600080fd5b506200020c600160a060020a036004358116906024358116906044351662000b42565b60408051918252519081900360200190f35b3480156200022b57600080fd5b5062000245600160a060020a036004351660243562000b65565b60408051600160a060020a039092168252519081900360200190f35b3480156200026e57600080fd5b506200020c600160a060020a036004358116906024351662000b9d565b3480156200029857600080fd5b50620002a660043562000bba565b604080519115158252519081900360200190f35b348015620002c757600080fd5b50620002d262000bf4565b005b348015620002e157600080fd5b50620002f8600160a060020a036004351662000c6c565b6040518086600160a060020a0316600160a060020a0316815260200180602001806020018060200185151515158152602001848103845288818151815260200191508051906020019080838360005b838110156200036157818101518382015260200162000347565b50505050905090810190601f1680156200038f5780820380516001836020036101000a031916815260200191505b50848103835287518152875160209182019189019080838360005b83811015620003c4578181015183820152602001620003aa565b50505050905090810190601f168015620003f25780820380516001836020036101000a031916815260200191505b50848103825286518152865160209182019188019080838360005b83811015620004275781810151838201526020016200040d565b50505050905090810190601f168015620004555780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390f35b3480156200047657600080fd5b50604080516020601f606435600481810135928301849004840285018401909552818452620002a694600160a060020a03813581169560248035831696604435909316953695608494920191819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975062000f6a9650505050505050565b3480156200052957600080fd5b506200018a600160a060020a03600435166200146b565b3480156200054d57600080fd5b50620002a662001510565b3480156200056557600080fd5b50604080516020601f608435600481810135928301849004840285018401909552818452620002a694600160a060020a038135811695602480359092169560443515159560643515159536959460a49493910191908190840183828082843750949750620015209650505050505050565b348015620005e357600080fd5b50620002d2620019f3565b348015620005fb57600080fd5b50620002d262001a60565b3480156200061357600080fd5b506200024562001add565b3480156200062b57600080fd5b50620002a6600160a060020a036004351662001aec565b3480156200064f57600080fd5b50604080516020601f608435600481810135928301849004840285018401909552818452620002a694600160a060020a0381358116956024803590921695604435956064359536959460a4949391019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975062001e9e9650505050505050565b3480156200070757600080fd5b506200018a600160a060020a036004351662002510565b3480156200072b57600080fd5b506200018a620025b5565b3480156200074357600080fd5b5062000245600160a060020a03600435166024356200261d565b3480156200076a57600080fd5b5060408051602060048035808201358381028086018501909652808552620002d295369593946024949385019291829185019084908082843750949750620026399650505050505050565b348015620007c257600080fd5b5060408051602060046024803582810135601f8101859004850286018501909652858552620002a6958335600160a060020a031695369560449491939091019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a999881019791965091820194509250829150840183828082843750949750620027b49650505050505050565b348015620008a857600080fd5b5062000245600160a060020a036004351660243562002a1c565b348015620008cf57600080fd5b506200018a62002a38565b348015620008e757600080fd5b506040805160206004803580820135601f81018490048402850184019095528484526200024594369492936024939284019190819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020888301358a018035601f8101839004830284018301909452838352979a89359a8a8301359a9199909850606090910196509194509081019250819084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375050604080516020601f89358b018035918201839004830284018301909452808352979a99988101979196509182019450925082915084018382808284375094975062002a9c9650505050505050565b34801562000a4857600080fd5b506200020c62002f1b565b34801562000a6057600080fd5b50620002d2600160a060020a036004351662002f21565b34801562000a8457600080fd5b50620002a6600160a060020a036004351662002f47565b606081600160a060020a038116151562000ab457600080fd5b600160a060020a03811630141562000acb57600080fd5b600160a060020a0383166000908152600560209081526040918290208054835181840281018401909452808452909183018282801562000b3557602002820191906000526020600020905b8154600160a060020a0316815260019091019060200180831162000b16575b5050505050915050919050565b600a60209081526000938452604080852082529284528284209052825290205481565b60076020528160005260406000208181548110151562000b8157fe5b600091825260209091200154600160a060020a03169150829050565b600b60209081526000928352604080842090915290825290205481565b60008054600160a060020a0316331462000bd357600080fd5b60005460a060020a900460ff161562000beb57600080fd5b50600d55600190565b600054600160a060020a0316331462000c0c57600080fd5b60005460a060020a900460ff16151562000c2557600080fd5b6000805474ff0000000000000000000000000000000000000000191681556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b339190a1565b60006060806060600062000c7f62003b0e565b86600160a060020a038116151562000c9657600080fd5b600160a060020a03811630141562000cad57600080fd5b600160a060020a03888116600090815260086020908152604091829020825160808101845281549094168452600180820180548551600261010094831615949094026000190190911692909204601f810185900485028301850190955284825291938584019391929183018282801562000d6b5780601f1062000d3f5761010080835404028352916020019162000d6b565b820191906000526020600020905b81548152906001019060200180831162000d4d57829003601f168201915b5050509183525050600282810180546040805160206001841615610100026000190190931694909404601f8101839004830285018301909152808452938101939083018282801562000e015780601f1062000dd55761010080835404028352916020019162000e01565b820191906000526020600020905b81548152906001019060200180831162000de357829003601f168201915b505050918352505060038201805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815293820193929183018282801562000e995780601f1062000e6d5761010080835404028352916020019162000e99565b820191906000526020600020905b81548152906001019060200180831162000e7b57829003601f168201915b5050505050815250509150816000015182602001518360400151846060015160037372ae13d70f65c56e59eb63993605abef1ecb9c416375ce4ef990918e6040518363ffffffff1660e060020a0281526004018083815260200182600160a060020a0316600160a060020a031681526020019250505060206040518083038186803b15801562000f2857600080fd5b505af415801562000f3d573d6000803e3d6000fd5b505050506040513d602081101562000f5457600080fd5b5051939c929b5090995097509095509350505050565b6000805481908190819060a060020a900460ff161562000f8957600080fd5b600160a060020a038916600090815260096020526040902054899060ff16151562000fb357600080fd5b89935083600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562000ff557600080fd5b505af11580156200100a573d6000803e3d6000fd5b505050506040513d60208110156200102157600080fd5b5051925033600160a060020a038416146200103b57600080fd5b6040805160a081018252600160a060020a03808d16825285811660208301528b81169282019290925290891660608201523060808201526200107d9062003098565b83600160a060020a03166343dcbc86896040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015620010d957600080fd5b505af1158015620010ee573d6000803e3d6000fd5b505050506040513d60208110156200110557600080fd5b505115156200111357600080fd5b7348819464877341cb7e0bbd91e0c268016ae5e6ad6324c91c1b8b8b8b8b8b6040518663ffffffff1660e060020a0281526004018086600160a060020a0316600160a060020a0316815260200185600160a060020a0316600160a060020a0316815260200184600160a060020a0316600160a060020a031681526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015620011cf578181015183820152602001620011b5565b50505050905090810190601f168015620011fd5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156200123257818101518382015260200162001218565b50505050905090810190601f168015620012605780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b1580156200128357600080fd5b505af415801562001298573d6000803e3d6000fd5b505050506040513d6020811015620012af57600080fd5b50511515620012bd57600080fd5b6040517fffaef25e000000000000000000000000000000000000000000000000000000008152600160a060020a038a8116600483019081528a821660248401526060604484019081528a5160648501528a519288169363ffaef25e938e938e938e939192909160840190602085019080838360005b838110156200134c57818101518382015260200162001332565b50505050905090810190601f1680156200137a5780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156200139c57600080fd5b505af1158015620013b1573d6000803e3d6000fd5b505050506040513d6020811015620013c857600080fd5b50519150811515620013d957600080fd5b620013e5848a6200313b565b600160a060020a0389811660008181526005602090815260408083208054600181018255908452918320909101805473ffffffffffffffffffffffffffffffffffffffff19168f86161790555191928716917f96a360ee9d47dddc23543ca7e1b847174c225dc8f968677e1d5b6f35f978108f9190a35060019998505050505050505050565b606081600160a060020a03811615156200148457600080fd5b600160a060020a0381163014156200149b57600080fd5b600160a060020a0383166000908152600660209081526040918290208054835181840281018401909452808452909183018282801562000b3557602002820191906000526020600020908154600160a060020a0316815260019091019060200180831162000b16575050505050915050919050565b60005460a060020a900460ff1681565b60008054819081908190819060a060020a900460ff16156200154157600080fd5b600160a060020a038a166000908152600960205260409020548a9060ff1615156200156b57600080fd5b8a945084600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015620015ad57600080fd5b505af1158015620015c2573d6000803e3d6000fd5b505050506040513d6020811015620015d957600080fd5b5051604080517fc081efc1000000000000000000000000000000000000000000000000000000008152600160a060020a038d8116600483015291519296509087169163c081efc1916024808201926020929091908290030181600087803b1580156200164457600080fd5b505af115801562001659573d6000803e3d6000fd5b505050506040513d60208110156200167057600080fd5b505115156200167e57600080fd5b84600160a060020a0316634372df998b6040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015620016da57600080fd5b505af1158015620016ef573d6000803e3d6000fd5b505050506040513d60208110156200170657600080fd5b5051925033600160a060020a03851614806200172a575033600160a060020a038416145b15156200173657600080fd5b7348819464877341cb7e0bbd91e0c268016ae5e6ad636c7e02368c8c868d8d8d6040518763ffffffff1660e060020a0281526004018087600160a060020a0316600160a060020a0316815260200186600160a060020a0316600160a060020a0316815260200185600160a060020a0316600160a060020a03168152602001841515151581526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b8381101562001803578181015183820152602001620017e9565b50505050905090810190601f168015620018315780820380516001836020036101000a031916815260200191505b5097505050505050505060206040518083038186803b1580156200185457600080fd5b505af415801562001869573d6000803e3d6000fd5b505050506040513d60208110156200188057600080fd5b505115156200188e57600080fd5b881580620018995750875b604080517f96661b04000000000000000000000000000000000000000000000000000000008152600160a060020a038d8116600483015283151560248301529151929450908716916396661b04916044808201926020929091908290030181600087803b1580156200190a57600080fd5b505af11580156200191f573d6000803e3d6000fd5b505050506040513d60208110156200193657600080fd5b505115156200194457600080fd5b6200195485858c868d8d6200360b565b8115620019a15789600160a060020a031685600160a060020a03167fcc3f610635149ab98af5df8f627c661ab8d314e273ae1ab29a88bac48d90b68e60405160405180910390a3620019e2565b83600160a060020a031685600160a060020a03167ff692f1409d5d399fd8f4bd35525ad35edd52de67ca7e2767a65c8e1fe7ec9cf160405160405180910390a35b5060019a9950505050505050505050565b600054600160a060020a0316331462001a0b57600080fd5b60008054604051600160a060020a03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600054600160a060020a0316331462001a7857600080fd5b60005460a060020a900460ff161562001a9057600080fd5b6000805474ff0000000000000000000000000000000000000000191660a060020a1781556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff6259190a1565b600054600160a060020a031681565b60008054819081908190819060a060020a900460ff161562001b0d57600080fd5b600160a060020a038616600090815260096020526040902054869060ff16151562001b3757600080fd5b604080517f75ce4ef900000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038916602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c41916375ce4ef9916044808301926020929190829003018186803b15801562001bb257600080fd5b505af415801562001bc7573d6000803e3d6000fd5b505050506040513d602081101562001bde57600080fd5b5051151562001bec57600080fd5b86945084600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562001c2e57600080fd5b505af115801562001c43573d6000803e3d6000fd5b505050506040513d602081101562001c5a57600080fd5b5051935033600160a060020a038516148062001c805750600054600160a060020a031633145b151562001c8c57600080fd5b84600160a060020a03166343d726d66040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562001ccb57600080fd5b505af115801562001ce0573d6000803e3d6000fd5b505050506040513d602081101562001cf757600080fd5b50519250821562001e9357600160a060020a038481166000818152600b602090815260408083208a861684528252808320805490849055600c54825160e060020a63a9059cbb028152600481019690965260248601829052915190975094169363a9059cbb93604480820194918390030190829087803b15801562001d7b57600080fd5b505af115801562001d90573d6000803e3d6000fd5b505050506040513d602081101562001da757600080fd5b5051151562001db557600080fd5b604080517f7d98ebde00000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038916602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c4191637d98ebde916044808301926020929190829003018186803b15801562001e3057600080fd5b505af415801562001e45573d6000803e3d6000fd5b505050506040513d602081101562001e5c57600080fd5b5050604051600160a060020a038816907fc674f2738d835a5ee10ac4c9fc95355170bec02f7b438d737c8821ca222640f990600090a25b509095945050505050565b6000805481908190819060a060020a900460ff161562001ebd57600080fd5b600160a060020a038a166000908152600960205260409020548a9060ff16151562001ee757600080fd5b89600160a060020a038116151562001efe57600080fd5b600160a060020a03811630141562001f1557600080fd5b8b945084600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801562001f5757600080fd5b505af115801562001f6c573d6000803e3d6000fd5b505050506040513d602081101562001f8357600080fd5b5051935033600160a060020a0385161462001f9d57600080fd5b84600160a060020a03166343dcbc868c6040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801562001ff957600080fd5b505af11580156200200e573d6000803e3d6000fd5b505050506040513d60208110156200202557600080fd5b5051156200203257600080fd5b604080517f75ce4ef900000000000000000000000000000000000000000000000000000000815260036004820152600160a060020a038d16602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c41916375ce4ef9916044808301926020929190829003018186803b158015620020ad57600080fd5b505af4158015620020c2573d6000803e3d6000fd5b505050506040513d6020811015620020d957600080fd5b50511515620020e757600080fd5b7348819464877341cb7e0bbd91e0c268016ae5e6ad634ae90a408d8d8d8d8d8d6040518763ffffffff1660e060020a0281526004018087600160a060020a0316600160a060020a0316815260200186600160a060020a0316600160a060020a031681526020018581526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015620021985781810151838201526020016200217e565b50505050905090810190601f168015620021c65780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015620021fb578181015183820152602001620021e1565b50505050905090810190601f168015620022295780820380516001836020036101000a031916815260200191505b509850505050505050505060206040518083038186803b1580156200224d57600080fd5b505af415801562002262573d6000803e3d6000fd5b505050506040513d60208110156200227957600080fd5b505115156200228757600080fd5b84600160a060020a031663502341738c8c8c8c6040518563ffffffff1660e060020a0281526004018085600160a060020a0316600160a060020a0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156200230f578181015183820152602001620022f5565b50505050905090810190601f1680156200233d5780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b1580156200236057600080fd5b505af115801562002375573d6000803e3d6000fd5b505050506040513d60208110156200238c57600080fd5b5051925082156200250057604080517fb57ab3ac00000000000000000000000000000000000000000000000000000000815260016004820152600160a060020a038e16602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c419163b57ab3ac916044808301926020929190829003018186803b1580156200241257600080fd5b505af415801562002427573d6000803e3d6000fd5b505050506040513d60208110156200243e57600080fd5b810190808051906020019092919050505050600660008c600160a060020a0316600160a060020a031681526020019081526020016000208c90806001815401808255809150509060018203906000526020600020016000909192909190916101000a815481600160a060020a030219169083600160a060020a03160217905550508a600160a060020a031685600160a060020a03167f83cce77ef1950fd47994e9ab4fa3263f250200e45f9133f74375d8c1fd072fd860405160405180910390a35b50909a9950505050505050505050565b606081600160a060020a03811615156200252957600080fd5b600160a060020a0381163014156200254057600080fd5b600160a060020a0383166000908152600760209081526040918290208054835181840281018401909452808452909183018282801562000b3557602002820191906000526020600020908154600160a060020a0316815260019091019060200180831162000b16575050505050915050919050565b606060036001018054806020026020016040519081016040528092919081815260200182805480156200261257602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311620025f3575b505050505090505b90565b60066020528160005260406000208181548110151562000b8157fe5b6000805481908190600160a060020a031633146200265657600080fd5b600092505b8351831015620027a65783838151811015156200267457fe5b6020908102909101810151604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051919450600160a060020a038516926370a08231926024808401938290030181600087803b158015620026df57600080fd5b505af1158015620026f4573d6000803e3d6000fd5b505050506040513d60208110156200270b57600080fd5b5051600080546040805160e060020a63a9059cbb028152600160a060020a0392831660048201526024810185905290519394509085169263a9059cbb92604480840193602093929083900390910190829087803b1580156200276c57600080fd5b505af115801562002781573d6000803e3d6000fd5b505050506040513d60208110156200279857600080fd5b50506001909201916200265b565b600054600160a060020a0316ff5b600080548190600160a060020a03163314620027cf57600080fd5b60005460a060020a900460ff1615620027e757600080fd5b85600160a060020a0381161515620027fe57600080fd5b600160a060020a0381163014156200281557600080fd5b600160a060020a038781166000818152600860209081526040918290205482517fb57ab3ac0000000000000000000000000000000000000000000000000000000081526003600482015260248101949094529151919093161594507372ae13d70f65c56e59eb63993605abef1ecb9c419263b57ab3ac9260448082019391829003018186803b158015620028a857600080fd5b505af4158015620028bd573d6000803e3d6000fd5b505050506040513d6020811015620028d457600080fd5b50511515620028e257600080fd5b60408051608081018252600160a060020a0389811680835260208084018b81528486018b9052606085018a9052600092835260088252949091208351815473ffffffffffffffffffffffffffffffffffffffff19169316929092178255925180519293919262002959926001850192019062003b40565b50604082015180516200297791600284019160209091019062003b40565b50606082015180516200299591600384019160209091019062003b40565b509050508115620029da57604051600160a060020a038816907f1e59e06fbc9b065c65d072c1f7a2ed1d81154e6e57768747c6c082207dca730890600090a262002a0f565b604051600160a060020a038816907f9db0a73cad02bbf95f84090f7c99969d3a1cf17d5da896752289967f9f80a58490600090a25b5060019695505050505050565b60056020528160005260406000208181548110151562000b8157fe5b6060600180018054806020026020016040519081016040528092919081815260200182805480156200261257602002820191906000526020600020908154600160a060020a03168152600190910190602001808311620025f3575050505050905090565b60008054819060a060020a900460ff161562002ab757600080fd5b600d5486101562002ac757600080fd5b600c54604080517fdd62ed3e00000000000000000000000000000000000000000000000000000000815233600482015230602482015290518892600160a060020a03169163dd62ed3e9160448083019260209291908290030181600087803b15801562002b3357600080fd5b505af115801562002b48573d6000803e3d6000fd5b505050506040513d602081101562002b5f57600080fd5b5051101562002b6d57600080fd5b3389898988888862002b7e62003bc5565b8088600160a060020a0316600160a060020a03168152602001806020018060200187815260200180602001806020018060200186810386528c818151815260200191508051906020019080838360005b8381101562002be857818101518382015260200162002bce565b50505050905090810190601f16801562002c165780820380516001836020036101000a031916815260200191505b5086810385528b5181528b516020918201918d019080838360005b8381101562002c4b57818101518382015260200162002c31565b50505050905090810190601f16801562002c795780820380516001836020036101000a031916815260200191505b5086810384528951815289516020918201918b019080838360005b8381101562002cae57818101518382015260200162002c94565b50505050905090810190601f16801562002cdc5780820380516001836020036101000a031916815260200191505b5086810383528851815288516020918201918a019080838360005b8381101562002d1157818101518382015260200162002cf7565b50505050905090810190601f16801562002d3f5780820380516001836020036101000a031916815260200191505b50868103825287518152875160209182019189019080838360005b8381101562002d7457818101518382015260200162002d5a565b50505050905090810190601f16801562002da25780820380516001836020036101000a031916815260200191505b509c50505050505050505050505050604051809103906000f08015801562002dce573d6000803e3d6000fd5b50600c54604080517f23b872dd000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018a90529051929350600160a060020a03909116916323b872dd916064808201926020929091908290030181600087803b15801562002e4657600080fd5b505af115801562002e5b573d6000803e3d6000fd5b505050506040513d602081101562002e7257600080fd5b5050336000818152600b60209081526040808320600160a060020a0386168085529083528184208b90559383526007825280832080546001818101835591855283852001805473ffffffffffffffffffffffffffffffffffffffff1916861790558484526009909252808320805460ff1916909217909155517fcf6ea478d30b7e2b0d188cd4bc726f7e42c48dd94081b929ae8f03b8743f02d99190a298975050505050505050565b600d5481565b600054600160a060020a0316331462002f3957600080fd5b62002f448162003a4f565b50565b60008054600160a060020a0316331462002f6057600080fd5b60005460a060020a900460ff161562002f7857600080fd5b81600160a060020a038116151562002f8f57600080fd5b600160a060020a03811630141562002fa657600080fd5b604080517f7d98ebde00000000000000000000000000000000000000000000000000000000815260036004820152600160a060020a038516602482015290517372ae13d70f65c56e59eb63993605abef1ecb9c4191637d98ebde916044808301926020929190829003018186803b1580156200302157600080fd5b505af415801562003036573d6000803e3d6000fd5b505050506040513d60208110156200304d57600080fd5b505115156200305b57600080fd5b604051600160a060020a038416907fd2df117cdff329511dba7edac459dd05c2b14dc4c88ea1faf058c15de773b43390600090a250600192915050565b6000805b600582101562003136576000838360058110620030b557fe5b6020020151600160a060020a03161415620030cf57600080fd5b50600181015b60058110156200312a57828160058110620030ec57fe5b6020020151600160a060020a03168383600581106200310757fe5b6020020151600160a060020a031614156200312157600080fd5b600101620030d5565b6001909101906200309c565b505050565b600080600080600080600080600060149054906101000a900460ff161515156200316457600080fd5b89600160a060020a0316637150d8ae6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015620031a357600080fd5b505af1158015620031b8573d6000803e3d6000fd5b505050506040513d6020811015620031cf57600080fd5b5051604080517f4372df99000000000000000000000000000000000000000000000000000000008152600160a060020a038c811660048301529151929a50908c1691634372df99916024808201926020929091908290030181600087803b1580156200323a57600080fd5b505af11580156200324f573d6000803e3d6000fd5b505050506040513d60208110156200326657600080fd5b5051600160a060020a03808a166000908152600b60209081526040808320938f168084529382528083205481517fa035b1fe0000000000000000000000000000000000000000000000000000000081529151959c509a50929363a035b1fe93600480820194918390030190829087803b158015620032e357600080fd5b505af1158015620032f8573d6000803e3d6000fd5b505050506040513d60208110156200330f57600080fd5b5051604080517f43ca78a2000000000000000000000000000000000000000000000000000000008152600160a060020a038a811660048301529151929750908c16916343ca78a29160248082019260009290919082900301818387803b1580156200337957600080fd5b505af11580156200338e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260a0811015620033b857600080fd5b8151602083015160408401516060850180519395929491939183019291640100000000811115620033e857600080fd5b82016020810184811115620033fc57600080fd5b81516401000000008111828201871017156200341757600080fd5b50949a506200343896508b95508a94505063ffffffff62003acd1692505050565b925062003446848762003ae1565b91506200345a838363ffffffff62003afb16565b90506200346e868363ffffffff62003afb16565b600b60008a600160a060020a0316600160a060020a0316815260200190815260200160002060008c600160a060020a0316600160a060020a0316815260200190815260200160002081905550600c60009054906101000a9004600160a060020a0316600160a060020a03166323b872dd8930846040518463ffffffff1660e060020a0281526004018084600160a060020a0316600160a060020a0316815260200183600160a060020a0316600160a060020a031681526020018281526020019350505050602060405180830381600087803b1580156200354d57600080fd5b505af115801562003562573d6000803e3d6000fd5b505050506040513d60208110156200357957600080fd5b505115156200358757600080fd5b600160a060020a038089166000908152600a602090815260408083208e851684528252808320938d1683529290522054620035c9908463ffffffff62003acd16565b600160a060020a039889166000908152600a602090815260408083209d8c1683529c81528c82209b909a16815299909852505050959094209290925550505050565b60008054819081908190819060a060020a900460ff16156200362c57600080fd5b8a600160a060020a031663a035b1fe6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156200366b57600080fd5b505af115801562003680573d6000803e3d6000fd5b505050506040513d60208110156200369757600080fd5b5051604080517f43ca78a2000000000000000000000000000000000000000000000000000000008152600160a060020a038b811660048301529151929750908d16916343ca78a29160248082019260009290919082900301818387803b1580156200370157600080fd5b505af115801562003716573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260a08110156200374057600080fd5b81516020830151604084015160608501805193959294919391830192916401000000008111156200377057600080fd5b820160208101848111156200378457600080fd5b81516401000000008111828201871017156200379f57600080fd5b50949a50620037c096508b95508a94505063ffffffff62003acd1692505050565b925082600a60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a0316815260200190815260200160002054101515156200383d57600080fd5b600160a060020a03808b166000908152600a602090815260408083208f851684528252808320938d16835292905220546200387f908463ffffffff62003afb16565b600a60008c600160a060020a0316600160a060020a0316815260200190815260200160002060008d600160a060020a0316600160a060020a0316815260200190815260200160002060008b600160a060020a0316600160a060020a031681526020019081526020016000208190555086620038fb5789620038fd565b875b91508615806200390a5750855b62003916578962003918565b885b600c546040805160e060020a63a9059cbb028152600160a060020a03868116600483015260248201899052915193945091169163a9059cbb916044808201926020929091908290030181600087803b1580156200397457600080fd5b505af115801562003989573d6000803e3d6000fd5b505050506040513d6020811015620039a057600080fd5b50511515620039ae57600080fd5b600c546040805160e060020a63a9059cbb028152600160a060020a038481166004830152602482018990529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801562003a0857600080fd5b505af115801562003a1d573d6000803e3d6000fd5b505050506040513d602081101562003a3457600080fd5b5051151562003a4257600080fd5b5050505050505050505050565b600160a060020a038116151562003a6557600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b8181018281101562003adb57fe5b92915050565b600081831062003af2578162003af4565b825b9392505050565b60008282111562003b0857fe5b50900390565b6080604051908101604052806000600160a060020a031681526020016060815260200160608152602001606081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1062003b8357805160ff191683800117855562003bb3565b8280016001018555821562003bb3579182015b8281111562003bb357825182559160200191906001019062003b96565b5062003bc192915062003bd6565b5090565b604051611aaa8062003bf483390190565b6200261a91905b8082111562003bc1576000815560010162003bdd560060806040523480156200001157600080fd5b5060405162001aaa38038062001aaa83398101604090815281516020830151918301516060840151608085015160a086015160c087015160008054600160a060020a0319163317905594969586019593840194929391820192908201910186600160a060020a03811615156200008657600080fd5b600160a060020a0381163014156200009d57600080fd5b8251600010620000ac57600080fd5b8151600010620000bb57600080fd5b60018054600160a060020a031916600160a060020a038a161790558651620000eb9060029060208a01906200017d565b508551620001019060039060208901906200017d565b50600485905583516200011c9060059060208701906200017d565b508251620001329060069060208601906200017d565b508151620001489060079060208501906200017d565b50506008805468ff00000000ffffffff19164263ffffffff161767ffffffff0000000019169055506200022295505050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620001c057805160ff1916838001178555620001f0565b82800160010185558215620001f0579182015b82811115620001f0578251825591602001919060010190620001d3565b50620001fe92915062000202565b5090565b6200021f91905b80821115620001fe576000815560010162000209565b90565b61187880620002326000396000f3006080604052600436106101485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632728e28b811461014d5780634372df991461018657806343ca78a2146101c357806343d726d61461029657806343dcbc86146102bf57806350234173146102e0578063600f1f2b1461034c5780636d4b76d51461037a578063715018a6146103925780637150d8ae146103a95780637d4ccb14146103be5780638da5cb5b1461044857806396661b041461045d57806396e8150a14610483578063a035b1fe1461051b578063b1f4ff9014610542578063c081efc114610557578063cee26ed514610578578063cf09e0d014610590578063cf317b7e146105a5578063d778ce3c14610679578063ec9359401461068e578063f2fde38b146106a3578063f678462f146106c4578063ffaef25e146106d9575b600080fd5b34801561015957600080fd5b50610162610748565b6040518082600281111561017257fe5b60ff16815260200191505060405180910390f35b34801561019257600080fd5b506101a7600160a060020a036004351661075d565b60408051600160a060020a039092168252519081900360200190f35b3480156101cf57600080fd5b506101e4600160a060020a03600435166108c0565b6040518086600160a060020a0316600160a060020a03168152602001858152602001848152602001806020018363ffffffff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561025757818101518382015260200161023f565b50505050905090810190601f1680156102845780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b3480156102a257600080fd5b506102ab610a0c565b604080519115158252519081900360200190f35b3480156102cb57600080fd5b506102ab600160a060020a0360043516610aa7565b3480156102ec57600080fd5b50604080516020601f6064356004818101359283018490048402850184019095528184526102ab94600160a060020a038135169460248035956044359536956084949301918190840183828082843750949750610afd9650505050505050565b34801561035857600080fd5b50610361610c86565b6040805163ffffffff9092168252519081900360200190f35b34801561038657600080fd5b506101a7600435610c9a565b34801561039e57600080fd5b506103a7610cc2565b005b3480156103b557600080fd5b506101a7610d2e565b3480156103ca57600080fd5b506103d3610d3d565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561040d5781810151838201526020016103f5565b50505050905090810190601f16801561043a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561045457600080fd5b506101a7610dcb565b34801561046957600080fd5b506102ab600160a060020a03600435166024351515610dda565b34801561048f57600080fd5b506104a4600160a060020a0360043516610f54565b60408051600160a060020a038716815263ffffffff80861692820192909252908316606082015260208101608082018360028111156104df57fe5b60ff168152602001828103825286818151815260200191508051906020019080838360008381101561025757818101518382015260200161023f565b34801561052757600080fd5b50610530611033565b60408051918252519081900360200190f35b34801561054e57600080fd5b506103d3611039565b34801561056357600080fd5b506102ab600160a060020a0360043516611091565b34801561058457600080fd5b506101a76004356110e7565b34801561059c57600080fd5b506103616110f5565b3480156105b157600080fd5b506105c6600160a060020a0360043516611101565b60408051600160a060020a038089168252871660208083019190915263ffffffff80871660608401528516608083015260a0820184905260c0928201838152875193830193909352865191929160e084019188019080838360005b83811015610639578181015183820152602001610621565b50505050905090810190601f1680156106665780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390f35b34801561068557600080fd5b506103d361129e565b34801561069a57600080fd5b506103d36112f9565b3480156106af57600080fd5b506103a7600160a060020a0360043516611354565b3480156106d057600080fd5b506103d3611377565b3480156106e557600080fd5b50604080516020600460443581810135601f81018490048402850184019095528484526102ab948235600160a060020a03908116956024803590921695369594606494929301919081908401838280828437509497506113d29650505050505050565b60085468010000000000000000900460ff1681565b6000610767611758565b82600160a060020a038116151561077d57600080fd5b600160a060020a03811630141561079357600080fd5b61079c84611091565b15156107a757600080fd5b600160a060020a03848116600090815260096020908152604091829020825160a08101845281549094168452600180820180548551600261010094831615949094026000190190911692909204601f81018590048502830185019095528482529193858401939192918301828280156108615780601f1061083657610100808354040283529160200191610861565b820191906000526020600020905b81548152906001019060200180831161084457829003601f168201915b505050918352505060028281015463ffffffff8082166020850152640100000000820416604084015260609092019168010000000000000000900460ff16908111156108a957fe5b60028111156108b457fe5b90525051949350505050565b6000806000606060006108d1611785565b86600160a060020a03811615156108e757600080fd5b600160a060020a0381163014156108fd57600080fd5b61090688610aa7565b151561091157600080fd5b600160a060020a0388166000908152600a6020908152604091829020825160808101845281548152600180830154828501526002808401805487519381161561010002600019011691909104601f810186900486028301860187528083529295939493860193919290918301828280156109cc5780601f106109a1576101008083540402835291602001916109cc565b820191906000526020600020905b8154815290600101906020018083116109af57829003601f168201915b50505091835250506003919091015463ffffffff1660209182015281519082015160408301516060909301519a9b919a9099509197509095509350505050565b60008054600160a060020a03163314610a2457600080fd5b600260085468010000000000000000900460ff166002811115610a4357fe5b1415610a4e57600080fd5b600854640100000000900463ffffffff1615610a6957600080fd5b506008805468ff00000000000000001916680200000000000000001767ffffffff0000000019166401000000004263ffffffff160217905560015b90565b600081600160a060020a0381161515610abf57600080fd5b600160a060020a038116301415610ad557600080fd5b5050600160a060020a03166000908152600a602052604090206003015463ffffffff16151590565b60008054600160a060020a03163314610b1557600080fd5b84600160a060020a0381161515610b2b57600080fd5b600160a060020a038116301415610b4157600080fd5b600854640100000000900463ffffffff1615610b5c57600080fd5b6064851115610b6a57600080fd5b610b7386610aa7565b15610b7d57600080fd5b60408051608081018252868152602080820187815282840187815263ffffffff42166060850152600160a060020a038b166000908152600a845294909420835181559051600182015592518051929392610bdd92600285019201906117b4565b50606091909101516003909101805463ffffffff191663ffffffff909216919091179055600c8054600181810183556000929092527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c701805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0389161790556008805468ff000000000000000019166801000000000000000083021790555060019695505050505050565b600854640100000000900463ffffffff1681565b600c805482908110610ca857fe5b600091825260209091200154600160a060020a0316905081565b600054600160a060020a03163314610cd957600080fd5b60008054604051600160a060020a03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600154600160a060020a031681565b6007805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b820191906000526020600020905b815481529060010190602001808311610da657829003601f168201915b505050505081565b600054600160a060020a031681565b60008054600160a060020a03163314610df257600080fd5b82600160a060020a0381161515610e0857600080fd5b600160a060020a038116301415610e1e57600080fd5b600260085468010000000000000000900460ff166002811115610e3d57fe5b1415610e4857600080fd5b600854640100000000900463ffffffff1615610e6357600080fd5b610e6c84611091565b1515610e7757600080fd5b6000600160a060020a038516600090815260096020526040902060029081015468010000000000000000900460ff1690811115610eb057fe5b14610eba57600080fd5b82610ec6576001610ec9565b60025b600160a060020a038516600090815260096020526040902060029081018054909168ff0000000000000000199091169068010000000000000000908490811115610f0f57fe5b0217905550505050600160a060020a03166000908152600960205260409020600201805467ffffffff0000000019166401000000004263ffffffff1602179055600190565b6009602090815260009182526040918290208054600180830180548651600261010094831615949094026000190190911692909204601f8101869004860283018601909652858252600160a060020a03909216949293909290830182828015610ffe5780601f10610fd357610100808354040283529160200191610ffe565b820191906000526020600020905b815481529060010190602001808311610fe157829003601f168201915b5050506002909301549192505063ffffffff8082169164010000000081049091169060ff680100000000000000009091041685565b60045481565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b600081600160a060020a03811615156110a957600080fd5b600160a060020a0381163014156110bf57600080fd5b5050600160a060020a031660009081526009602052604090206002015463ffffffff16151590565b600b805482908110610ca857fe5b60085463ffffffff1681565b60008060606000806000611113611758565b87600160a060020a038116151561112957600080fd5b600160a060020a03811630141561113f57600080fd5b61114889611091565b151561115357600080fd5b600160a060020a03898116600090815260096020908152604091829020825160a08101845281549094168452600180820180548551600261010094831615949094026000190190911692909204601f810185900485028301850190955284825291938584019391929183018282801561120d5780601f106111e25761010080835404028352916020019161120d565b820191906000526020600020905b8154815290600101906020018083116111f057829003601f168201915b505050918352505060028281015463ffffffff8082166020850152640100000000820416604084015260609092019168010000000000000000900460ff169081111561125557fe5b600281111561126057fe5b8152505091508882600001518360200151846040015185606001516112888760800151611628565b949e939d50919b50995097509095509350505050565b6006805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b6003805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b600054600160a060020a0316331461136b57600080fd5b611374816116db565b50565b6005805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610dc35780601f10610d9857610100808354040283529160200191610dc3565b60008054600160a060020a031633146113ea57600080fd5b83600160a060020a038116151561140057600080fd5b600160a060020a03811630141561141657600080fd5b83600160a060020a038116151561142c57600080fd5b600160a060020a03811630141561144257600080fd5b600160085468010000000000000000900460ff16600281111561146157fe5b1461146b57600080fd5b600854640100000000900463ffffffff161561148657600080fd5b61148f86611091565b1561149957600080fd5b6114a285610aa7565b15156114ad57600080fd5b60a06040519081016040528086600160a060020a031681526020018581526020014263ffffffff168152602001600063ffffffff168152602001600060028111156114f457fe5b9052600160a060020a0387811660009081526009602090815260409091208351815473ffffffffffffffffffffffffffffffffffffffff1916931692909217825582810151805161154b92600185019201906117b4565b50604082015160028083018054606086015163ffffffff9081166401000000000267ffffffff00000000199190951663ffffffff199092169190911716929092178083556080850151929168ff00000000000000001990911690680100000000000000009084908111156115bb57fe5b021790555050600b8054600181810183556000929092527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db9018054600160a060020a038a1673ffffffffffffffffffffffffffffffffffffffff1990911617905593505050509392505050565b60008082600281111561163757fe5b141561166457507f44617461526573706f6e736541646465640000000000000000000000000000006116d6565b600182600281111561167257fe5b141561169f57507f526566756e646564546f427579657200000000000000000000000000000000006116d6565b60028260028111156116ad57fe5b141561014857507f5472616e73616374696f6e436f6d706c657465640000000000000000000000005b919050565b600160a060020a03811615156116f057600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6040805160a081018252600080825260606020830181905292820181905291810182905290608082015290565b608060405190810160405280600081526020016000815260200160608152602001600063ffffffff1681525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106117f557805160ff1916838001178555611822565b82800160010185558215611822579182015b82811115611822578251825591602001919060010190611807565b5061182e929150611832565b5090565b610aa491905b8082111561182e57600081556001016118385600a165627a7a7230582090b9454469f2b12ba07c11a2c481de23eda8cd46e7fabdcae09b2ea5d54626870029a165627a7a723058208b119373d135bf2e3226c2a7685f7a2296b836fae440567bb8e62bb5532818d200290000000000000000000000003f17dd476faf0a4855572f0b6ed5115d9bba22ad0000000000000000000000000183b6ffc017ac4f767e460886291d09229a848b

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

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


   Library Used
CryptoUtils : 0x48819464877341cb7e0bbd91e0c268016ae5e6ad
MultiMap : 0x72ae13d70f65c56e59eb63993605abef1ecb9c41

   Swarm Source:
bzzr://8b119373d135bf2e3226c2a7685f7a2296b836fae440567bb8e62bb5532818d2

 

View All
Block Age transaction Difficulty GasUsed Reward
View All
Block Age UncleNumber Difficulty GasUsed Reward
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.