ETH Price: $2,458.63 (+0.51%)

Contract

0xceec7aAA57e3a77c73A9954b9b7D5B32ab688318
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Attest For79858132019-06-19 1:35:171937 days ago1560908117IN
Bloom: Attestation Logic
0 ETH0.000109221
Attest For79858132019-06-19 1:35:171937 days ago1560908117IN
Bloom: Attestation Logic
0 ETH0.000109241
Attest For79858122019-06-19 1:35:071937 days ago1560908107IN
Bloom: Attestation Logic
0 ETH0.000109311
Attest For79858112019-06-19 1:34:591937 days ago1560908099IN
Bloom: Attestation Logic
0 ETH0.000109241
Attest For79858112019-06-19 1:34:591937 days ago1560908099IN
Bloom: Attestation Logic
0 ETH0.000109221
Attest For79858112019-06-19 1:34:591937 days ago1560908099IN
Bloom: Attestation Logic
0 ETH0.000109311
Attest For79858082019-06-19 1:34:201937 days ago1560908060IN
Bloom: Attestation Logic
0 ETH0.000109271
Attest For79858062019-06-19 1:34:051937 days ago1560908045IN
Bloom: Attestation Logic
0 ETH0.00010911
Attest For79858062019-06-19 1:34:051937 days ago1560908045IN
Bloom: Attestation Logic
0 ETH0.00010921
Attest For79858042019-06-19 1:33:431937 days ago1560908023IN
Bloom: Attestation Logic
0 ETH0.000109241
Attest For79858032019-06-19 1:33:401937 days ago1560908020IN
Bloom: Attestation Logic
0 ETH0.000109221
Attest For79857952019-06-19 1:31:131937 days ago1560907873IN
Bloom: Attestation Logic
0 ETH0.000109291
Attest For79857942019-06-19 1:31:061937 days ago1560907866IN
Bloom: Attestation Logic
0 ETH0.00010911
Attest For79857942019-06-19 1:31:061937 days ago1560907866IN
Bloom: Attestation Logic
0 ETH0.000109311
Attest For79857932019-06-19 1:30:591937 days ago1560907859IN
Bloom: Attestation Logic
0 ETH0.000109221
Attest For79857902019-06-19 1:30:401937 days ago1560907840IN
Bloom: Attestation Logic
0 ETH0.000109221
Attest For79857822019-06-19 1:29:211937 days ago1560907761IN
Bloom: Attestation Logic
0 ETH0.000109181
Attest For79857782019-06-19 1:28:551937 days ago1560907735IN
Bloom: Attestation Logic
0 ETH0.000120171.1
Attest For76077382019-04-21 0:28:181996 days ago1555806498IN
Bloom: Attestation Logic
0 ETH0.000327813
Attest For76077372019-04-21 0:28:001996 days ago1555806480IN
Bloom: Attestation Logic
0 ETH0.000327623
Attest For76077372019-04-21 0:28:001996 days ago1555806480IN
Bloom: Attestation Logic
0 ETH0.000327933
Attest For76077352019-04-21 0:27:351996 days ago1555806455IN
Bloom: Attestation Logic
0 ETH0.000327433
Attest For76077352019-04-21 0:27:351996 days ago1555806455IN
Bloom: Attestation Logic
0 ETH0.000327743
Attest For76077352019-04-21 0:27:351996 days ago1555806455IN
Bloom: Attestation Logic
0 ETH0.000327553
Attest For76077332019-04-21 0:27:081996 days ago1555806428IN
Bloom: Attestation Logic
0 ETH0.000327813
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AttestationLogic

Compiler Version
v0.4.24+commit.e67f0147

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2018-12-04
*/

pragma solidity 0.4.24;



/**
 * @dev Pulled from OpenZeppelin: https://git.io/vbaRf
 *   When this is in a public release we will switch to not vendoring this file
 *
 * @title Eliptic curve signature operations
 *
 * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
 */

library ECRecovery {

  /**
   * @dev Recover signer address from a message by using his 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) public pure returns (address) {
    bytes32 r;
    bytes32 s;
    uint8 v;

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

    // Extracting these values isn't possible without assembly
    // solhint-disable no-inline-assembly
    // Divide the signature in r, s and v variables
    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 {
      return ecrecover(hash, v, r, s);
    }
  }

}


/**
 * @title SigningLogic is contract implementing signature recovery from typed data signatures
 * @notice Recovers signatures based on the SignTypedData implementation provided by ethSigUtil
 * @dev This contract is inherited by other contracts.
 */
contract SigningLogic {

  // Signatures contain a nonce to make them unique. usedSignatures tracks which signatures
  //  have been used so they can't be replayed
  mapping (bytes32 => bool) public usedSignatures;

  function burnSignatureDigest(bytes32 _signatureDigest, address _sender) internal {
    bytes32 _txDataHash = keccak256(abi.encode(_signatureDigest, _sender));
    require(!usedSignatures[_txDataHash], "Signature not unique");
    usedSignatures[_txDataHash] = true;
  }

  bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256(
    "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
  );

  bytes32 constant ATTESTATION_REQUEST_TYPEHASH = keccak256(
    "AttestationRequest(bytes32 dataHash,bytes32 nonce)"
  );

  bytes32 constant ADD_ADDRESS_TYPEHASH = keccak256(
    "AddAddress(address addressToAdd,bytes32 nonce)"
  );

  bytes32 constant REMOVE_ADDRESS_TYPEHASH = keccak256(
    "RemoveAddress(address addressToRemove,bytes32 nonce)"
  );

  bytes32 constant PAY_TOKENS_TYPEHASH = keccak256(
    "PayTokens(address sender,address receiver,uint256 amount,bytes32 nonce)"
  );

  bytes32 constant RELEASE_TOKENS_FOR_TYPEHASH = keccak256(
    "ReleaseTokensFor(address sender,uint256 amount,bytes32 nonce)"
  );

  bytes32 constant ATTEST_FOR_TYPEHASH = keccak256(
    "AttestFor(address subject,address requester,uint256 reward,bytes32 dataHash,bytes32 requestNonce)"
  );

  bytes32 constant CONTEST_FOR_TYPEHASH = keccak256(
    "ContestFor(address requester,uint256 reward,bytes32 requestNonce)"
  );

  bytes32 constant REVOKE_ATTESTATION_FOR_TYPEHASH = keccak256(
    "RevokeAttestationFor(bytes32 link,bytes32 nonce)"
  );

  bytes32 constant VOTE_FOR_TYPEHASH = keccak256(
    "VoteFor(uint16 choice,address voter,bytes32 nonce,address poll)"
  );

  bytes32 constant LOCKUP_TOKENS_FOR_TYPEHASH = keccak256(
    "LockupTokensFor(address sender,uint256 amount,bytes32 nonce)"
  );

  bytes32 DOMAIN_SEPARATOR;

  constructor (string name, string version, uint256 chainId) public {
    DOMAIN_SEPARATOR = hash(EIP712Domain({
      name: name,
      version: version,
      chainId: chainId,
      verifyingContract: this
    }));
  }

  struct EIP712Domain {
      string  name;
      string  version;
      uint256 chainId;
      address verifyingContract;
  }

  function hash(EIP712Domain eip712Domain) private pure returns (bytes32) {
    return keccak256(abi.encode(
      EIP712DOMAIN_TYPEHASH,
      keccak256(bytes(eip712Domain.name)),
      keccak256(bytes(eip712Domain.version)),
      eip712Domain.chainId,
      eip712Domain.verifyingContract
    ));
  }

  struct AttestationRequest {
      bytes32 dataHash;
      bytes32 nonce;
  }

  function hash(AttestationRequest request) private pure returns (bytes32) {
    return keccak256(abi.encode(
      ATTESTATION_REQUEST_TYPEHASH,
      request.dataHash,
      request.nonce
    ));
  }

  struct AddAddress {
      address addressToAdd;
      bytes32 nonce;
  }

  function hash(AddAddress request) private pure returns (bytes32) {
    return keccak256(abi.encode(
      ADD_ADDRESS_TYPEHASH,
      request.addressToAdd,
      request.nonce
    ));
  }

  struct RemoveAddress {
      address addressToRemove;
      bytes32 nonce;
  }

  function hash(RemoveAddress request) private pure returns (bytes32) {
    return keccak256(abi.encode(
      REMOVE_ADDRESS_TYPEHASH,
      request.addressToRemove,
      request.nonce
    ));
  }

  struct PayTokens {
      address sender;
      address receiver;
      uint256 amount;
      bytes32 nonce;
  }

  function hash(PayTokens request) private pure returns (bytes32) {
    return keccak256(abi.encode(
      PAY_TOKENS_TYPEHASH,
      request.sender,
      request.receiver,
      request.amount,
      request.nonce
    ));
  }

  struct AttestFor {
      address subject;
      address requester;
      uint256 reward;
      bytes32 dataHash;
      bytes32 requestNonce;
  }

  function hash(AttestFor request) private pure returns (bytes32) {
    return keccak256(abi.encode(
      ATTEST_FOR_TYPEHASH,
      request.subject,
      request.requester,
      request.reward,
      request.dataHash,
      request.requestNonce
    ));
  }

  struct ContestFor {
      address requester;
      uint256 reward;
      bytes32 requestNonce;
  }

  function hash(ContestFor request) private pure returns (bytes32) {
    return keccak256(abi.encode(
      CONTEST_FOR_TYPEHASH,
      request.requester,
      request.reward,
      request.requestNonce
    ));
  }

  struct RevokeAttestationFor {
      bytes32 link;
      bytes32 nonce;
  }

  function hash(RevokeAttestationFor request) private pure returns (bytes32) {
    return keccak256(abi.encode(
      REVOKE_ATTESTATION_FOR_TYPEHASH,
      request.link,
      request.nonce
    ));
  }

  struct VoteFor {
      uint16 choice;
      address voter;
      bytes32 nonce;
      address poll;
  }

  function hash(VoteFor request) private pure returns (bytes32) {
    return keccak256(abi.encode(
      VOTE_FOR_TYPEHASH,
      request.choice,
      request.voter,
      request.nonce,
      request.poll
    ));
  }

  struct LockupTokensFor {
    address sender;
    uint256 amount;
    bytes32 nonce;
  }

  function hash(LockupTokensFor request) private pure returns (bytes32) {
    return keccak256(abi.encode(
      LOCKUP_TOKENS_FOR_TYPEHASH,
      request.sender,
      request.amount,
      request.nonce
    ));
  }

  struct ReleaseTokensFor {
    address sender;
    uint256 amount;
    bytes32 nonce;
  }

  function hash(ReleaseTokensFor request) private pure returns (bytes32) {
    return keccak256(abi.encode(
      RELEASE_TOKENS_FOR_TYPEHASH,
      request.sender,
      request.amount,
      request.nonce
    ));
  }

  function generateRequestAttestationSchemaHash(
    bytes32 _dataHash,
    bytes32 _nonce
  ) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        DOMAIN_SEPARATOR,
        hash(AttestationRequest(
          _dataHash,
          _nonce
        ))
      )
      );
  }

  function generateAddAddressSchemaHash(
    address _addressToAdd,
    bytes32 _nonce
  ) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        DOMAIN_SEPARATOR,
        hash(AddAddress(
          _addressToAdd,
          _nonce
        ))
      )
      );
  }

  function generateRemoveAddressSchemaHash(
    address _addressToRemove,
    bytes32 _nonce
  ) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        DOMAIN_SEPARATOR,
        hash(RemoveAddress(
          _addressToRemove,
          _nonce
        ))
      )
      );
  }

  function generatePayTokensSchemaHash(
    address _sender,
    address _receiver,
    uint256 _amount,
    bytes32 _nonce
  ) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        DOMAIN_SEPARATOR,
        hash(PayTokens(
          _sender,
          _receiver,
          _amount,
          _nonce
        ))
      )
      );
  }

  function generateAttestForDelegationSchemaHash(
    address _subject,
    address _requester,
    uint256 _reward,
    bytes32 _dataHash,
    bytes32 _requestNonce
  ) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        DOMAIN_SEPARATOR,
        hash(AttestFor(
          _subject,
          _requester,
          _reward,
          _dataHash,
          _requestNonce
        ))
      )
      );
  }

  function generateContestForDelegationSchemaHash(
    address _requester,
    uint256 _reward,
    bytes32 _requestNonce
  ) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        DOMAIN_SEPARATOR,
        hash(ContestFor(
          _requester,
          _reward,
          _requestNonce
        ))
      )
      );
  }

  function generateRevokeAttestationForDelegationSchemaHash(
    bytes32 _link,
    bytes32 _nonce
  ) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        DOMAIN_SEPARATOR,
        hash(RevokeAttestationFor(
          _link,
          _nonce
        ))
      )
      );
  }

  function generateVoteForDelegationSchemaHash(
    uint16 _choice,
    address _voter,
    bytes32 _nonce,
    address _poll
  ) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        DOMAIN_SEPARATOR,
        hash(VoteFor(
          _choice,
          _voter,
          _nonce,
          _poll
        ))
      )
      );
  }

  function generateLockupTokensDelegationSchemaHash(
    address _sender,
    uint256 _amount,
    bytes32 _nonce
  ) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        DOMAIN_SEPARATOR,
        hash(LockupTokensFor(
          _sender,
          _amount,
          _nonce
        ))
      )
      );
  }

  function generateReleaseTokensDelegationSchemaHash(
    address _sender,
    uint256 _amount,
    bytes32 _nonce
  ) internal view returns (bytes32) {
    return keccak256(
      abi.encodePacked(
        "\x19\x01",
        DOMAIN_SEPARATOR,
        hash(ReleaseTokensFor(
          _sender,
          _amount,
          _nonce
        ))
      )
      );
  }

  function recoverSigner(bytes32 _hash, bytes _sig) internal pure returns (address) {
    address signer = ECRecovery.recover(_hash, _sig);
    require(signer != address(0));

    return signer;
  }
}
pragma solidity ^0.4.21;


/**
 * @title ERC20Basic
 * @dev Simpler version of ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/179
 */
contract ERC20Basic {
  function totalSupply() public view returns (uint256);
  function balanceOf(address who) public view returns (uint256);
  function transfer(address to, uint256 value) public returns (bool);
  event Transfer(address indexed from, address indexed to, uint256 value);
}


/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 */
contract ERC20 is ERC20Basic {
  function allowance(address owner, address spender) public view returns (uint256);
  function transferFrom(address from, address to, uint256 value) public returns (bool);
  function approve(address spender, uint256 value) public returns (bool);
  event Approval(address indexed owner, address indexed spender, uint256 value);
}


/**
 * @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) {
    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 SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure.
 * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
  function safeTransfer(ERC20Basic token, address to, uint256 value) internal {
    assert(token.transfer(to, value));
  }

  function safeTransferFrom(
    ERC20 token,
    address from,
    address to,
    uint256 value
  )
    internal
  {
    assert(token.transferFrom(from, to, value));
  }

  function safeApprove(ERC20 token, address spender, uint256 value) internal {
    assert(token.approve(spender, value));
  }
}


/**
 * @notice TokenEscrowMarketplace is an ERC20 payment channel that enables users to send BLT by exchanging signatures off-chain
 *  Users approve the contract address to transfer BLT on their behalf using the standard ERC20.approve function
 *  After approval, either the user or the contract admin initiates the transfer of BLT into the contract
 *  Once in the contract, users can send payments via a signed message to another user. 
 *  The signature transfers BLT from lockup to the recipient's balance
 *  Users can withdraw funds at any time. Or the admin can release them on the user's behalf
 *  
 *  BLT is stored in the contract by address
 *  
 *  Only the AttestationLogic contract is authorized to release funds once a jobs is complete
 */
contract TokenEscrowMarketplace is SigningLogic {
  using SafeERC20 for ERC20;
  using SafeMath for uint256;

  address public attestationLogic;

  mapping(address => uint256) public tokenEscrow;
  ERC20 public token;

  event TokenMarketplaceWithdrawal(address escrowPayer, uint256 amount);
  event TokenMarketplaceEscrowPayment(address escrowPayer, address escrowPayee, uint256 amount);
  event TokenMarketplaceDeposit(address escrowPayer, uint256 amount);

  /**
   * @notice The TokenEscrowMarketplace constructor initializes the interfaces to the other contracts
   * @dev Some actions are restricted to be performed by the attestationLogic contract.
   *  Signing logic is upgradeable in case the signTypedData spec changes
   * @param _token Address of BLT
   * @param _attestationLogic Address of current attestation logic contract
   */
  constructor(
    ERC20 _token,
    address _attestationLogic
    ) public SigningLogic("Bloom Token Escrow Marketplace", "2", 1) {
    token = _token;
    attestationLogic = _attestationLogic;
  }

  modifier onlyAttestationLogic() {
    require(msg.sender == attestationLogic);
    _;
  }

  /**
   * @notice Lockup tokens for set time period on behalf of user. Must be preceeded by approve
   * @dev Authorized by a signTypedData signature by sender
   *  Sigs can only be used once. They contain a unique nonce
   *  So an action can be repeated, with a different signature
   * @param _sender User locking up their tokens
   * @param _amount Tokens to lock up
   * @param _nonce Unique Id so signatures can't be replayed
   * @param _delegationSig Signed hash of these input parameters so an admin can submit this on behalf of a user
   */
  function moveTokensToEscrowLockupFor(
    address _sender,
    uint256 _amount,
    bytes32 _nonce,
    bytes _delegationSig
    ) external {
      validateLockupTokensSig(
        _sender,
        _amount,
        _nonce,
        _delegationSig
      );
      moveTokensToEscrowLockupForUser(_sender, _amount);
  }

  /**
   * @notice Verify lockup signature is valid
   * @param _sender User locking up their tokens
   * @param _amount Tokens to lock up
   * @param _nonce Unique Id so signatures can't be replayed
   * @param _delegationSig Signed hash of these input parameters so an admin can submit this on behalf of a user
   */
  function validateLockupTokensSig(
    address _sender,
    uint256 _amount,
    bytes32 _nonce,
    bytes _delegationSig
  ) private {
    bytes32 _signatureDigest = generateLockupTokensDelegationSchemaHash(_sender, _amount, _nonce);
    require(_sender == recoverSigner(_signatureDigest, _delegationSig), 'Invalid LockupTokens Signature');
    burnSignatureDigest(_signatureDigest, _sender);
  }

  /**
   * @notice Lockup tokens by user. Must be preceeded by approve
   * @param _amount Tokens to lock up
   */
  function moveTokensToEscrowLockup(uint256 _amount) external {
    moveTokensToEscrowLockupForUser(msg.sender, _amount);
  }

  /**
   * @notice Lockup tokens for set time. Must be preceeded by approve
   * @dev Private function called by appropriate public function
   * @param _sender User locking up their tokens
   * @param _amount Tokens to lock up
   */
  function moveTokensToEscrowLockupForUser(
    address _sender,
    uint256 _amount
    ) private {
    token.safeTransferFrom(_sender, this, _amount);
    addToEscrow(_sender, _amount);
  }

  /**
   * @notice Withdraw tokens from escrow back to requester
   * @dev Authorized by a signTypedData signature by sender
   *  Sigs can only be used once. They contain a unique nonce
   *  So an action can be repeated, with a different signature
   * @param _sender User withdrawing their tokens
   * @param _amount Tokens to withdraw
   * @param _nonce Unique Id so signatures can't be replayed
   * @param _delegationSig Signed hash of these input parameters so an admin can submit this on behalf of a user
   */
  function releaseTokensFromEscrowFor(
    address _sender,
    uint256 _amount,
    bytes32 _nonce,
    bytes _delegationSig
    ) external {
      validateReleaseTokensSig(
        _sender,
        _amount,
        _nonce,
        _delegationSig
      );
      releaseTokensFromEscrowForUser(_sender, _amount);
  }

  /**
   * @notice Verify lockup signature is valid
   * @param _sender User withdrawing their tokens
   * @param _amount Tokens to lock up
   * @param _nonce Unique Id so signatures can't be replayed
   * @param _delegationSig Signed hash of these input parameters so an admin can submit this on behalf of a user
   */
  function validateReleaseTokensSig(
    address _sender,
    uint256 _amount,
    bytes32 _nonce,
    bytes _delegationSig

  ) private {
    bytes32 _signatureDigest = generateReleaseTokensDelegationSchemaHash(_sender, _amount, _nonce);
    require(_sender == recoverSigner(_signatureDigest, _delegationSig), 'Invalid ReleaseTokens Signature');
    burnSignatureDigest(_signatureDigest, _sender);
  }

  /**
   * @notice Release tokens back to payer's available balance if lockup expires
   * @dev Token balance retreived by accountId. Can be different address from the one that deposited tokens
   * @param _amount Tokens to retreive from escrow
   */
  function releaseTokensFromEscrow(uint256 _amount) external {
    releaseTokensFromEscrowForUser(msg.sender, _amount);
  }

  /**
   * @notice Release tokens back to payer's available balance
   * @param _payer User retreiving tokens from escrow
   * @param _amount Tokens to retreive from escrow
   */
  function releaseTokensFromEscrowForUser(
    address _payer,
    uint256 _amount
    ) private {
      subFromEscrow(_payer, _amount);
      token.safeTransfer(_payer, _amount);
      emit TokenMarketplaceWithdrawal(_payer, _amount);
  }

  /**
   * @notice Pay from escrow of payer to available balance of receiever
   * @dev Private function to modify balances on payment
   * @param _payer User with tokens in escrow
   * @param _receiver User receiving tokens
   * @param _amount Tokens being sent
   */
  function payTokensFromEscrow(address _payer, address _receiver, uint256 _amount) private {
    subFromEscrow(_payer, _amount);
    token.safeTransfer(_receiver, _amount);
  }

  /**
   * @notice Pay tokens to receiver from payer's escrow given a valid signature
   * @dev Execution restricted to attestationLogic contract
   * @param _payer User paying tokens from escrow
   * @param _receiver User receiving payment
   * @param _amount Tokens being paid
   * @param _nonce Unique Id for sig to make it one-time-use
   * @param _paymentSig Signed parameters by payer authorizing payment
   */
  function requestTokenPayment(
    address _payer,
    address _receiver,
    uint256 _amount,
    bytes32 _nonce,
    bytes _paymentSig
    ) external onlyAttestationLogic {

    validatePaymentSig(
      _payer,
      _receiver,
      _amount,
      _nonce,
      _paymentSig
    );
    payTokensFromEscrow(_payer, _receiver, _amount);
    emit TokenMarketplaceEscrowPayment(_payer, _receiver, _amount);
  }

  /**
   * @notice Verify payment signature is valid
   * @param _payer User paying tokens from escrow
   * @param _receiver User receiving payment
   * @param _amount Tokens being paid
   * @param _nonce Unique Id for sig to make it one-time-use
   * @param _paymentSig Signed parameters by payer authorizing payment
   */
  function validatePaymentSig(
    address _payer,
    address _receiver,
    uint256 _amount,
    bytes32 _nonce,
    bytes _paymentSig

  ) private {
    bytes32 _signatureDigest = generatePayTokensSchemaHash(_payer, _receiver, _amount, _nonce);
    require(_payer == recoverSigner(_signatureDigest, _paymentSig), 'Invalid Payment Signature');
    burnSignatureDigest(_signatureDigest, _payer);
  }

  /**
   * @notice Helper function to add to escrow balance 
   * @param _from Account address for escrow mapping
   * @param _amount Tokens to lock up
   */
  function addToEscrow(address _from, uint256 _amount) private {
    tokenEscrow[_from] = tokenEscrow[_from].add(_amount);
    emit TokenMarketplaceDeposit(_from, _amount);
  }

  /**
   * Helper function to reduce escrow token balance of user
   */
  function subFromEscrow(address _from, uint256 _amount) private {
    require(tokenEscrow[_from] >= _amount);
    tokenEscrow[_from] = tokenEscrow[_from].sub(_amount);
  }
}

/**
 * @title Initializable
 * @dev The Initializable contract has an initializer address, and provides basic authorization control
 * only while in initialization mode. Once changed to production mode the inializer loses authority
 */
contract Initializable {
  address public initializer;
  bool public initializing;

  event InitializationEnded();

  /**
   * @dev The Initializable constructor sets the initializer to the provided address
   */
  constructor(address _initializer) public {
    initializer = _initializer;
    initializing = true;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyDuringInitialization() {
    require(msg.sender == initializer, 'Method can only be called by initializer');
    require(initializing, 'Method can only be called during initialization');
    _;
  }

  /**
   * @dev Allows the initializer to end the initialization period
   */
  function endInitialization() public onlyDuringInitialization {
    initializing = false;
    emit InitializationEnded();
  }

}


/**
 * @title AttestationLogic allows users to submit attestations given valid signatures
 * @notice Attestation Logic Logic provides a public interface for Bloom and
 *  users to submit attestations.
 */
contract AttestationLogic is Initializable, SigningLogic{
    TokenEscrowMarketplace public tokenEscrowMarketplace;

  /**
   * @notice AttestationLogic constructor sets the implementation address of all related contracts
   * @param _tokenEscrowMarketplace Address of marketplace holding tokens which are
   *  released to attesters upon completion of a job
   */
  constructor(
    address _initializer,
    TokenEscrowMarketplace _tokenEscrowMarketplace
    ) Initializable(_initializer) SigningLogic("Bloom Attestation Logic", "2", 1) public {
    tokenEscrowMarketplace = _tokenEscrowMarketplace;
  }

  event TraitAttested(
    address subject,
    address attester,
    address requester,
    bytes32 dataHash
    );
  event AttestationRejected(address indexed attester, address indexed requester);
  event AttestationRevoked(bytes32 link, address attester);
  event TokenEscrowMarketplaceChanged(address oldTokenEscrowMarketplace, address newTokenEscrowMarketplace);

  /**
   * @notice Function for attester to submit attestation from their own account) 
   * @dev Wrapper for attestForUser using msg.sender
   * @param _subject User this attestation is about
   * @param _requester User requesting and paying for this attestation in BLT
   * @param _reward Payment to attester from requester in BLT
   * @param _requesterSig Signature authorizing payment from requester to attester
   * @param _dataHash Hash of data being attested and nonce
   * @param _requestNonce Nonce in sig signed by subject and requester so they can't be replayed
   * @param _subjectSig Signed authorization from subject with attestation agreement
   */
  function attest(
    address _subject,
    address _requester,
    uint256 _reward,
    bytes _requesterSig,
    bytes32 _dataHash,
    bytes32 _requestNonce,
    bytes _subjectSig // Sig of subject with requester, attester, dataHash, requestNonce
  ) external {
    attestForUser(
      _subject,
      msg.sender,
      _requester,
      _reward,
      _requesterSig,
      _dataHash,
      _requestNonce,
      _subjectSig
    );
  }

  /**
   * @notice Submit attestation for a user in order to pay the gas costs
   * @dev Recover signer of delegation message. If attester matches delegation signature, add the attestation
   * @param _subject user this attestation is about
   * @param _attester user completing the attestation
   * @param _requester user requesting this attestation be completed and paying for it in BLT
   * @param _reward payment to attester from requester in BLT wei
   * @param _requesterSig signature authorizing payment from requester to attester
   * @param _dataHash hash of data being attested and nonce
   * @param _requestNonce Nonce in sig signed by subject and requester so they can't be replayed
   * @param _subjectSig signed authorization from subject with attestation agreement
   * @param _delegationSig signature authorizing attestation on behalf of attester
   */
  function attestFor(
    address _subject,
    address _attester,
    address _requester,
    uint256 _reward,
    bytes _requesterSig,
    bytes32 _dataHash,
    bytes32 _requestNonce,
    bytes _subjectSig, // Sig of subject with dataHash and requestNonce
    bytes _delegationSig
  ) external {
    // Confirm attester address matches recovered address from signature
    validateAttestForSig(_subject, _attester, _requester, _reward, _dataHash, _requestNonce, _delegationSig);
    attestForUser(
      _subject,
      _attester,
      _requester,
      _reward,
      _requesterSig,
      _dataHash,
      _requestNonce,
      _subjectSig
    );
  }

  /**
   * @notice Perform attestation
   * @dev Verify valid certainty level and user addresses
   * @param _subject user this attestation is about
   * @param _attester user completing the attestation
   * @param _requester user requesting this attestation be completed and paying for it in BLT
   * @param _reward payment to attester from requester in BLT wei
   * @param _requesterSig signature authorizing payment from requester to attester
   * @param _dataHash hash of data being attested and nonce
   * @param _requestNonce Nonce in sig signed by subject and requester so they can't be replayed
   * @param _subjectSig signed authorization from subject with attestation agreement
   */
  function attestForUser(
    address _subject,
    address _attester,
    address _requester,
    uint256 _reward,
    bytes _requesterSig,
    bytes32 _dataHash,
    bytes32 _requestNonce,
    bytes _subjectSig
    ) private {
    
    validateSubjectSig(
      _subject,
      _dataHash,
      _requestNonce,
      _subjectSig
    );

    emit TraitAttested(
      _subject,
      _attester,
      _requester,
      _dataHash
    );

    if (_reward > 0) {
      tokenEscrowMarketplace.requestTokenPayment(_requester, _attester, _reward, _requestNonce, _requesterSig);
    }
  }

  /**
   * @notice Function for attester to reject an attestation and receive payment 
   *  without associating the negative attestation with the subject's bloomId
   * @param _requester User requesting and paying for this attestation in BLT
   * @param _reward Payment to attester from requester in BLT
   * @param _requestNonce Nonce in sig signed by requester so it can't be replayed
   * @param _requesterSig Signature authorizing payment from requester to attester
   */
  function contest(
    address _requester,
    uint256 _reward,
    bytes32 _requestNonce,
    bytes _requesterSig
  ) external {
    contestForUser(
      msg.sender,
      _requester,
      _reward,
      _requestNonce,
      _requesterSig
    );
  }

  /**
   * @notice Function for attester to reject an attestation and receive payment 
   *  without associating the negative attestation with the subject's bloomId
   *  Perform on behalf of attester to pay gas fees
   * @param _requester User requesting and paying for this attestation in BLT
   * @param _attester user completing the attestation
   * @param _reward Payment to attester from requester in BLT
   * @param _requestNonce Nonce in sig signed by requester so it can't be replayed
   * @param _requesterSig Signature authorizing payment from requester to attester
   */
  function contestFor(
    address _attester,
    address _requester,
    uint256 _reward,
    bytes32 _requestNonce,
    bytes _requesterSig,
    bytes _delegationSig
  ) external {
    validateContestForSig(
      _attester,
      _requester,
      _reward,
      _requestNonce,
      _delegationSig
    );
    contestForUser(
      _attester,
      _requester,
      _reward,
      _requestNonce,
      _requesterSig
    );
  }

  /**
   * @notice Private function for attester to reject an attestation and receive payment 
   *  without associating the negative attestation with the subject's bloomId
   * @param _attester user completing the attestation
   * @param _requester user requesting this attestation be completed and paying for it in BLT
   * @param _reward payment to attester from requester in BLT wei
   * @param _requestNonce Nonce in sig signed by requester so it can't be replayed
   * @param _requesterSig signature authorizing payment from requester to attester
   */
  function contestForUser(
    address _attester,
    address _requester,
    uint256 _reward,
    bytes32 _requestNonce,
    bytes _requesterSig
    ) private {

    if (_reward > 0) {
      tokenEscrowMarketplace.requestTokenPayment(_requester, _attester, _reward, _requestNonce, _requesterSig);
    }
    emit AttestationRejected(_attester, _requester);
  }

  /**
   * @notice Verify subject signature is valid 
   * @param _subject user this attestation is about
   * @param _dataHash hash of data being attested and nonce
   * param _requestNonce Nonce in sig signed by subject so it can't be replayed
   * @param _subjectSig Signed authorization from subject with attestation agreement
   */
  function validateSubjectSig(
    address _subject,
    bytes32 _dataHash,
    bytes32 _requestNonce,
    bytes _subjectSig
  ) private {
    bytes32 _signatureDigest = generateRequestAttestationSchemaHash(_dataHash, _requestNonce);
    require(_subject == recoverSigner(_signatureDigest, _subjectSig));
    burnSignatureDigest(_signatureDigest, _subject);
  }

  /**
   * @notice Verify attester delegation signature is valid 
   * @param _subject user this attestation is about
   * @param _attester user completing the attestation
   * @param _requester user requesting this attestation be completed and paying for it in BLT
   * @param _reward payment to attester from requester in BLT wei
   * @param _dataHash hash of data being attested and nonce
   * @param _requestNonce nonce in sig signed by subject so it can't be replayed
   * @param _delegationSig signature authorizing attestation on behalf of attester
   */
  function validateAttestForSig(
    address _subject,
    address _attester,
    address _requester,
    uint256 _reward,
    bytes32 _dataHash,
    bytes32 _requestNonce,
    bytes _delegationSig
  ) private {
    bytes32 _delegationDigest = generateAttestForDelegationSchemaHash(_subject, _requester, _reward, _dataHash, _requestNonce);
    require(_attester == recoverSigner(_delegationDigest, _delegationSig), 'Invalid AttestFor Signature');
    burnSignatureDigest(_delegationDigest, _attester);
  }

  /**
   * @notice Verify attester delegation signature is valid 
   * @param _attester user completing the attestation
   * @param _requester user requesting this attestation be completed and paying for it in BLT
   * @param _reward payment to attester from requester in BLT wei
   * @param _requestNonce nonce referenced in TokenEscrowMarketplace so payment sig can't be replayed
   * @param _delegationSig signature authorizing attestation on behalf of attester
   */
  function validateContestForSig(
    address _attester,
    address _requester,
    uint256 _reward,
    bytes32 _requestNonce,
    bytes _delegationSig
  ) private {
    bytes32 _delegationDigest = generateContestForDelegationSchemaHash(_requester, _reward, _requestNonce);
    require(_attester == recoverSigner(_delegationDigest, _delegationSig), 'Invalid ContestFor Signature');
    burnSignatureDigest(_delegationDigest, _attester);
  }

  /**
   * @notice Submit attestation completed prior to deployment of this contract
   * @dev Gives initializer privileges to write attestations during the initialization period without signatures
   * @param _requester user requesting this attestation be completed 
   * @param _attester user completing the attestation
   * @param _subject user this attestation is about
   * @param _dataHash hash of data being attested
   */
  function migrateAttestation(
    address _requester,
    address _attester,
    address _subject,
    bytes32 _dataHash
  ) public onlyDuringInitialization {
    emit TraitAttested(
      _subject,
      _attester,
      _requester,
      _dataHash
    );
  }

  /**
   * @notice Revoke an attestation
   * @dev Link is included in dataHash and cannot be directly connected to a BloomID
   * @param _link bytes string embedded in dataHash to link revocation
   */
  function revokeAttestation(
    bytes32 _link
    ) external {
      revokeAttestationForUser(_link, msg.sender);
  }

  /**
   * @notice Revoke an attestation
   * @dev Link is included in dataHash and cannot be directly connected to a BloomID
   * @param _link bytes string embedded in dataHash to link revocation
   */
  function revokeAttestationFor(
    address _sender,
    bytes32 _link,
    bytes32 _nonce,
    bytes _delegationSig
    ) external {
      validateRevokeForSig(_sender, _link, _nonce, _delegationSig);
      revokeAttestationForUser(_link, _sender);
  }

  /**
   * @notice Verify revocation signature is valid 
   * @param _link bytes string embedded in dataHash to link revocation
   * @param _sender user revoking attestation
   * @param _delegationSig signature authorizing revocation on behalf of revoker
   */
  function validateRevokeForSig(
    address _sender,
    bytes32 _link,
    bytes32 _nonce,
    bytes _delegationSig
  ) private {
    bytes32 _delegationDigest = generateRevokeAttestationForDelegationSchemaHash(_link, _nonce);
    require(_sender == recoverSigner(_delegationDigest, _delegationSig), 'Invalid RevokeFor Signature');
    burnSignatureDigest(_delegationDigest, _sender);
  }

  /**
   * @notice Revoke an attestation
   * @dev Link is included in dataHash and cannot be directly connected to a BloomID
   * @param _link bytes string embedded in dataHash to link revocation
   * @param _sender address identify revoker
   */
  function revokeAttestationForUser(
    bytes32 _link,
    address _sender
    ) private {
      emit AttestationRevoked(_link, _sender);
  }

    /**
   * @notice Set the implementation of the TokenEscrowMarketplace contract by setting a new address
   * @dev Restricted to initializer
   * @param _newTokenEscrowMarketplace Address of new SigningLogic implementation
   */
  function setTokenEscrowMarketplace(TokenEscrowMarketplace _newTokenEscrowMarketplace) external onlyDuringInitialization {
    address oldTokenEscrowMarketplace = tokenEscrowMarketplace;
    tokenEscrowMarketplace = _newTokenEscrowMarketplace;
    emit TokenEscrowMarketplaceChanged(oldTokenEscrowMarketplace, tokenEscrowMarketplace);
  }

}

Contract Security Audit

Contract ABI

[{"constant":false,"inputs":[{"name":"_attester","type":"address"},{"name":"_requester","type":"address"},{"name":"_reward","type":"uint256"},{"name":"_requestNonce","type":"bytes32"},{"name":"_requesterSig","type":"bytes"},{"name":"_delegationSig","type":"bytes"}],"name":"contestFor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initializing","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_subject","type":"address"},{"name":"_requester","type":"address"},{"name":"_reward","type":"uint256"},{"name":"_requesterSig","type":"bytes"},{"name":"_dataHash","type":"bytes32"},{"name":"_requestNonce","type":"bytes32"},{"name":"_subjectSig","type":"bytes"}],"name":"attest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newTokenEscrowMarketplace","type":"address"}],"name":"setTokenEscrowMarketplace","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_requester","type":"address"},{"name":"_reward","type":"uint256"},{"name":"_requestNonce","type":"bytes32"},{"name":"_requesterSig","type":"bytes"}],"name":"contest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_link","type":"bytes32"}],"name":"revokeAttestation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tokenEscrowMarketplace","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_requester","type":"address"},{"name":"_attester","type":"address"},{"name":"_subject","type":"address"},{"name":"_dataHash","type":"bytes32"}],"name":"migrateAttestation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initializer","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_subject","type":"address"},{"name":"_attester","type":"address"},{"name":"_requester","type":"address"},{"name":"_reward","type":"uint256"},{"name":"_requesterSig","type":"bytes"},{"name":"_dataHash","type":"bytes32"},{"name":"_requestNonce","type":"bytes32"},{"name":"_subjectSig","type":"bytes"},{"name":"_delegationSig","type":"bytes"}],"name":"attestFor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"endInitialization","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_sender","type":"address"},{"name":"_link","type":"bytes32"},{"name":"_nonce","type":"bytes32"},{"name":"_delegationSig","type":"bytes"}],"name":"revokeAttestationFor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"usedSignatures","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_initializer","type":"address"},{"name":"_tokenEscrowMarketplace","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"subject","type":"address"},{"indexed":false,"name":"attester","type":"address"},{"indexed":false,"name":"requester","type":"address"},{"indexed":false,"name":"dataHash","type":"bytes32"}],"name":"TraitAttested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"attester","type":"address"},{"indexed":true,"name":"requester","type":"address"}],"name":"AttestationRejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"link","type":"bytes32"},{"indexed":false,"name":"attester","type":"address"}],"name":"AttestationRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"oldTokenEscrowMarketplace","type":"address"},{"indexed":false,"name":"newTokenEscrowMarketplace","type":"address"}],"name":"TokenEscrowMarketplaceChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"InitializationEnded","type":"event"}]

60806040523480156200001157600080fd5b50604051604080620028d283398101806040528101908080519060200190929190805190602001909291905050506040805190810160405280601781526020017f426c6f6f6d204174746573746174696f6e204c6f6769630000000000000000008152506040805190810160405280600181526020017f3200000000000000000000000000000000000000000000000000000000000000815250600184806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600060146101000a81548160ff021916908315150217905550506200015b6080604051908101604052808581526020018481526020018381526020013073ffffffffffffffffffffffffffffffffffffffff16815250620001b1640100000000026401000000009004565b6002816000191690555050505080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050620003fb565b600060405180807f454950373132446f6d61696e28737472696e67206e616d652c737472696e672081526020017f76657273696f6e2c75696e7432353620636861696e49642c616464726573732081526020017f766572696679696e67436f6e74726163742900000000000000000000000000008152506052019050604051809103902082600001516040518082805190602001908083835b6020831015156200027157805182526020820191506020810190506020830392506200024a565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902083602001516040518082805190602001908083835b602083101515620002da5780518252602082019150602081019050602083039250620002b3565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902084604001518560600151604051602001808660001916600019168152602001856000191660001916815260200184600019166000191681526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001955050505050506040516020818303038152906040526040518082805190602001908083835b602083101515620003c75780518252602082019150602081019050602083039250620003a0565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209050919050565b6124c7806200040b6000396000f3006080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630ca7a56a146100ca5780632599f159146101755780632a5502ad146101a45780633c7367781461025d5780634ae122bb146102a05780634d5e1da6146103135780634e46f6e3146103445780639a43a3141461039b5780639ce110d71461042c5780639f74474514610483578063b397657d14610574578063d0bad1d61461058b578063f978fd6114610602575b600080fd5b3480156100d657600080fd5b50610173600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803560001916906020019092919080359060200190820180359060200191909192939192939080359060200190820180359060200191909192939192939050505061064b565b005b34801561018157600080fd5b5061018a6106d3565b604051808215151515815260200191505060405180910390f35b3480156101b057600080fd5b5061025b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001919091929391929390803560001916906020019092919080356000191690602001909291908035906020019082018035906020019190919293919293905050506106e6565b005b34801561026957600080fd5b5061029e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610765565b005b3480156102ac57600080fd5b50610311600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035600019169060200190929190803590602001908201803590602001919091929391929390505050610a1e565b005b34801561031f57600080fd5b506103426004803603810190808035600019169060200190929190505050610a64565b005b34801561035057600080fd5b50610359610a71565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156103a757600080fd5b5061042a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035600019169060200190929190505050610a97565b005b34801561043857600080fd5b50610441610d0c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561048f57600080fd5b50610572600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190820180359060200191909192939192939080356000191690602001909291908035600019169060200190929190803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390505050610d31565b005b34801561058057600080fd5b50610589610df4565b005b34801561059757600080fd5b50610600600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080356000191690602001909291908035600019169060200190929190803590602001908201803590602001919091929391929390505050610fd0565b005b34801561060e57600080fd5b50610631600480360381019080803560001916906020019092919050505061101f565b604051808215151515815260200191505060405180910390f35b61068a8888888886868080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505061103f565b6106c98888888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505061110c565b5050505050505050565b600060149054906101000a900460ff1681565b61075a89338a8a8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050898989898080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611305565b505050505050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610851576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420627920696e6981526020017f7469616c697a657200000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600060149054906101000a900460ff1615156108fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f8152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420647572696e6781526020017f20696e697469616c697a6174696f6e000000000000000000000000000000000081525060400191505060405180910390fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fff80ee77c85d9a66d44e11d38886b3f07748e818eaeb0660b75706962d0f56d581600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15050565b610a5d3386868686868080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505061110c565b5050505050565b610a6e813361158e565b50565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610b81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420627920696e6981526020017f7469616c697a657200000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600060149054906101000a900460ff161515610c2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f8152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420647572696e6781526020017f20696e697469616c697a6174696f6e000000000000000000000000000000000081525060400191505060405180910390fd5b7f53931139c48182587fa8ce0ac76dd9cd86655899a636bffdce8138a0cdb2c1b582848684604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001826000191660001916815260200194505050505060405180910390a150505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610d728c8c8c8c8a8a88888080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611605565b610de68c8c8c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050508b8b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611305565b505050505050505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ede576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420627920696e6981526020017f7469616c697a657200000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600060149054906101000a900460ff161515610f88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f8152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420647572696e6781526020017f20696e697469616c697a6174696f6e000000000000000000000000000000000081525060400191505060405180910390fd5b60008060146101000a81548160ff0219169083151502179055507f0cabb9c05f9eeeadb6765f175642f19876b512ba15100b1391420b714b0c3d0060405160405180910390a1565b61100e85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506116d6565b611018848661158e565b5050505050565b60016020528060005260406000206000915054906101000a900460ff1681565b600061104c8585856117a1565b905061105881836118ad565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415156110fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f496e76616c696420436f6e74657374466f72205369676e61747572650000000081525060200191505060405180910390fd5b6111048187611a13565b505050505050565b60008311156112a457600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635ed5eb5085878686866040518663ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001836000191660001916815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561123b578082015181840152602081019050611220565b50505050905090810190601f1680156112685780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b15801561128b57600080fd5b505af115801561129f573d6000803e3d6000fd5b505050505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f9a53975728a25417448708f6de6b9c942bbe4461c6647852e0b60c91c3c2fad360405160405180910390a35050505050565b61131188848484611bab565b7f53931139c48182587fa8ce0ac76dd9cd86655899a636bffdce8138a0cdb2c1b588888886604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001826000191660001916815260200194505050505060405180910390a1600085111561158457600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635ed5eb5087898886896040518663ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001836000191660001916815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561151b578082015181840152602081019050611500565b50505050905090810190601f1680156115485780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b15801561156b57600080fd5b505af115801561157f573d6000803e3d6000fd5b505050505b5050505050505050565b7f59d1b98a5da8bbc1db92f7d8d2e21c3067da65edbe08f4ae23df11487ee4c8b082826040518083600019166000191681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15050565b60006116148887878787611c0d565b905061162081836118ad565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415156116c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496e76616c696420417474657374466f72205369676e6174757265000000000081525060200191505060405180910390fd5b6116cc8188611a13565b5050505050505050565b60006116e28484611d41565b90506116ee81836118ad565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16141515611790576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496e76616c6964205265766f6b65466f72205369676e6174757265000000000081525060200191505060405180910390fd5b61179a8186611a13565b5050505050565b60006002546117e46060604051908101604052808773ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018560001916815250611e33565b60405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183600019166000191681526020018260001916600019168152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831015156118775780518252602082019150602081019050602083039250611852565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902090509392505050565b600080737a75cb349d9a9d4c2d3eb8a22cb3090222d8557b6319045a2585856040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180836000191660001916815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561194557808201518184015260208101905061192a565b50505050905090810190601f1680156119725780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b15801561199057600080fd5b505af41580156119a4573d6000803e3d6000fd5b505050506040513d60208110156119ba57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515611a0957600080fd5b8091505092915050565b600082826040516020018083600019166000191681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001925050506040516020818303038152906040526040518082805190602001908083835b602083101515611aa65780518252602082019150602081019050602083039250611a81565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905060016000826000191660001916815260200190815260200160002060009054906101000a900460ff16151515611b73576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5369676e6174757265206e6f7420756e6971756500000000000000000000000081525060200191505060405180910390fd5b6001806000836000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550505050565b6000611bb78484611f9f565b9050611bc381836118ad565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16141515611bfc57600080fd5b611c068186611a13565b5050505050565b6000600254611c7660a0604051908101604052808973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff168152602001878152602001866000191681526020018560001916815250612091565b60405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183600019166000191681526020018260001916600019168152602001925050506040516020818303038152906040526040518082805190602001908083835b602083101515611d095780518252602082019150602081019050602083039250611ce4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905095945050505050565b6000600254611d6b604080519081016040528086600019168152602001856000191681525061226f565b60405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183600019166000191681526020018260001916600019168152602001925050506040516020818303038152906040526040518082805190602001908083835b602083101515611dfe5780518252602082019150602081019050602083039250611dd9565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905092915050565b600060405180807f436f6e74657374466f722861646472657373207265717565737465722c75696e81526020017f74323536207265776172642c6279746573333220726571756573744e6f6e636581526020017f2900000000000000000000000000000000000000000000000000000000000000815250604101905060405180910390208260000151836020015184604001516040516020018085600019166000191681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200182600019166000191681526020019450505050506040516020818303038152906040526040518082805190602001908083835b602083101515611f6b5780518252602082019150602081019050602083039250611f46565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209050919050565b6000600254611fc96040805190810160405280866000191681526020018560001916815250612385565b60405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183600019166000191681526020018260001916600019168152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310151561205c5780518252602082019150602081019050602083039250612037565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905092915050565b600060405180807f417474657374466f722861646472657373207375626a6563742c61646472657381526020017f73207265717565737465722c75696e74323536207265776172642c627974657381526020017f33322064617461486173682c6279746573333220726571756573744e6f6e636581526020017f290000000000000000000000000000000000000000000000000000000000000081525060610190506040518091039020826000015183602001518460400151856060015186608001516040516020018087600019166000191681526020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018360001916600019168152602001826000191660001916815260200196505050505050506040516020818303038152906040526040518082805190602001908083835b60208310151561223b5780518252602082019150602081019050602083039250612216565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209050919050565b600060405180807f5265766f6b654174746573746174696f6e466f722862797465733332206c696e81526020017f6b2c62797465733332206e6f6e6365290000000000000000000000000000000081525060300190506040518091039020826000015183602001516040516020018084600019166000191681526020018360001916600019168152602001826000191660001916815260200193505050506040516020818303038152906040526040518082805190602001908083835b602083101515612351578051825260208201915060208101905060208303925061232c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209050919050565b600060405180807f4174746573746174696f6e52657175657374286279746573333220646174614881526020017f6173682c62797465733332206e6f6e636529000000000000000000000000000081525060320190506040518091039020826000015183602001516040516020018084600019166000191681526020018360001916600019168152602001826000191660001916815260200193505050506040516020818303038152906040526040518082805190602001908083835b6020831015156124675780518252602082019150602081019050602083039250612442565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902090509190505600a165627a7a72305820bff582e58c664569a718e5ba7037128a0b9eb86816de1b987f598c644b6553fc002900000000000000000000000028c7ba752fd214a54ea25f075ab459ab17bd5fd20000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106100c5576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630ca7a56a146100ca5780632599f159146101755780632a5502ad146101a45780633c7367781461025d5780634ae122bb146102a05780634d5e1da6146103135780634e46f6e3146103445780639a43a3141461039b5780639ce110d71461042c5780639f74474514610483578063b397657d14610574578063d0bad1d61461058b578063f978fd6114610602575b600080fd5b3480156100d657600080fd5b50610173600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803560001916906020019092919080359060200190820180359060200191909192939192939080359060200190820180359060200191909192939192939050505061064b565b005b34801561018157600080fd5b5061018a6106d3565b604051808215151515815260200191505060405180910390f35b3480156101b057600080fd5b5061025b600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001908201803590602001919091929391929390803560001916906020019092919080356000191690602001909291908035906020019082018035906020019190919293919293905050506106e6565b005b34801561026957600080fd5b5061029e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610765565b005b3480156102ac57600080fd5b50610311600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035600019169060200190929190803590602001908201803590602001919091929391929390505050610a1e565b005b34801561031f57600080fd5b506103426004803603810190808035600019169060200190929190505050610a64565b005b34801561035057600080fd5b50610359610a71565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156103a757600080fd5b5061042a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035600019169060200190929190505050610a97565b005b34801561043857600080fd5b50610441610d0c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561048f57600080fd5b50610572600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190820180359060200191909192939192939080356000191690602001909291908035600019169060200190929190803590602001908201803590602001919091929391929390803590602001908201803590602001919091929391929390505050610d31565b005b34801561058057600080fd5b50610589610df4565b005b34801561059757600080fd5b50610600600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080356000191690602001909291908035600019169060200190929190803590602001908201803590602001919091929391929390505050610fd0565b005b34801561060e57600080fd5b50610631600480360381019080803560001916906020019092919050505061101f565b604051808215151515815260200191505060405180910390f35b61068a8888888886868080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505061103f565b6106c98888888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505061110c565b5050505050505050565b600060149054906101000a900460ff1681565b61075a89338a8a8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050898989898080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611305565b505050505050505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610851576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420627920696e6981526020017f7469616c697a657200000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600060149054906101000a900460ff1615156108fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f8152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420647572696e6781526020017f20696e697469616c697a6174696f6e000000000000000000000000000000000081525060400191505060405180910390fd5b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fff80ee77c85d9a66d44e11d38886b3f07748e818eaeb0660b75706962d0f56d581600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15050565b610a5d3386868686868080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505061110c565b5050505050565b610a6e813361158e565b50565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610b81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420627920696e6981526020017f7469616c697a657200000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600060149054906101000a900460ff161515610c2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f8152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420647572696e6781526020017f20696e697469616c697a6174696f6e000000000000000000000000000000000081525060400191505060405180910390fd5b7f53931139c48182587fa8ce0ac76dd9cd86655899a636bffdce8138a0cdb2c1b582848684604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001826000191660001916815260200194505050505060405180910390a150505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610d728c8c8c8c8a8a88888080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611605565b610de68c8c8c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050508b8b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611305565b505050505050505050505050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610ede576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420627920696e6981526020017f7469616c697a657200000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600060149054906101000a900460ff161515610f88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f8152602001807f4d6574686f642063616e206f6e6c792062652063616c6c656420647572696e6781526020017f20696e697469616c697a6174696f6e000000000000000000000000000000000081525060400191505060405180910390fd5b60008060146101000a81548160ff0219169083151502179055507f0cabb9c05f9eeeadb6765f175642f19876b512ba15100b1391420b714b0c3d0060405160405180910390a1565b61100e85858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050506116d6565b611018848661158e565b5050505050565b60016020528060005260406000206000915054906101000a900460ff1681565b600061104c8585856117a1565b905061105881836118ad565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415156110fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f496e76616c696420436f6e74657374466f72205369676e61747572650000000081525060200191505060405180910390fd5b6111048187611a13565b505050505050565b60008311156112a457600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635ed5eb5085878686866040518663ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001836000191660001916815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561123b578082015181840152602081019050611220565b50505050905090810190601f1680156112685780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b15801561128b57600080fd5b505af115801561129f573d6000803e3d6000fd5b505050505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f9a53975728a25417448708f6de6b9c942bbe4461c6647852e0b60c91c3c2fad360405160405180910390a35050505050565b61131188848484611bab565b7f53931139c48182587fa8ce0ac76dd9cd86655899a636bffdce8138a0cdb2c1b588888886604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001826000191660001916815260200194505050505060405180910390a1600085111561158457600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635ed5eb5087898886896040518663ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001836000191660001916815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561151b578082015181840152602081019050611500565b50505050905090810190601f1680156115485780820380516001836020036101000a031916815260200191505b509650505050505050600060405180830381600087803b15801561156b57600080fd5b505af115801561157f573d6000803e3d6000fd5b505050505b5050505050505050565b7f59d1b98a5da8bbc1db92f7d8d2e21c3067da65edbe08f4ae23df11487ee4c8b082826040518083600019166000191681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15050565b60006116148887878787611c0d565b905061162081836118ad565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415156116c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496e76616c696420417474657374466f72205369676e6174757265000000000081525060200191505060405180910390fd5b6116cc8188611a13565b5050505050505050565b60006116e28484611d41565b90506116ee81836118ad565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16141515611790576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f496e76616c6964205265766f6b65466f72205369676e6174757265000000000081525060200191505060405180910390fd5b61179a8186611a13565b5050505050565b60006002546117e46060604051908101604052808773ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018560001916815250611e33565b60405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183600019166000191681526020018260001916600019168152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831015156118775780518252602082019150602081019050602083039250611852565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902090509392505050565b600080737a75cb349d9a9d4c2d3eb8a22cb3090222d8557b6319045a2585856040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180836000191660001916815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561194557808201518184015260208101905061192a565b50505050905090810190601f1680156119725780820380516001836020036101000a031916815260200191505b50935050505060206040518083038186803b15801561199057600080fd5b505af41580156119a4573d6000803e3d6000fd5b505050506040513d60208110156119ba57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515611a0957600080fd5b8091505092915050565b600082826040516020018083600019166000191681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001925050506040516020818303038152906040526040518082805190602001908083835b602083101515611aa65780518252602082019150602081019050602083039250611a81565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905060016000826000191660001916815260200190815260200160002060009054906101000a900460ff16151515611b73576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5369676e6174757265206e6f7420756e6971756500000000000000000000000081525060200191505060405180910390fd5b6001806000836000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550505050565b6000611bb78484611f9f565b9050611bc381836118ad565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16141515611bfc57600080fd5b611c068186611a13565b5050505050565b6000600254611c7660a0604051908101604052808973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff168152602001878152602001866000191681526020018560001916815250612091565b60405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183600019166000191681526020018260001916600019168152602001925050506040516020818303038152906040526040518082805190602001908083835b602083101515611d095780518252602082019150602081019050602083039250611ce4565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905095945050505050565b6000600254611d6b604080519081016040528086600019168152602001856000191681525061226f565b60405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183600019166000191681526020018260001916600019168152602001925050506040516020818303038152906040526040518082805190602001908083835b602083101515611dfe5780518252602082019150602081019050602083039250611dd9565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905092915050565b600060405180807f436f6e74657374466f722861646472657373207265717565737465722c75696e81526020017f74323536207265776172642c6279746573333220726571756573744e6f6e636581526020017f2900000000000000000000000000000000000000000000000000000000000000815250604101905060405180910390208260000151836020015184604001516040516020018085600019166000191681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200182600019166000191681526020019450505050506040516020818303038152906040526040518082805190602001908083835b602083101515611f6b5780518252602082019150602081019050602083039250611f46565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209050919050565b6000600254611fc96040805190810160405280866000191681526020018560001916815250612385565b60405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183600019166000191681526020018260001916600019168152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310151561205c5780518252602082019150602081019050602083039250612037565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905092915050565b600060405180807f417474657374466f722861646472657373207375626a6563742c61646472657381526020017f73207265717565737465722c75696e74323536207265776172642c627974657381526020017f33322064617461486173682c6279746573333220726571756573744e6f6e636581526020017f290000000000000000000000000000000000000000000000000000000000000081525060610190506040518091039020826000015183602001518460400151856060015186608001516040516020018087600019166000191681526020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018360001916600019168152602001826000191660001916815260200196505050505050506040516020818303038152906040526040518082805190602001908083835b60208310151561223b5780518252602082019150602081019050602083039250612216565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209050919050565b600060405180807f5265766f6b654174746573746174696f6e466f722862797465733332206c696e81526020017f6b2c62797465733332206e6f6e6365290000000000000000000000000000000081525060300190506040518091039020826000015183602001516040516020018084600019166000191681526020018360001916600019168152602001826000191660001916815260200193505050506040516020818303038152906040526040518082805190602001908083835b602083101515612351578051825260208201915060208101905060208303925061232c565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209050919050565b600060405180807f4174746573746174696f6e52657175657374286279746573333220646174614881526020017f6173682c62797465733332206e6f6e636529000000000000000000000000000081525060320190506040518091039020826000015183602001516040516020018084600019166000191681526020018360001916600019168152602001826000191660001916815260200193505050506040516020818303038152906040526040518082805190602001908083835b6020831015156124675780518252602082019150602081019050602083039250612442565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902090509190505600a165627a7a72305820bff582e58c664569a718e5ba7037128a0b9eb86816de1b987f598c644b6553fc0029

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

00000000000000000000000028c7ba752fd214a54ea25f075ab459ab17bd5fd20000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _initializer (address): 0x28C7ba752fD214A54ea25f075ab459Ab17bd5fD2
Arg [1] : _tokenEscrowMarketplace (address): 0x0000000000000000000000000000000000000000

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000028c7ba752fd214a54ea25f075ab459ab17bd5fd2
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000


Libraries Used


Swarm Source

bzzr://bff582e58c664569a718e5ba7037128a0b9eb86816de1b987f598c644b6553fc

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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