ETH Price: $3,416.52 (-6.80%)

Contract

0xd546551924a883B604d4127b0Af309C95Ba9BA6d
 
Transaction Hash
Method
Block
From
To
Withdraw Token64602482018-10-05 21:37:312267 days ago1538775451IN
0xd5465519...95Ba9BA6d
0 ETH0.000368467
Withdraw64601962018-10-05 21:23:422267 days ago1538774622IN
0xd5465519...95Ba9BA6d
0 ETH0.000194847
Withdraw Token64601912018-10-05 21:22:142267 days ago1538774534IN
0xd5465519...95Ba9BA6d
0 ETH0.000368467
Withdraw56359882018-05-18 17:20:202407 days ago1526664020IN
0xd5465519...95Ba9BA6d
0 ETH0.0006843316
Withdraw Token56359772018-05-18 17:16:442407 days ago1526663804IN
0xd5465519...95Ba9BA6d
0 ETH0.0006149916
Withdraw Token56359752018-05-18 17:16:332407 days ago1526663793IN
0xd5465519...95Ba9BA6d
0 ETH0.0006032316
Withdraw Token56359732018-05-18 17:15:372407 days ago1526663737IN
0xd5465519...95Ba9BA6d
0 ETH0.0010998216
Withdraw Token56359582018-05-18 17:12:072407 days ago1526663527IN
0xd5465519...95Ba9BA6d
0 ETH0.0011022716
Withdraw Token56359542018-05-18 17:11:022407 days ago1526663462IN
0xd5465519...95Ba9BA6d
0 ETH0.0008226112
Withdraw Token52195532018-03-08 16:47:112478 days ago1520527631IN
0xd5465519...95Ba9BA6d
0 ETH0.00021894
Withdraw52193482018-03-08 15:59:312478 days ago1520524771IN
0xd5465519...95Ba9BA6d
0 ETH0.000171344
Withdraw Token52193482018-03-08 15:59:312478 days ago1520524771IN
0xd5465519...95Ba9BA6d
0 ETH0.00021894
Withdraw Token52148332018-03-07 21:37:252479 days ago1520458645IN
0xd5465519...95Ba9BA6d
0 ETH0.000114174
Withdraw Token52148332018-03-07 21:37:252479 days ago1520458645IN
0xd5465519...95Ba9BA6d
0 ETH0.00015384
Withdraw Token52148312018-03-07 21:37:132479 days ago1520458633IN
0xd5465519...95Ba9BA6d
0 ETH0.00021894
Withdraw Token52147842018-03-07 21:27:512479 days ago1520458071IN
0xd5465519...95Ba9BA6d
0 ETH0.000275314
Withdraw Token52147782018-03-07 21:25:322479 days ago1520457932IN
0xd5465519...95Ba9BA6d
0 ETH0.00027894
Withdraw Token52147772018-03-07 21:25:192479 days ago1520457919IN
0xd5465519...95Ba9BA6d
0 ETH0.000228094
Withdraw52147722018-03-07 21:23:272479 days ago1520457807IN
0xd5465519...95Ba9BA6d
0 ETH0.000171344
Lock Contract52088892018-03-06 21:27:072480 days ago1520371627IN
0xd5465519...95Ba9BA6d
0 ETH0.000263976
Cancel Order52080722018-03-06 18:05:202480 days ago1520359520IN
0xd5465519...95Ba9BA6d
0 ETH0.000213294
Cancel Order52080722018-03-06 18:05:202480 days ago1520359520IN
0xd5465519...95Ba9BA6d
0 ETH0.000213294
Cancel Order52080722018-03-06 18:05:202480 days ago1520359520IN
0xd5465519...95Ba9BA6d
0 ETH0.000213294
Cancel Order52080722018-03-06 18:05:202480 days ago1520359520IN
0xd5465519...95Ba9BA6d
0 ETH0.000213294
Cancel Order52080692018-03-06 18:04:482480 days ago1520359488IN
0xd5465519...95Ba9BA6d
0 ETH0.000213044
View all transactions

Latest 16 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
64601962018-10-05 21:23:422267 days ago1538774622
0xd5465519...95Ba9BA6d
0.00635281 ETH
56359882018-05-18 17:20:202407 days ago1526664020
0xd5465519...95Ba9BA6d
1.338 ETH
52193482018-03-08 15:59:312478 days ago1520524771
0xd5465519...95Ba9BA6d
17.573 ETH
52147722018-03-07 21:23:272479 days ago1520457807
0xd5465519...95Ba9BA6d
0.14952127 ETH
52043822018-03-06 3:05:022481 days ago1520305502
0xd5465519...95Ba9BA6d
0.1 ETH
52015582018-03-05 15:39:492481 days ago1520264389
0xd5465519...95Ba9BA6d
0.89982 ETH
52015582018-03-05 15:39:492481 days ago1520264389
0xd5465519...95Ba9BA6d
1.42982233 ETH
52015512018-03-05 15:37:072481 days ago1520264227
0xd5465519...95Ba9BA6d
24.3298525 ETH
52014952018-03-05 15:26:132481 days ago1520263573
0xd5465519...95Ba9BA6d
33.9527514 ETH
51930532018-03-04 4:55:222482 days ago1520139322
0xd5465519...95Ba9BA6d
1.41506969 ETH
51928522018-03-04 4:06:492482 days ago1520136409
0xd5465519...95Ba9BA6d
2.492619 ETH
51927782018-03-04 3:49:172483 days ago1520135357
0xd5465519...95Ba9BA6d
0.57 ETH
51878432018-03-03 7:52:512483 days ago1520063571
0xd5465519...95Ba9BA6d
5.771 ETH
51851352018-03-02 20:58:432484 days ago1520024323
0xd5465519...95Ba9BA6d
0.175 ETH
51833772018-03-02 13:49:142484 days ago1519998554
0xd5465519...95Ba9BA6d
0.01 ETH
51400462018-02-23 4:36:132491 days ago1519360573
0xd5465519...95Ba9BA6d
0.004 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
UberDelta

Compiler Version
v0.4.20+commit.3155dd80

Optimization Enabled:
Yes with 999 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2018-03-05
*/

pragma solidity ^0.4.19;

// 
// UberDelta Exchange Contract - v1.0.0
// 
//  www.uberdelta.com
//

contract Token {
  function balanceOf(address _owner) public view returns (uint256 balance);
  function transfer(address _to, uint256 _value) public returns (bool success);
  function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
  function approve(address _spender, uint256 _value) public returns (bool success);
}

contract SafeMath {
  function safeMul(uint256 a, uint256 b) internal pure returns (uint256 c) {
    if (a == 0) {
      return 0;
    }
    c = a * b;
    require(c / a == b);
    return c;
  }
  
  function safeDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
    require(b > 0); //gentler than an assert.
    c = a / b;
    return c;
  }


  function safeSub(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b <= a);
    return a - b;
  }


  function safeAdd(uint256 a, uint256 b) internal pure returns (uint256 c) {
    c = a + b;
    require(c >= a);
    return c;
  }
}

contract OwnerManager {

  address public owner;
  address public newOwner;
  address public manager;

  event OwnershipTransferProposed(address indexed _from, address indexed _to);
  event OwnershipTransferConfirmed(address indexed _from, address indexed _to);
  event NewManager(address indexed _newManager);


  modifier onlyOwner {
    assert(msg.sender == owner);
    _;
  }
  
  modifier onlyManager {
    assert(msg.sender == manager);
    _;
  }


  function OwnerManager() public{
    owner = msg.sender;
    manager = msg.sender;
  }


  function transferOwnership(address _newOwner) onlyOwner external{
    require(_newOwner != owner);
    
    OwnershipTransferProposed(owner, _newOwner);
    
    newOwner = _newOwner;
  }


  function confirmOwnership() external {
    assert(msg.sender == newOwner);
    
    OwnershipTransferConfirmed(owner, newOwner);
    
    owner = newOwner;
  }


  function newManager(address _newManager) onlyOwner external{
    require(_newManager != address(0x0));
    
    NewManager(_newManager);
    
    manager = _newManager;
  }

}


contract Helper is OwnerManager {

  mapping (address => bool) public isHelper;

  modifier onlyHelper {
    assert(isHelper[msg.sender] == true);
    _;
  }

  event ChangeHelper(
    address indexed helper,
    bool status
  );

  function Helper() public{
    isHelper[msg.sender] = true;
  }

  function changeHelper(address _helper, bool _status) external onlyManager {
	  ChangeHelper(_helper, _status);
    isHelper[_helper] = _status;
  }

}


contract Compliance {
  function canDeposit(address _user) public view returns (bool isAllowed);
  function canTrade(address _token, address _user) public view returns (bool isAllowed);
  function validateTrade(
    address _token,
    address _getUser,
    address _giveUser
  )
    public
    view
    returns (bool isAllowed)
  ;
}

contract OptionRegistry {
  function registerOptionPair(
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires
  )
  public
  returns(bool)
  ;
  
  function isOptionPairRegistered(
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires
  )
  public
  view
  returns(bool)  
  ;
  
}

contract EOS {
    function register(string key) public;
}

contract UberDelta is SafeMath, OwnerManager, Helper {

  // The account that will receive fees
  address public feeAccount;
  
  // The account that will receive lost ERC20 tokens
  address public sweepAccount;
  
  // The address of the compliance engine
  address public complianceAddress;
  
  // The address of the options registry
  address public optionsRegistryAddress;
  
  // The address of the next exchange contract
  address public newExchange;

  // Turn off deposits and trades, allow upgrade and withdraw
  bool public contractLocked;
  
  bytes32 signedTradeHash = keccak256(
    "address contractAddress",
    "address takerTokenAddress",
    "uint256 takerTokenAmount",
    "address makerTokenAddress",
    "uint256 makerTokenAmount",
    "uint256 tradeExpires",
    "uint256 salt",
    "address maker",
    "address restrictedTo"
  );
  
  bytes32 signedWithdrawHash = keccak256(
    "address contractAddress",
    "uint256 amount",
    "uint256 fee",
    "uint256 withdrawExpires",
    "uint256 salt",
    "address maker",
    "address restrictedTo"
  );


  // Balance per token, for each user.
  mapping (address => mapping (address => uint256)) public balances;
  
  // global token balance tracking (to detect lost tokens)
  mapping (address => uint256) public globalBalance;
  
  // List of orders created by calling the exchange contract directly.
  mapping (bytes32 => bool) public orders;
  
  // Lists the amount of each order that has been filled or cancelled.
  mapping (bytes32 => uint256) public orderFills;
  
  // Tokens that need to be checked through the compliance engine.
  mapping (address => bool) public restrictedTokens;

  // Mapping of fees by user class (default class == 0x0)
  mapping (uint256 => uint256) public feeByClass;
  
  // Mapping of users to user classes.
  mapping (address => uint256) public userClass; 
  
  
  /*******************************************
  / Exchange Regular Events
  /******************************************/
  
  // Note: Order creation is usually off-chain
  event Order(
    bytes32 indexed tradePair,
    address indexed maker,
    address[4] addressData,
    uint256[4] numberData
  );
  
  event Cancel(
    bytes32 indexed tradePair,
    address indexed maker,
    address[4] addressData,
    uint256[4] numberData,
    uint256 status
  );
  
   event FailedTrade( 
    bytes32 indexed tradePair,
    address indexed taker,
    bytes32 hash,
    uint256 failReason
  ); 
  
  event Trade( 
    bytes32 indexed tradePair,
    address indexed maker,
    address indexed taker,
    address makerToken,
    address takerToken,
    address restrictedTo,
    uint256[4] numberData,
    uint256 tradeAmount,
    bool fillOrKill
  );
  
  event Deposit(
    address indexed token,
    address indexed toUser,
    address indexed sender,
    uint256 amount
  );
  
  event Withdraw(
    address indexed token,
    address indexed toUser,
    uint256 amount
  );

  event InternalTransfer(
    address indexed token,
    address indexed toUser,
    address indexed sender,
    uint256 amount
  );

  event TokenSweep(
    address indexed token,
    address indexed sweeper,
    uint256 amount,
    uint256 balance
  );
  
  event RestrictToken(
    address indexed token,
    bool status
  );
  
  event NewExchange(
    address newExchange
  );
  
  event ChangeFeeAccount(
    address feeAccount
  );
  
  event ChangeSweepAccount(
    address sweepAccount
  );
  
  event ChangeClassFee(
    uint256 indexed class,
    uint256 fee
  );
  
  event ChangeUserClass(
    address indexed user,
    uint256 class
  );
  
  event LockContract(
    bool status
  );
  
  event UpdateComplianceAddress(
    address newComplianceAddress
  );
  
  event UpdateOptionsRegistryAddress(
    address newOptionsRegistryAddress
  );
  
  event Upgrade(
    address indexed user,
    address indexed token,
    address newExchange,
    uint256 amount
  );
  
  event RemoteWithdraw(
    address indexed maker,
    address indexed sender,
    uint256 withdrawAmount,
    uint256 feeAmount,
    uint256 withdrawExpires,
    uint256 salt,
    address restrictedTo
  );
  
  event CancelRemoteWithdraw(
    address indexed maker,
    uint256 withdrawAmount,
    uint256 feeAmount,
    uint256 withdrawExpires,
    uint256 salt,
    address restrictedTo,
    uint256 status
  );

  //Constructor Function, set initial values.
  function UberDelta() public {
    feeAccount = owner;
    sweepAccount = owner;
    feeByClass[0x0] = 3000000000000000;
    contractLocked = false;
    complianceAddress = this;
    optionsRegistryAddress = this;
  }


  // Prevent raw sends of Eth.
  function() public {
    revert();
  }
  
  
  
  /*******************************************
  / Contract Control Functions
  /******************************************/
  function changeNewExchange(address _newExchange) external onlyOwner {
    //since _newExchange being zero turns off the upgrade function, lets
    //allow this to be reset to 0x0.
    
    newExchange = _newExchange;
    
    NewExchange(_newExchange);
  }


  function changeFeeAccount(address _feeAccount) external onlyManager {
    require(_feeAccount != address(0x0));
    
    feeAccount = _feeAccount;
    
    ChangeFeeAccount(_feeAccount);
  }

  function changeSweepAccount(address _sweepAccount) external onlyManager {
    require(_sweepAccount != address(0x0));
    
    sweepAccount = _sweepAccount;
    
    ChangeSweepAccount(_sweepAccount);
  }

  function changeClassFee(uint256 _class, uint256 _fee) external onlyManager {
    require(_fee <= 10000000000000000); //Max 1%.

    feeByClass[_class] = _fee;

    ChangeClassFee(_class, _fee);
  }
  
  function changeUserClass(address _user, uint256 _newClass) external onlyHelper {
    userClass[_user] = _newClass;
    
    ChangeUserClass(_user, _newClass);
  }
  
  //Turn off deposits and trades, but still allow withdrawals and upgrades.
  function lockContract(bool _lock) external onlyManager {
    contractLocked = _lock;
    
    LockContract(_lock);
  }
  
  function updateComplianceAddress(address _newComplianceAddress)
    external
    onlyManager
  {
    complianceAddress = _newComplianceAddress;
    
    UpdateComplianceAddress(_newComplianceAddress);
  }

  function updateOptionsRegistryAddress(address _newOptionsRegistryAddress)
    external
    onlyManager
  {
    optionsRegistryAddress = _newOptionsRegistryAddress;
    
    UpdateOptionsRegistryAddress(_newOptionsRegistryAddress);
  }


  // restriction function for tokens that need additional verifications
  function tokenRestriction(address _newToken, bool _status) external onlyHelper {
    restrictedTokens[_newToken] = _status;
    
    RestrictToken(_newToken, _status);
  }

  
  //Turn off deposits and trades, but still allow withdrawals and upgrades.
  modifier notLocked() {
    require(!contractLocked);
    _;
  }
  
  
  /*******************************************************
  / Deposit/Withdrawal/Transfer
  /
  / In all of the following functions, it should be noted
  / that the 0x0 address is used to represent ETH.
  /******************************************************/
  
  // SafeMath sanity checks inputs in deposit(), withdraw(), and token functions.
  
  // Deposit ETH in the contract to trade with
  function deposit() external notLocked payable returns(uint256) {
    require(Compliance(complianceAddress).canDeposit(msg.sender)); 
    // defaults to true until we change compliance code
    
    balances[address(0x0)][msg.sender] = safeAdd(balances[address(0x0)][msg.sender], msg.value);
    globalBalance[address(0x0)] = safeAdd(globalBalance[address(0x0)], msg.value);

    Deposit(0x0, msg.sender, msg.sender, msg.value);
    
    return(msg.value);
  }

  // Withdraw ETH from the contract to your wallet  (internal transaction on etherscan)
  function withdraw(uint256 _amount) external returns(uint256) {
    //require(balances[address(0x0)][msg.sender] >= _amount);
    //handled by safeSub.
    
    balances[address(0x0)][msg.sender] = safeSub(balances[address(0x0)][msg.sender], _amount);
    globalBalance[address(0x0)] = safeSub(globalBalance[address(0x0)], _amount);
 
    //transfer has a built in require
    msg.sender.transfer(_amount);
    
    Withdraw(0x0, msg.sender, _amount);
    
    return(_amount);
  }


  // Deposit ERC20 tokens in the contract to trade with
  // Token(_token).approve(this, _amount) must be called in advance
  // ERC223 tokens must be deposited by a transfer to this contract ( see tokenFallBack(..) )
  function depositToken(address _token, uint256 _amount) external notLocked returns(uint256) {
    require(_token != address(0x0));
    
    require(Compliance(complianceAddress).canDeposit(msg.sender));

    balances[_token][msg.sender] = safeAdd(balances[_token][msg.sender], _amount);
    globalBalance[_token] = safeAdd(globalBalance[_token], _amount);
    
    require(Token(_token).transferFrom(msg.sender, this, _amount));

    Deposit(_token, msg.sender, msg.sender, _amount);
    
    return(_amount);
  }

  // Withdraw ERC20/223 tokens from the contract back to your wallet
  function withdrawToken(address _token, uint256 _amount)
    external
    returns (uint256)
  {
    if (_token == address(0x0)){
      //keep the nulls to reduce gas usage.
      //require(balances[_token)][msg.sender] >= _amount);
      //handled by safeSub.
      balances[address(0x0)][msg.sender] = safeSub(balances[address(0x0)][msg.sender], _amount);
      globalBalance[address(0x0)] = safeSub(globalBalance[address(0x0)], _amount);

      //transfer has a built in require
      msg.sender.transfer(_amount);
    } else {
      //require(balances[_token][msg.sender] >= _amount);
      //handled by safeSub 
 
      balances[_token][msg.sender] = safeSub(balances[_token][msg.sender], _amount);
      globalBalance[_token] = safeSub(globalBalance[_token], _amount);

      require(Token(_token).transfer(msg.sender, _amount));
    }    

    Withdraw(_token, msg.sender, _amount);
    
    return _amount;
  }

  // Deposit ETH in the contract on behalf of another address
  // Warning: afterwards, only _user will be able to trade or withdraw these funds
  function depositToUser(address _toUser) external payable notLocked returns (bool success) {
    require(
        (_toUser != address(0x0))
     && (_toUser != address(this))
     && (Compliance(complianceAddress).canDeposit(_toUser))
    );
    
    balances[address(0x0)][_toUser] = safeAdd(balances[address(0x0)][_toUser], msg.value);
    globalBalance[address(0x0)] = safeAdd(globalBalance[address(0x0)], msg.value);
    
    Deposit(0x0, _toUser, msg.sender, msg.value);
    
    return true;
  }

  // Deposit ERC20 tokens in the contract on behalf of another address
  // Token(_token).approve(this, _amount) must be called in advance
  // Warning: afterwards, only _toUser will be able to trade or withdraw these funds
  // ERC223 tokens must be deposited by a transfer to this contract ( see tokenFallBack(..) )
  function depositTokenToUser(
    address _toUser,
    address _token,
    uint256 _amount
  )
    external
    notLocked
    returns (bool success)
  {
    require(
        (_token != address(0x0))

     && (_toUser  != address(0x0))
     && (_toUser  != address(this))
     && (_toUser  != _token)
     && (Compliance(complianceAddress).canDeposit(_toUser))
    );
    
    balances[_token][_toUser] = safeAdd(balances[_token][_toUser], _amount);
    globalBalance[_token] = safeAdd(globalBalance[_token], _amount);

    require(Token(_token).transferFrom(msg.sender, this, _amount));

    Deposit(_token, _toUser, msg.sender, _amount);
    
    return true;
  }


  //ERC223 Token Acceptor function, called when an ERC2223 token is transferred to this contract
  // provide _sendTo to make it a deposit on behalf of another address (depositToUser)
  function tokenFallback(
    address _from,  // user calling the function
    uint256 _value, // the number of tokens
    bytes _sendTo     // "deposit to other user" if exactly 20 bytes sent
    
  )
    external
    notLocked
  {
    //first lets figure out who this is going to.
    address toUser = _from;     //probably this
    if (_sendTo.length == 20){  //but use data for sendTo otherwise.

      // I'm about 90% sure I don't need to do the casting here, but for
      // like twenty gas, I'll take the protection from potentially
      // stomping on weird memory locations.
      
      uint256 asmAddress;
      assembly { //uses 50 gas
        asmAddress := calldataload(120)
      }
      toUser = address(asmAddress);
    }
    
    //sanity checks.
    require(
        (toUser != address(0x0))
     && (toUser != address(this))
     && (toUser != msg.sender)  // msg.sender is the token
     && (Compliance(complianceAddress).canDeposit(toUser))
    );
    
    // check if a contract is calling this
    uint256 codeLength;
    assembly {
      codeLength := extcodesize(caller)
    }
    require(codeLength > 0);    
    
    globalBalance[msg.sender] = safeAdd(globalBalance[msg.sender], _value);
    balances[msg.sender][toUser] = safeAdd(balances[msg.sender][toUser], _value);
    
    //sanity check, and as a perk, we check for balanceOf();
    require(Token(msg.sender).balanceOf(this) >= _value);

    Deposit(msg.sender, toUser, _from, _value);
  }

  // Move deposited tokens or ETH (0x0) from one to another address within the contract
  function internalTransfer(
    address _toUser,
    address _token,
    uint256 _amount
  )
    external
    notLocked 
    returns(uint256)
  {
    require(
        (balances[_token][msg.sender] >= _amount)
     && (_toUser != address(0x0))
     && (_toUser != address(this))
     && (_toUser != _token)
     && (Compliance(complianceAddress).canDeposit(_toUser))
    );
 
    balances[_token][msg.sender] = safeSub(balances[_token][msg.sender], _amount);
    balances[_token][_toUser] = safeAdd(balances[_token][_toUser], _amount);

    InternalTransfer(_token, _toUser, msg.sender, _amount);
    
    return(_amount);
  }
  
  // return the token/ETH balance a user has deposited in the contract
  function balanceOf(address _token, address _user) external view returns (uint) {
    return balances[_token][_user];
  }

  
  // In order to see the ERC20 total balance, we're calling an external contract,
  // and this contract claims to be ERC20, but we don't know what's really there.
  // We can't rely on the EVM or solidity to enforce "view", so even though a
  // normal token can rely on itself to be non-malicious, we can't.
  // We have no idea what potentially evil tokens we'll be interacting with.
  // The call to check the reported balance needs to go after the state changes,
  // even though it's un-natural. Now, on one hand, this function might at first
  // appear safe, since we're only allowing the sweeper address to access
  // *this function,* but we are reading the state of the globalBalance.
  // In theory, a malicious token could do the following:
  //  1a) Check if the caller of balanceOf is our contract, if it's not, act normally.
  //  1b) If the caller is our contract, it does the following:
  //  2) Read our contracts globalBalance for its own address.
  //  3) Sets our contract's balance of the token (in the token controller) to our internal globalBalance
  //  4) Allocates some other address the difference in globalBalance and actual balance for our contract.
  //  5) Report back to this function exactly the amount we had in globalBalance.
  // (which, by then is true, since they were stolen).
  // Now we're always going to see 0 extra tokens, and our users have had their tokens perminantly lost.
  // bonus: this is why there is no "sweep all" function.
    
  // Detect ERC20 tokens that have been sent to the contract without a deposit (lost tokens),
  // which are not included in globalBalance[..]
  function sweepTokenAmount(address _token, uint256 _amount) external returns(uint256) {
    assert(msg.sender == sweepAccount);

    balances[_token][sweepAccount] = safeAdd(balances[_token][sweepAccount], _amount);
    globalBalance[_token] = safeAdd(globalBalance[_token], _amount);
    
    //You go last!
	if(_token != address(0x0)) { 
      require(globalBalance[_token] <= Token(_token).balanceOf(this));
	} else {
	  // if another contract performs selfdestruct(UberDelta),
    // ETH can get in here without being in globalBalance
	  require(globalBalance[address(0x0)] <= this.balance); 
	}
    
    TokenSweep(_token, msg.sender, _amount, balances[_token][sweepAccount]);
    
    return(_amount);
  }
  
  
  /*******************************************
  / Regular Trading functions
  /******************************************/
  
  //now contracts can place orders!
  
  
  // Normal order creation happens off-chain and orders are signed by creators,
  // this function allows for on-chain orders to be created
  function order(
    address[4] _addressData,
    uint256[4] _numberData //web3 isn't ready for structs.
  )
    external
    notLocked
    returns (bool success)
  {
  
//    _addressData[2] is maker;
    if (msg.sender != _addressData[2]) { return false; }
    
    bytes32 hash = getHash(_addressData, _numberData);

    orders[hash] = true;

    Order(
      (bytes32(_addressData[0]) ^ bytes32(_addressData[1])),
      msg.sender,
      _addressData,
      _numberData);
    
    return true;
  }  


  function tradeBalances(
    address _takerTokenAddress,
    uint256 _takerTokenAmount,
    address _makerTokenAddress,
    uint256 _makerTokenAmount,
    address _maker,
    uint256 _tradeAmount
  )
    internal
  {
    require(_takerTokenAmount > 0); //safeDiv

    // We charge only the takers this fee
    uint256 feeValue = safeMul(_tradeAmount, feeByClass[userClass[msg.sender]]) / (1 ether);
    
    balances[_takerTokenAddress][_maker] =
      safeAdd(balances[_takerTokenAddress][_maker], _tradeAmount);
    balances[_takerTokenAddress][msg.sender] =
      safeSub(balances[_takerTokenAddress][msg.sender], safeAdd(_tradeAmount, feeValue));
    
    balances[_makerTokenAddress][_maker] =
      safeSub(
        balances[_makerTokenAddress][_maker],
        safeMul(_makerTokenAmount, _tradeAmount) / _takerTokenAmount
      );
    balances[_makerTokenAddress][msg.sender] =
      safeAdd(
        balances[_makerTokenAddress][msg.sender],
        safeMul(_makerTokenAmount, _tradeAmount) / _takerTokenAmount
      );
    
    balances[_takerTokenAddress][feeAccount] =
      safeAdd(balances[_takerTokenAddress][feeAccount], feeValue);
  }


  function trade(
    address[4] _addressData,
    uint256[4] _numberData, //web3 isn't ready for structs.
    uint8 _v,
    bytes32 _r,
    bytes32 _s,
    uint256 _amount,
    bool _fillOrKill
  )
    external
    notLocked
    returns(uint256 tradeAmount)
  {
  
//      _addressData[0], // takerTokenAddress;
//      _numberData[0], // takerTokenAmount;
//      _addressData[1], // makerTokenAddress;
//      _numberData[1], // makerTokenAmount;
//      _numberData[2], // tradeExpires;
//      _numberData[3], // salt;
//      _addressData[2], // maker;
//      _addressData[3] // restrictedTo;
    
    bytes32 hash = getHash(_addressData, _numberData);
    
    tradeAmount = safeSub(_numberData[0], orderFills[hash]); //avail to trade
    
    //balance of giveToken / amount I said I'd give of giveToken * amount I said I want of getToken
    if (
      tradeAmount > safeDiv(
        safeMul(balances[_addressData[1]][_addressData[2]], _numberData[0]),
        _numberData[1]
      )
    )
    {
      tradeAmount = safeDiv(
        safeMul(balances[_addressData[1]][_addressData[2]], _numberData[0]),
        _numberData[1]
      );
    }
    
    if (tradeAmount > _amount) { tradeAmount = _amount; }
    
        //_numberData[0] is takerTokenAmount
    if (tradeAmount == 0) { //idfk. There's nothing there to get. Canceled? Traded?
      if (orderFills[hash] < _numberData[0]) { //Maker seems to be missing tokens?
        FailedTrade(
          (bytes32(_addressData[0]) ^ bytes32(_addressData[1])),
          msg.sender,
          hash,
          0
        );
      } else {  // either cancelled or already traded.
        FailedTrade(
          (bytes32(_addressData[0]) ^ bytes32(_addressData[1])),
          msg.sender,
          hash,
          1
        );
      }
      return 0;
    }
    
    
    if (block.number > _numberData[2]) { //order is expired
      FailedTrade(
        (bytes32(_addressData[0]) ^ bytes32(_addressData[1])),
        msg.sender,
        hash,
        2
      );
      return 0;
    }


    if ((_fillOrKill == true) && (tradeAmount < _amount)) { //didnt fill, so kill
      FailedTrade(
        (bytes32(_addressData[0]) ^ bytes32(_addressData[1])),
        msg.sender,
        hash,
        3
      );
      return 0;
    }
    
        
    uint256 feeValue = safeMul(_amount, feeByClass[userClass[msg.sender]]) / (1 ether);

    //if they trade more than they have, get 0.
    if ( (_amount + feeValue) > balances[_addressData[0]][msg.sender])  { 
      FailedTrade(
        (bytes32(_addressData[0]) ^ bytes32(_addressData[1])),
        msg.sender,
        hash,
        4
      );
      return 0;
    }
    
    if ( //not a valid order.
        (ecrecover(keccak256(signedTradeHash, hash), _v, _r, _s) != _addressData[2])
        && (! orders[hash])
    )
    {
      FailedTrade(
        (bytes32(_addressData[0]) ^ bytes32(_addressData[1])),
        msg.sender,
        hash,
        5
      );
      return 0;
    }

    
    if ((_addressData[3] != address(0x0)) && (_addressData[3] != msg.sender)) { //check restrictedTo
      FailedTrade(
        (bytes32(_addressData[0]) ^ bytes32(_addressData[1])),
        msg.sender,
        hash,
        6
      );
      return 0;
    }
        
    
    if ( //if there's a compliance restriction.
      ((_addressData[0] != address(0x0)) //if not Eth, and restricted, check with Compliance.
        && (restrictedTokens[_addressData[0]] )
        && ! Compliance(complianceAddress).validateTrade(_addressData[0], _addressData[2], msg.sender)
      )
      || ((_addressData[1] != address(0x0))  //ditto
        && (restrictedTokens[_addressData[1]])
        && ! Compliance(complianceAddress).validateTrade(_addressData[1], _addressData[2], msg.sender)
      )
    )
    {
      FailedTrade(
        (bytes32(_addressData[0]) ^ bytes32(_addressData[1])),
        msg.sender,
        hash,
        7
      );
      return 0;
    }
    
    //Do the thing!
    
    tradeBalances(
      _addressData[0], // takerTokenAddress;
      _numberData[0], // takerTokenAmount;
      _addressData[1], // makerTokenAddress;
      _numberData[1], // makerTokenAmount;
      _addressData[2], // maker;
      tradeAmount
    );

    orderFills[hash] = safeAdd(orderFills[hash], tradeAmount);

    Trade(
      (bytes32(_addressData[0]) ^ bytes32(_addressData[1])),
      _addressData[2],
      msg.sender,
      _addressData[1],
      _addressData[0],
      _addressData[3],
      _numberData,
      tradeAmount,
      _fillOrKill
    );
    
    return(tradeAmount);
  }
  
  
  // Cancel a signed order, once this is confirmed nobody will be able to trade it anymore
  function cancelOrder(
    address[4] _addressData,
    uint256[4] _numberData //web3 isn't ready for structs.
  )
    external
    returns(uint256 amountCancelled)
  {
    
    require(msg.sender == _addressData[2]);
    
    //  msg.sender can 'cancel' nonexistent orders since they're offchain.
    bytes32 hash = getHash(_addressData, _numberData);
 
    amountCancelled = safeSub(_numberData[0],orderFills[hash]);
    
    orderFills[hash] = _numberData[0];
 
    //event trigger is moved ahead of balance resetting to allow expression of the already-filled amount
//    _numberData[0] is takerTokenAmount;
    Cancel(
      (bytes32(_addressData[0]) ^ bytes32(_addressData[1])),
      msg.sender,
      _addressData,
      _numberData,
      amountCancelled);

    return amountCancelled;    
  }



  /**************************
  / Remote Withdraw
  ***************************/
  
  // Perform an ETH withdraw transaction for someone else based on their signed message
  // Useful if the owner of the funds does not have enough ETH for gas fees in their wallet.
  // msg.sender receives fee for the effort and gas costs
  function remoteWithdraw(
    uint256 _withdrawAmount,
    uint256 _feeAmount,
    uint256 _withdrawExpires,
    uint256 _salt,
    address _maker,
    address _restrictedTo, //0x0 = anyone
    uint8 _v,
    bytes32 _r,
    bytes32 _s
  )
    external
    notLocked
    returns(bool)
  {
    //is the withdraw possible?
    require(
        (balances[address(0x0)][_maker] >= safeAdd(_withdrawAmount, _feeAmount))
     && (
            (_restrictedTo == address(0x0))
         || (_restrictedTo == msg.sender)
        )
     && ((_feeAmount == 0) || (Compliance(complianceAddress).canDeposit(msg.sender)))
    );
    
    //has this withdraw happened already? (and generate the hash)

    bytes32 hash = keccak256(
      this, 
      _withdrawAmount,
      _feeAmount,
      _withdrawExpires,
      _salt,
      _maker,
      _restrictedTo
    );

    require(orderFills[hash] == 0);

    //is this real?
    require(
      ecrecover(keccak256(signedWithdrawHash, hash), _v, _r, _s) == _maker
    );
    
    //only once.
    orderFills[hash] = 1;

    balances[address(0x0)][_maker] =
      safeSub(balances[address(0x0)][_maker], safeAdd(_withdrawAmount, _feeAmount));
    // pay fee to the user performing the remote withdraw
    balances[address(0x0)][msg.sender] = safeAdd(balances[address(0x0)][msg.sender], _feeAmount);
    
    globalBalance[address(0x0)] = safeSub(globalBalance[address(0x0)], _withdrawAmount);

    RemoteWithdraw(
      _maker,
      msg.sender,
      _withdrawAmount,
      _feeAmount,
      _withdrawExpires,
      _salt,
      _restrictedTo
    );

    //implicit require included.
    _maker.transfer(_withdrawAmount);
    
    return(true);
  }

  // cancel a signed request for a remote withdraw
  function cancelRemoteWithdraw(
    uint256 _withdrawAmount,
    uint256 _feeAmount,
    uint256 _withdrawExpires,
    uint256 _salt,
    address _restrictedTo //0x0 = anyone
  )
    external
  {
      // msg.sender can cancel nonexsistent orders.
    bytes32 hash = keccak256(
      this, 
      _withdrawAmount,
      _feeAmount,
      _withdrawExpires,
      _salt,
      msg.sender,
      _restrictedTo
    );
    
    CancelRemoteWithdraw(
      msg.sender,
      _withdrawAmount,
      _feeAmount,
      _withdrawExpires,
      _salt,
      _restrictedTo,
      orderFills[hash]
    );
    
    //set to completed after, event shows pre-cancel status.
    orderFills[hash] = 1;
  }
  
  
 

  /**************************
  /Upgrade Function
  ***************************/
      
  // move tokens/ETH over to a new upgraded smart contract  (avoids having to withdraw & deposit)
  function upgrade(address _token) external returns(uint256 moveBalance) {
    require (newExchange != address(0x0));

    moveBalance = balances[_token][msg.sender];

    globalBalance[_token] = safeSub(globalBalance[_token], moveBalance);
    balances[_token][msg.sender] = 0;

    if (_token != address(0x0)){
      require(Token(_token).approve(newExchange, moveBalance));
      require(UberDelta(newExchange).depositTokenToUser(msg.sender, _token, moveBalance));
    } else {
      require(UberDelta(newExchange).depositToUser.value(moveBalance)(msg.sender));
    }

    Upgrade(msg.sender, _token, newExchange, moveBalance);
    
    return(moveBalance);
  }


  
  /*******************************************
  / Data View functions
  /******************************************/
  
  function testTrade(
    address[4] _addressData,
    uint256[4] _numberData, //web3 isn't ready for structs.
    uint8 _v,
    bytes32 _r,
    bytes32 _s,
    uint256 _amount,
    address _sender,
    bool _fillOrKill
  )
    public
    view
    returns(uint256)
  {
    uint256 feeValue = safeMul(_amount, feeByClass[userClass[_sender]]) / (1 ether);

    if (
      contractLocked
      ||
      ((_addressData[0] != address(0x0)) //if not Eth, and restricted, check with Compliance.
        && (restrictedTokens[_addressData[0]] )
        && ! Compliance(complianceAddress).validateTrade(_addressData[0], _addressData[2], _sender)
      )
      || ((_addressData[1] != address(0x0))  //ditto
        && (restrictedTokens[_addressData[1]])
        && ! Compliance(complianceAddress).validateTrade(_addressData[1], _addressData[2], _sender)
      )
         //if they trade more than they have, get 0.
      || ((_amount + feeValue) > balances[_addressData[0]][_sender]) 
      || ((_addressData[3] != address(0x0)) && (_addressData[3] != _sender)) //check restrictedTo
    )
    {
      return 0;
    }
      
    uint256 tradeAmount = availableVolume(
        _addressData,
        _numberData,
        _v,
        _r,
        _s
    );
    
    if (tradeAmount > _amount) { tradeAmount = _amount; }
    
    if ((_fillOrKill == true) && (tradeAmount < _amount)) {
      return 0;
    }

    return tradeAmount;
  }


  // get how much of an order is left (unfilled)
  // return value in order of _takerTokenAddress
  function availableVolume(
    address[4] _addressData,
    uint256[4] _numberData, //web3 isn't ready for structs.
    uint8 _v,
    bytes32 _r,
    bytes32 _s
  )
    public
    view
    returns(uint256 amountRemaining)
  {     
//    _addressData[0] // takerTokenAddress;
//    _numberData[0] // takerTokenAmount;
//    _addressData[1] // makerTokenAddress;
//    _numberData[1] // makerTokenAmount;
//    _numberData[2] // tradeExpires;
//    _numberData[3] // salt;
//    _addressData[2] // maker;
//    _addressData[3] // restrictedTo;

    bytes32 hash = getHash(_addressData, _numberData);

    if (
      (block.number > _numberData[2])
      || ( 
        (ecrecover(keccak256(signedTradeHash, hash), _v, _r, _s) != _addressData[2])
        && (! orders[hash])
      )
    ) { return 0; }

    //uint256 amountRemaining = safeSub(myTrade.takerTokenAmount, orderFills[hash]);
     amountRemaining = safeSub(_numberData[0], orderFills[hash]);

    if (
      amountRemaining < safeDiv(
        safeMul(balances[_addressData[1]][_addressData[2]], _numberData[0]),
        _numberData[1]
      )
    ) return amountRemaining;

    return (
      safeDiv(
        safeMul(balances[_addressData[1]][_addressData[2]], _numberData[0]),
        _numberData[1]
      )
    );
  }


  // get how much of an order has been filled
  // return value in order of _takerTokenAddress
  function getUserFee(
    address _user
  )
    external
    view
    returns(uint256)
  {
    return feeByClass[userClass[_user]];
  }


  // get how much of an order has been filled
  // return value in order of _takerTokenAddress
  function amountFilled(
    address[4] _addressData,
    uint256[4] _numberData //web3 isn't ready for structs.
  )
    external
    view
    returns(uint256)
  {
    bytes32 hash = getHash(_addressData, _numberData);

    return orderFills[hash];
  }

  
  // check if a request for a remote withdraw is still valid
  function testRemoteWithdraw(
    uint256 _withdrawAmount,
    uint256 _feeAmount,
    uint256 _withdrawExpires,
    uint256 _salt,
    address _maker,
    address _restrictedTo,
    uint8 _v,
    bytes32 _r,
    bytes32 _s,
    address _sender
  )
    external
    view
    returns(uint256)
  {
    bytes32 hash = keccak256(
      this,
      _withdrawAmount,
      _feeAmount,
      _withdrawExpires,
      _salt,
      _maker,
      _restrictedTo
    );

    if (
      contractLocked
      ||
      (balances[address(0x0)][_maker] < safeAdd(_withdrawAmount, _feeAmount))
      ||((_restrictedTo != address(0x0)) && (_restrictedTo != _sender))
      || (orderFills[hash] != 0)
      || (ecrecover(keccak256(signedWithdrawHash, hash), _v, _r, _s) != _maker)
      || ((_feeAmount > 0) && (! Compliance(complianceAddress).canDeposit(_sender)))
    )
    {
      return 0;
    } else {
      return _withdrawAmount;
    }
  }
  
  
  
  function getHash(
    address[4] _addressData,
    uint256[4] _numberData //web3 isn't ready for structs.
  )
    public
    view
    returns(bytes32)
  {
    return(
      keccak256(
        this,
        _addressData[0], // takerTokenAddress;
        _numberData[0], // takerTokenAmount;
        _addressData[1], // makerTokenAddress;
        _numberData[1], // makerTokenAmount;
        _numberData[2], // tradeExpires;
        _numberData[3], // salt;
        _addressData[2], // maker;
        _addressData[3] // restrictedTo;
      )
    );
  }
  
  

  /***********************************
  / Compliance View Code
  ************************************/
  //since the compliance code might move, we should have a way to always
  //call a function to this contract to get the current values

    function testCanDeposit(
    address _user
  )
    external
    view
    returns (bool)
  {
    return(Compliance(complianceAddress).canDeposit(_user));
  }
  
  function testCanTrade(
    address _token,
    address _user
  )
    external
    view
    returns (bool)
  {
    return(Compliance(complianceAddress).canTrade(_token, _user));
  }

  
  function testValidateTrade(
    address _token,
    address _getUser,
    address _giveUser
  )
    external
    view
    returns (bool isAllowed)
  {
    return(Compliance(complianceAddress).validateTrade(_token, _getUser, _giveUser));
  }
  


  /**************************
  / Default Compliance Code
  ***************************/
  // These will eventually live in a different contract.
  // every can deposit by default, later a registry?
  // For now, always say no if called for trades. 
  // the earliest use may be halting trade in a token.
  function canDeposit(
    address _user
  )
    public
    view
    returns (bool isAllowed)
  {
    return(true);
  }
  
  function canTrade(
    address _token,
    address _user
  )
    public
    view
    returns (bool isAllowed)
  {
    return(false);
  }

  
  function validateTrade(
    address _token,
    address _getUser,
    address _giveUser
  )
    public
    view
    returns (bool isAllowed)
  {
    return(false);
  }
  


  /***********************************
  / THIS IS WHERE OPTIONS LIVE!!!!
  /**********************************/
  
  
  mapping (address => uint256) public exercisedOptions;
  
  //get asset for tickets
  event CollapseOption(
    address indexed user,
    address indexed holderTicketAddress,
    address indexed writerTicketAddress,
    uint256 ticketsCollapsed,
    bytes32 optionPair //assetTokenAddress xor strikeTokenAddress
  );    
  
  //get holderticket + asset for strike
  event ExcerciseUnwind(
    address indexed user,
    address indexed holderTicketAddress,
    uint256 ticketsUnwound,
    bytes32 optionPair,
    bool fillOrKill
  );  
  
  //get asset for writerticket
  event ExpireOption(
    address indexed user,
    address indexed writerTicketAddress,
    uint256 ticketsExpired,
    bytes32 optionPair
  );  
  
  //get tickets for asset
  event CreateOption(
    address indexed user,
    address indexed holderTicketAddress,
    address indexed writerTicketAddress,
    uint256 ticketsCreated,
    bytes32 optionPair
  );  
  
  //get assset for strike + holderticket
  event ExcerciseOption(
    address indexed user,
    address indexed holderTicketAddress,
    uint256 ticketsExcercised,
    bytes32 optionPair //assetTokenAddress xor strikeTokenAddress
  );  
  
  /******************
  / optionFunctions
  ******************/
  
  //if before expiry, deposit asset, get buy ticket, write ticket
  // 1 ticket gets (10^18) option units credited to them.
  function createOptionPair( //#65
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires,
    uint256 _ticketAmount //tickets times (1 ether)
  )
    external
    notLocked
    returns (uint256 ticketsCreated)
  {
    //if before expiry
    require (block.number < _optionExpires); //option would be expired
    
    //if they have the asset
    //[checked by safemath during locking]

    //lock asset to 0x0.
    //the percent of one contract times _assetTokenAmount = amount moving
    //creation fee?
    balances[_assetTokenAddress][0x0] =
      safeAdd(
        balances[_assetTokenAddress][0x0],
        safeDiv(safeMul(_assetTokenAmount, _ticketAmount), 1 ether)
      );

    balances[_assetTokenAddress][msg.sender] =
      safeSub(
        balances[_assetTokenAddress][msg.sender],
        safeDiv(safeMul(_assetTokenAmount, _ticketAmount), 1 ether)
      );
    
    
    address holderTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      false
    );
    
    address writerTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      true
    );
    
    //issue write option
    balances[writerTicketAddress][msg.sender] =
      safeAdd(balances[writerTicketAddress][msg.sender], _ticketAmount);
    globalBalance[writerTicketAddress] =
      safeAdd(globalBalance[writerTicketAddress], _ticketAmount);

    //issue hold option
    balances[holderTicketAddress][msg.sender] =
      safeAdd(balances[holderTicketAddress][msg.sender], _ticketAmount);
    globalBalance[holderTicketAddress] =
      safeAdd(globalBalance[holderTicketAddress], _ticketAmount);

    CreateOption(
      msg.sender,
      holderTicketAddress,
      writerTicketAddress,
      _ticketAmount,
      (bytes32(_assetTokenAddress) ^ bytes32(_strikeTokenAddress))
    );
    
    //check if we need to register, and do if we do.
    if (
      OptionRegistry(optionsRegistryAddress).isOptionPairRegistered(
        _assetTokenAddress,
        _assetTokenAmount,
        _strikeTokenAddress,
        _strikeTokenAmount,
        _optionExpires
      )
      == false
    )
    {
      require(
        OptionRegistry(optionsRegistryAddress).registerOptionPair(
          _assetTokenAddress,
          _assetTokenAmount,
          _strikeTokenAddress,
          _strikeTokenAmount,
          _optionExpires
        )
      );
    }
    return _ticketAmount;
  }
  
  //if own buy & writer ticket get asset, void tickets
  // 1 ticket gets 10^18 option units voided.
  function collapseOptionPair( //#66
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires,
    uint256 _ticketAmount
  )
    external
    returns (uint256 ticketsCollapsed)
  {
    
    address holderTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      false
    );
    
    address writerTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      true
    );
    
    //if they have the write option
    //if they have the hold option
    require (
      (balances[holderTicketAddress][msg.sender] >= _ticketAmount)
      && (balances[writerTicketAddress][msg.sender] >= _ticketAmount)
    );
    //I guess it can be expired, since you have both legs.
    
    //void write option
    balances[writerTicketAddress][msg.sender] =
      safeSub(balances[writerTicketAddress][msg.sender], _ticketAmount);
    globalBalance[writerTicketAddress] =
      safeSub(globalBalance[writerTicketAddress], _ticketAmount);

    //void hold option
    balances[holderTicketAddress][msg.sender] =
      safeSub(balances[holderTicketAddress][msg.sender], _ticketAmount);
    globalBalance[holderTicketAddress] =
      safeSub(globalBalance[holderTicketAddress], _ticketAmount);
 
    //unlock asset
    balances[_assetTokenAddress][0x0] = safeSub(
      balances[_assetTokenAddress][0x0],
      safeDiv(safeMul(_assetTokenAmount, _ticketAmount), 1 ether)
    );

    balances[_assetTokenAddress][msg.sender] = safeAdd(
      balances[_assetTokenAddress][msg.sender],
      safeDiv(safeMul(_assetTokenAmount, _ticketAmount), 1 ether)
    );
    
    //emit event
    CollapseOption(
      msg.sender,
      holderTicketAddress,
      writerTicketAddress,
      _ticketAmount,
      (bytes32(_assetTokenAddress) ^ bytes32(_strikeTokenAddress))
    );
    
    return _ticketAmount;
  }

  /*about invisableHandOfAdamSmith():
    q: why would someone ever want to buy an out-of-the-money,
       collaterized call option at strike price?

    a: if an american option is executed, and the collateral's movement
       makes it later out of the money, the value of the option would
       need to be calculated by including the "pre-executed" amount.
       * 
       This would prevent an external actor performing weird arb trades
       (write a billion tickets, collapse a billion tickets, profit!).
       Skip the middle man! Writers are more likely to get 100% token or
       strike at expiry, based on market value, and holders still have
       their option intact.
       * 
       Arbers gonna arb. Let them do their thing.
*/

  //if there have been executions, Adam Smith can deposit asset, get strike, up to execution amount.
//  function invisibleHandOfAdamSmith( //#67

  function optionExcerciseUnwind(
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires,
    uint256 _ticketAmount,
    bool _fillOrKill //do we want? probably...
  )
    external
    notLocked
    returns (uint256 ticketsUnwound) //(amountTraded)
  {
    //only before, equal to expiry
    require(block.number <= _optionExpires);
    
    address holderTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      false
    );
    
    //if strike-pool[hash] != 0 {
    ticketsUnwound = exercisedOptions[holderTicketAddress];

    //fill or kill.
    require((_fillOrKill == false) || (ticketsUnwound >= _ticketAmount));

    //get amount to trade.
    if (ticketsUnwound > _ticketAmount) ticketsUnwound = _ticketAmount;
    
    require(ticketsUnwound > 0);
    //cant buy zero, either because not avail, or you asked for zero.
 
    //check compliance, like a trade!
    require(
      (! restrictedTokens[holderTicketAddress]) //if it is not restricted
    || Compliance(complianceAddress).canTrade(holderTicketAddress, msg.sender) // or compliance says yes.
    );

    //debit balance of caller of asset tokens, credit 0x0
    balances[_assetTokenAddress][msg.sender] = safeSub(
      balances[_assetTokenAddress][msg.sender],
      safeDiv(safeMul(_assetTokenAmount, ticketsUnwound), 1 ether)
    );

    balances[_assetTokenAddress][0x0] = safeAdd(
      balances[_assetTokenAddress][0x0],
      safeDiv(safeMul(_assetTokenAmount, ticketsUnwound), 1 ether)
    );
    
    //debit balance of exercisedOptions of holdOption, credit caller.
    //no change in global balances.
    exercisedOptions[holderTicketAddress] =
      safeSub(exercisedOptions[holderTicketAddress], ticketsUnwound);
    balances[holderTicketAddress][msg.sender] =
      safeAdd(balances[holderTicketAddress][msg.sender], ticketsUnwound);

    //debit balance of 0x0 of strike, credit caller.
    balances[_strikeTokenAddress][0x0] = safeSub(
      balances[_strikeTokenAddress][0x0],
      safeDiv(safeMul(_strikeTokenAmount, ticketsUnwound), 1 ether)
    );

    balances[_strikeTokenAddress][msg.sender] = safeAdd(
      balances[_strikeTokenAddress][msg.sender],
      safeDiv(safeMul(_strikeTokenAmount, ticketsUnwound), 1 ether)
    );
    
    //emit event.
    ExcerciseUnwind(
      msg.sender,
      holderTicketAddress,
      ticketsUnwound,
      (bytes32(_assetTokenAddress) ^ bytes32(_strikeTokenAddress)),
      _fillOrKill
    );
    
    return ticketsUnwound;
  }
  
  //if before expiry, and own hold ticket, then pay strike, get asset, void hold ticket
  function excerciseOption( //#68
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires,
    uint256 _ticketAmount
  )
  external 
  returns (uint256 ticketsExcercised)
  {  
    //only holder before, equal to expiry
    require(block.number <= _optionExpires);
    
    address holderTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      false
    );
    
    //get balance of tickets
    ticketsExcercised = balances[holderTicketAddress][msg.sender];
    require(ticketsExcercised >= _ticketAmount); //its just a balance here.
    
    //get amount to trade.
    if (ticketsExcercised > _ticketAmount) ticketsExcercised = _ticketAmount;
    
    //cant execute zero, either you have zero, or you asked for zero.
    require(ticketsExcercised > 0);
    
    //debit balance of caller for holdOption, credit exercisedOptions    
    balances[holderTicketAddress][msg.sender] =
      safeSub(balances[holderTicketAddress][msg.sender], ticketsExcercised);
    exercisedOptions[holderTicketAddress] =
      safeAdd(exercisedOptions[holderTicketAddress], ticketsExcercised);
        
    //debit balance of caller for strikeToken, credit 0x0
    balances[_strikeTokenAddress][msg.sender] = safeSub(
      balances[_strikeTokenAddress][msg.sender],
      safeDiv(safeMul(_strikeTokenAmount, ticketsExcercised), 1 ether)
    );

    balances[_strikeTokenAddress][0x0] = safeAdd(
      balances[_strikeTokenAddress][0x0],
      safeDiv(safeMul(_strikeTokenAmount, ticketsExcercised), 1 ether)
    );
    
    //debit balance of 0x0 of asset, credit caller.   
    balances[_assetTokenAddress][0x0] = safeSub(
      balances[_assetTokenAddress][0x0],
      safeDiv(safeMul(_assetTokenAmount, ticketsExcercised), 1 ether)
    );
    
    balances[_assetTokenAddress][msg.sender] = safeAdd(
      balances[_assetTokenAddress][msg.sender],
      safeDiv(safeMul(_assetTokenAmount, ticketsExcercised), 1 ether)
    );

    
    //no change in global balances.
    //emit event.
    ExcerciseOption(
      msg.sender,
      holderTicketAddress,
      ticketsExcercised,
      (bytes32(_assetTokenAddress) ^ bytes32(_strikeTokenAddress))
    );
    
    return ticketsExcercised;
  }

  
  //if after expiry, get collateral, void option.
  function expireOption( //#69
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires,
    uint256 _ticketAmount
  )
  external 
  returns (uint256 ticketsExpired)
  {
  //only writer, only after expiry
    require(block.number > _optionExpires);
        
    address holderTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      false
    );
    
    address writerTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      true
    );
    
    //get balance of tickets
    ticketsExpired = balances[writerTicketAddress][msg.sender];
    require(ticketsExpired >= _ticketAmount); //its just a balance here.
    
    //get amount to trade.
    if (ticketsExpired > _ticketAmount) ticketsExpired = _ticketAmount;
    
    //cant execute zero, either you have zero, or you asked for zero.
    require(ticketsExpired > 0);
    
    // debit holder tickets from user, add to exercisedOptions.
    balances[writerTicketAddress][msg.sender] =
      safeSub(balances[writerTicketAddress][msg.sender], ticketsExpired);
    exercisedOptions[writerTicketAddress] =
      safeAdd(exercisedOptions[writerTicketAddress], ticketsExpired);
    
    //calculate amounts
    uint256 strikeTokenAmount =
      safeDiv(
        safeMul(
          safeDiv(safeMul(ticketsExpired, _strikeTokenAmount), 1 ether), //tickets
          exercisedOptions[holderTicketAddress]
        ),
        globalBalance[holderTicketAddress]
      );

    uint256 assetTokenAmount =
      safeDiv(
        safeMul(
          safeDiv(safeMul(ticketsExpired, _assetTokenAmount), 1 ether), //tickets
          safeSub(globalBalance[holderTicketAddress], exercisedOptions[holderTicketAddress])
        ),
        globalBalance[holderTicketAddress]
      );
    

    //debit zero, add to msg.sender
    balances[_strikeTokenAddress][0x0] =
      safeSub(balances[_strikeTokenAddress][0x0], strikeTokenAmount);
    balances[_assetTokenAddress][0x0] =
      safeSub(balances[_assetTokenAddress][0x0], assetTokenAmount);
    balances[_strikeTokenAddress][msg.sender] =
      safeAdd(balances[_strikeTokenAddress][msg.sender], strikeTokenAmount);
    balances[_assetTokenAddress][msg.sender] =
      safeAdd(balances[_assetTokenAddress][msg.sender], assetTokenAmount);
  
  //set inactive

    ExpireOption( //#69]
      msg.sender,
      writerTicketAddress,
      ticketsExpired,
      (bytes32(_assetTokenAddress) ^ bytes32(_strikeTokenAddress))
    );
    return ticketsExpired;
  }


  //get an option's Hash's address
  //  (•_•)  ( •_•)>⌐■-■  (⌐■_■)
  //
  //going from 32 bytes to 20 bytes still gives us 160 bits of hash goodness.
  //that's still a crazy large number, and used by ethereum for addresses.
  function getOptionAddress(
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires,
    bool _isWriter
  )
    public
    view
    returns(address)
  {
    return(
      address(
        keccak256(
          _assetTokenAddress,
          _assetTokenAmount,
          _strikeTokenAddress,
          _strikeTokenAmount,
          _optionExpires,
          _isWriter
        )
      )
    );
  }

  /***********************************
  / Options View Code
  ************************************/
  //since the options code might move, we should have a way to always
  //call a function to this contract to get the current values
  
  function testIsOptionPairRegistered(
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires
  )
  external
  view
  returns(bool)
  {
    return(
      OptionRegistry(optionsRegistryAddress).isOptionPairRegistered(
        _assetTokenAddress,
        _assetTokenAmount,
        _strikeTokenAddress,
        _strikeTokenAmount,
        _optionExpires
      )
    );
  }
  

  /***********************************
  / Default Options Registration Code
  ************************************/
  // Register emits an event and adds it to restrictedToken.
  // We'll deal with any other needed registration later.
  // Set up for upgradeable external contract.
  // return bools.
  
  event RegisterOptionsPair(
    bytes32 indexed optionPair, //assetTokenAddress xor strikeTokenAddress
    address indexed writerTicketAddress,
    address indexed holderTicketAddress,
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires
  );  
  
    
  function registerOptionPair(
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires
  )
  public
  returns(bool)
  {
    address holderTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      false
    );
    
//    if (
//      isOptionPairRegistered(
//        _assetTokenAddress,
//        _assetTokenAmount,
//        _strikeTokenAddress,
//        _strikeTokenAmount,
//        _optionExpires
//      )
//    )
    //cheaper not to make call gaswise, same result.
    
    if (restrictedTokens[holderTicketAddress]) {
      return false;
    //return halts execution, but else is better for readibility
    } else {

      address writerTicketAddress = getOptionAddress(
        _assetTokenAddress,
        _assetTokenAmount,
        _strikeTokenAddress,
        _strikeTokenAmount,
        _optionExpires,
        true
      );
    
      restrictedTokens[holderTicketAddress] = true;
      restrictedTokens[writerTicketAddress] = true;
    
      //an external contract would need to call something like this:
      // after being registered as a helper contract on the main site.
      //UberDelta(uberdeltaAddress).tokenRestriction(holderTicketAddress, true);
      //UberDelta(uberdeltaAddress).tokenRestriction(writerTicketAddress, true);
    
      RegisterOptionsPair(
        (bytes32(_assetTokenAddress) ^ bytes32(_strikeTokenAddress)),
        holderTicketAddress,
        writerTicketAddress,
        _assetTokenAddress,
        _assetTokenAmount,
        _strikeTokenAddress,
        _strikeTokenAmount,
        _optionExpires
      );
    
      return(true);
    }
  }
  
  
  // for v1, we'll simply return if there's a restriction.
  function isOptionPairRegistered(
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires
  )
  public
  view
  returns(bool)
  {
    address holderTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      false
    );
    
    return(restrictedTokens[holderTicketAddress]);
  }
  
  
  function getOptionPair(
    address _assetTokenAddress,
    uint256 _assetTokenAmount,
    address _strikeTokenAddress,
    uint256 _strikeTokenAmount,
    uint256 _optionExpires
  )
  public
  view
  returns(address holderTicketAddress, address writerTicketAddress)
  {
    holderTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      false
    );
    
    writerTicketAddress = getOptionAddress(
      _assetTokenAddress,
      _assetTokenAmount,
      _strikeTokenAddress,
      _strikeTokenAmount,
      _optionExpires,
      true
    );
    
    return(holderTicketAddress, writerTicketAddress);
  }
  
  
  /******************
  / EOS Registration
  ******************/
  // some users will accidentally keep EOS on the exchange during the snapshot.
  function EOSRegistration (string _key) external onlyOwner{
    EOS(0xd0a6E6C54DbC68Db5db3A091B171A77407Ff7ccf).register(_key);
  }
  
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"name":"_token","type":"address"},{"name":"_getUser","type":"address"},{"name":"_giveUser","type":"address"}],"name":"validateTrade","outputs":[{"name":"isAllowed","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"newExchange","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_user","type":"address"}],"name":"getUserFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"upgrade","outputs":[{"name":"moveBalance","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_user","type":"address"},{"name":"_newClass","type":"uint256"}],"name":"changeUserClass","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_assetTokenAddress","type":"address"},{"name":"_assetTokenAmount","type":"uint256"},{"name":"_strikeTokenAddress","type":"address"},{"name":"_strikeTokenAmount","type":"uint256"},{"name":"_optionExpires","type":"uint256"},{"name":"_isWriter","type":"bool"}],"name":"getOptionAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"userClass","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_addressData","type":"address[4]"},{"name":"_numberData","type":"uint256[4]"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"availableVolume","outputs":[{"name":"amountRemaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_toUser","type":"address"},{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"depositTokenToUser","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_withdrawAmount","type":"uint256"},{"name":"_feeAmount","type":"uint256"},{"name":"_withdrawExpires","type":"uint256"},{"name":"_salt","type":"uint256"},{"name":"_maker","type":"address"},{"name":"_restrictedTo","type":"address"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"}],"name":"remoteWithdraw","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_class","type":"uint256"},{"name":"_fee","type":"uint256"}],"name":"changeClassFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"},{"name":"_user","type":"address"}],"name":"testCanTrade","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_withdrawAmount","type":"uint256"},{"name":"_feeAmount","type":"uint256"},{"name":"_withdrawExpires","type":"uint256"},{"name":"_salt","type":"uint256"},{"name":"_maker","type":"address"},{"name":"_restrictedTo","type":"address"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"},{"name":"_sender","type":"address"}],"name":"testRemoteWithdraw","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"contractLocked","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"depositToken","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_assetTokenAddress","type":"address"},{"name":"_assetTokenAmount","type":"uint256"},{"name":"_strikeTokenAddress","type":"address"},{"name":"_strikeTokenAmount","type":"uint256"},{"name":"_optionExpires","type":"uint256"}],"name":"isOptionPairRegistered","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"manager","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_user","type":"address"}],"name":"canDeposit","outputs":[{"name":"isAllowed","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_key","type":"string"}],"name":"EOSRegistration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"feeByClass","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newComplianceAddress","type":"address"}],"name":"updateComplianceAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_toUser","type":"address"},{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"internalTransfer","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newExchange","type":"address"}],"name":"changeNewExchange","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_addressData","type":"address[4]"},{"name":"_numberData","type":"uint256[4]"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"},{"name":"_amount","type":"uint256"},{"name":"_fillOrKill","type":"bool"}],"name":"trade","outputs":[{"name":"tradeAmount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"},{"name":"_user","type":"address"}],"name":"canTrade","outputs":[{"name":"isAllowed","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeAccount","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"exercisedOptions","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_feeAccount","type":"address"}],"name":"changeFeeAccount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"optionsRegistryAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_assetTokenAddress","type":"address"},{"name":"_assetTokenAmount","type":"uint256"},{"name":"_strikeTokenAddress","type":"address"},{"name":"_strikeTokenAmount","type":"uint256"},{"name":"_optionExpires","type":"uint256"},{"name":"_ticketAmount","type":"uint256"},{"name":"_fillOrKill","type":"bool"}],"name":"optionExcerciseUnwind","outputs":[{"name":"ticketsUnwound","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_addressData","type":"address[4]"},{"name":"_numberData","type":"uint256[4]"}],"name":"order","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_assetTokenAddress","type":"address"},{"name":"_assetTokenAmount","type":"uint256"},{"name":"_strikeTokenAddress","type":"address"},{"name":"_strikeTokenAmount","type":"uint256"},{"name":"_optionExpires","type":"uint256"}],"name":"testIsOptionPairRegistered","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_lock","type":"bool"}],"name":"lockContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"},{"name":"_getUser","type":"address"},{"name":"_giveUser","type":"address"}],"name":"testValidateTrade","outputs":[{"name":"isAllowed","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newManager","type":"address"}],"name":"newManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"globalBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"orders","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"withdrawToken","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_assetTokenAddress","type":"address"},{"name":"_assetTokenAmount","type":"uint256"},{"name":"_strikeTokenAddress","type":"address"},{"name":"_strikeTokenAmount","type":"uint256"},{"name":"_optionExpires","type":"uint256"}],"name":"getOptionPair","outputs":[{"name":"holderTicketAddress","type":"address"},{"name":"writerTicketAddress","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_toUser","type":"address"}],"name":"depositToUser","outputs":[{"name":"success","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_newToken","type":"address"},{"name":"_status","type":"bool"}],"name":"tokenRestriction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newOptionsRegistryAddress","type":"address"}],"name":"updateOptionsRegistryAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isHelper","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_value","type":"uint256"},{"name":"_sendTo","type":"bytes"}],"name":"tokenFallback","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sweepAccount","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"balances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_assetTokenAddress","type":"address"},{"name":"_assetTokenAmount","type":"uint256"},{"name":"_strikeTokenAddress","type":"address"},{"name":"_strikeTokenAmount","type":"uint256"},{"name":"_optionExpires","type":"uint256"},{"name":"_ticketAmount","type":"uint256"}],"name":"collapseOptionPair","outputs":[{"name":"ticketsCollapsed","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_addressData","type":"address[4]"},{"name":"_numberData","type":"uint256[4]"}],"name":"amountFilled","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_assetTokenAddress","type":"address"},{"name":"_assetTokenAmount","type":"uint256"},{"name":"_strikeTokenAddress","type":"address"},{"name":"_strikeTokenAmount","type":"uint256"},{"name":"_optionExpires","type":"uint256"},{"name":"_ticketAmount","type":"uint256"}],"name":"expireOption","outputs":[{"name":"ticketsExpired","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_addressData","type":"address[4]"},{"name":"_numberData","type":"uint256[4]"},{"name":"_v","type":"uint8"},{"name":"_r","type":"bytes32"},{"name":"_s","type":"bytes32"},{"name":"_amount","type":"uint256"},{"name":"_sender","type":"address"},{"name":"_fillOrKill","type":"bool"}],"name":"testTrade","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"newOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"confirmOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_helper","type":"address"},{"name":"_status","type":"bool"}],"name":"changeHelper","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"restrictedTokens","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_withdrawAmount","type":"uint256"},{"name":"_feeAmount","type":"uint256"},{"name":"_withdrawExpires","type":"uint256"},{"name":"_salt","type":"uint256"},{"name":"_restrictedTo","type":"address"}],"name":"cancelRemoteWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"sweepTokenAmount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_assetTokenAddress","type":"address"},{"name":"_assetTokenAmount","type":"uint256"},{"name":"_strikeTokenAddress","type":"address"},{"name":"_strikeTokenAmount","type":"uint256"},{"name":"_optionExpires","type":"uint256"}],"name":"registerOptionPair","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_user","type":"address"}],"name":"testCanDeposit","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_assetTokenAddress","type":"address"},{"name":"_assetTokenAmount","type":"uint256"},{"name":"_strikeTokenAddress","type":"address"},{"name":"_strikeTokenAmount","type":"uint256"},{"name":"_optionExpires","type":"uint256"},{"name":"_ticketAmount","type":"uint256"}],"name":"createOptionPair","outputs":[{"name":"ticketsCreated","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_addressData","type":"address[4]"},{"name":"_numberData","type":"uint256[4]"}],"name":"getHash","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_addressData","type":"address[4]"},{"name":"_numberData","type":"uint256[4]"}],"name":"cancelOrder","outputs":[{"name":"amountCancelled","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"orderFills","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"},{"name":"_user","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_sweepAccount","type":"address"}],"name":"changeSweepAccount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"complianceAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_assetTokenAddress","type":"address"},{"name":"_assetTokenAmount","type":"uint256"},{"name":"_strikeTokenAddress","type":"address"},{"name":"_strikeTokenAmount","type":"uint256"},{"name":"_optionExpires","type":"uint256"},{"name":"_ticketAmount","type":"uint256"}],"name":"excerciseOption","outputs":[{"name":"ticketsExcercised","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":false,"stateMutability":"nonpayable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"tradePair","type":"bytes32"},{"indexed":true,"name":"maker","type":"address"},{"indexed":false,"name":"addressData","type":"address[4]"},{"indexed":false,"name":"numberData","type":"uint256[4]"}],"name":"Order","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"tradePair","type":"bytes32"},{"indexed":true,"name":"maker","type":"address"},{"indexed":false,"name":"addressData","type":"address[4]"},{"indexed":false,"name":"numberData","type":"uint256[4]"},{"indexed":false,"name":"status","type":"uint256"}],"name":"Cancel","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"tradePair","type":"bytes32"},{"indexed":true,"name":"taker","type":"address"},{"indexed":false,"name":"hash","type":"bytes32"},{"indexed":false,"name":"failReason","type":"uint256"}],"name":"FailedTrade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"tradePair","type":"bytes32"},{"indexed":true,"name":"maker","type":"address"},{"indexed":true,"name":"taker","type":"address"},{"indexed":false,"name":"makerToken","type":"address"},{"indexed":false,"name":"takerToken","type":"address"},{"indexed":false,"name":"restrictedTo","type":"address"},{"indexed":false,"name":"numberData","type":"uint256[4]"},{"indexed":false,"name":"tradeAmount","type":"uint256"},{"indexed":false,"name":"fillOrKill","type":"bool"}],"name":"Trade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"token","type":"address"},{"indexed":true,"name":"toUser","type":"address"},{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"token","type":"address"},{"indexed":true,"name":"toUser","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"token","type":"address"},{"indexed":true,"name":"toUser","type":"address"},{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"InternalTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"token","type":"address"},{"indexed":true,"name":"sweeper","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"balance","type":"uint256"}],"name":"TokenSweep","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"status","type":"bool"}],"name":"RestrictToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newExchange","type":"address"}],"name":"NewExchange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"feeAccount","type":"address"}],"name":"ChangeFeeAccount","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sweepAccount","type":"address"}],"name":"ChangeSweepAccount","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"class","type":"uint256"},{"indexed":false,"name":"fee","type":"uint256"}],"name":"ChangeClassFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":false,"name":"class","type":"uint256"}],"name":"ChangeUserClass","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"status","type":"bool"}],"name":"LockContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newComplianceAddress","type":"address"}],"name":"UpdateComplianceAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newOptionsRegistryAddress","type":"address"}],"name":"UpdateOptionsRegistryAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"token","type":"address"},{"indexed":false,"name":"newExchange","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Upgrade","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"maker","type":"address"},{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"withdrawAmount","type":"uint256"},{"indexed":false,"name":"feeAmount","type":"uint256"},{"indexed":false,"name":"withdrawExpires","type":"uint256"},{"indexed":false,"name":"salt","type":"uint256"},{"indexed":false,"name":"restrictedTo","type":"address"}],"name":"RemoteWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"maker","type":"address"},{"indexed":false,"name":"withdrawAmount","type":"uint256"},{"indexed":false,"name":"feeAmount","type":"uint256"},{"indexed":false,"name":"withdrawExpires","type":"uint256"},{"indexed":false,"name":"salt","type":"uint256"},{"indexed":false,"name":"restrictedTo","type":"address"},{"indexed":false,"name":"status","type":"uint256"}],"name":"CancelRemoteWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"holderTicketAddress","type":"address"},{"indexed":true,"name":"writerTicketAddress","type":"address"},{"indexed":false,"name":"ticketsCollapsed","type":"uint256"},{"indexed":false,"name":"optionPair","type":"bytes32"}],"name":"CollapseOption","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"holderTicketAddress","type":"address"},{"indexed":false,"name":"ticketsUnwound","type":"uint256"},{"indexed":false,"name":"optionPair","type":"bytes32"},{"indexed":false,"name":"fillOrKill","type":"bool"}],"name":"ExcerciseUnwind","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"writerTicketAddress","type":"address"},{"indexed":false,"name":"ticketsExpired","type":"uint256"},{"indexed":false,"name":"optionPair","type":"bytes32"}],"name":"ExpireOption","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"holderTicketAddress","type":"address"},{"indexed":true,"name":"writerTicketAddress","type":"address"},{"indexed":false,"name":"ticketsCreated","type":"uint256"},{"indexed":false,"name":"optionPair","type":"bytes32"}],"name":"CreateOption","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"user","type":"address"},{"indexed":true,"name":"holderTicketAddress","type":"address"},{"indexed":false,"name":"ticketsExcercised","type":"uint256"},{"indexed":false,"name":"optionPair","type":"bytes32"}],"name":"ExcerciseOption","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"optionPair","type":"bytes32"},{"indexed":true,"name":"writerTicketAddress","type":"address"},{"indexed":true,"name":"holderTicketAddress","type":"address"},{"indexed":false,"name":"_assetTokenAddress","type":"address"},{"indexed":false,"name":"_assetTokenAmount","type":"uint256"},{"indexed":false,"name":"_strikeTokenAddress","type":"address"},{"indexed":false,"name":"_strikeTokenAmount","type":"uint256"},{"indexed":false,"name":"_optionExpires","type":"uint256"}],"name":"RegisterOptionsPair","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"helper","type":"address"},{"indexed":false,"name":"status","type":"bool"}],"name":"ChangeHelper","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"}],"name":"OwnershipTransferProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"}],"name":"OwnershipTransferConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_newManager","type":"address"}],"name":"NewManager","type":"event"}]

60606040526040517f6164647265737320636f6e74726163744164647265737300000000000000000081527f616464726573732074616b6572546f6b656e416464726573730000000000000060178201527f75696e743235362074616b6572546f6b656e416d6f756e74000000000000000060308201527f61646472657373206d616b6572546f6b656e416464726573730000000000000060488201527f75696e74323536206d616b6572546f6b656e416d6f756e74000000000000000060618201527f75696e743235362074726164654578706972657300000000000000000000000060798201527f75696e743235362073616c740000000000000000000000000000000000000000608d8201527f61646472657373206d616b65720000000000000000000000000000000000000060998201527f616464726573732072657374726963746564546f00000000000000000000000060a682015260ba016040519081900390206009556040517f6164647265737320636f6e74726163744164647265737300000000000000000081527f75696e7432353620616d6f756e7400000000000000000000000000000000000060178201527f75696e743235362066656500000000000000000000000000000000000000000060258201527f75696e743235362077697468647261774578706972657300000000000000000060308201527f75696e743235362073616c74000000000000000000000000000000000000000060478201527f61646472657373206d616b65720000000000000000000000000000000000000060538201527f616464726573732072657374726963746564546f0000000000000000000000006060820152607401604051908190039020600a55341561028d57600080fd5b60008054600160a060020a03338116600160a060020a0319928316811784556002805484168217905583526003602090815260408420805460ff191660011790558354600480548516918416918217905560058054851690911790559280526010909252660aa87bee5380007f6e0956cda88cad152e89927e53611735b61a5c762d1428573c6931b0a5efcb01556008805460a060020a60ff02191690556006805430909316928216831790556007805490911690911790556159e480620003566000396000f30060606040526004361061031e5763ffffffff60e060020a600035041663014b0732811461032e5780630380fd031461036d578063060f58c31461039c5780630900f010146103cd5780630c3257d0146103ec5780630e9fb0ed14610410578063136cc10a146104445780631651fc0014610463578063193ccc20146104d25780631d5eeb50146104fa5780631fd2e006146105385780632726403a146105515780632d957790146105765780632e1a7d4d146105be578063324cb3cb146105d4578063338b5dea146105e75780633a88594d14610609578063481c6a75146106385780634bf0d3311461064b5780635293f22f1461066a578063539313a414610688578063582945751461069e57806359e026f7146106bd5780635ea98520146106e5578063616ab6eb14610704578063657157e51461073457806365e17c9d146107595780636ca449f31461076c57806371ffcb161461078b5780637be68454146107aa57806382bd4ec5146107bd57806385914201146107f457806386cc5a1d1461080b578063897cceee1461083a578063899c4434146108525780638da5cb5b1461087d578063906e940014610890578063916a5606146108af5780639c3f1e90146108ce5780639e281a98146108e45780639f839d2214610906578063a4c1e9c014610959578063a7cb6edc1461096d578063bd499af314610991578063bfe00daa146109b0578063c0ee0b8a146109cf578063c166ee38146109fe578063c23f001f14610a11578063d0e30db014610a36578063d1023e7214610a3e578063d3bf64b114610a70578063d40c142914610a87578063d4be5c5214610ab9578063d4ee1d9014610b44578063d5d1e77014610b57578063d9d210b814610b6a578063dd5bcd9514610b8e578063df2c789114610bad578063e28deda514610bd8578063ec0da0cd14610bfa578063ec4b48ad14610c29578063ed45cc7214610c48578063f2fde38b14610c7a578063f3f728f114610c99578063f414348214610cf9578063f7213db614610d10578063f7888aec14610d26578063fd28392a14610d4b578063fda7992514610d6a578063fed1d73d14610d7d575b341561032957600080fd5b600080fd5b341561033957600080fd5b610359600160a060020a0360043581169060243581169060443516610daf565b604051901515815260200160405180910390f35b341561037857600080fd5b610380610db8565b604051600160a060020a03909116815260200160405180910390f35b34156103a757600080fd5b6103bb600160a060020a0360043516610dc7565b60405190815260200160405180910390f35b34156103d857600080fd5b6103bb600160a060020a0360043516610def565b34156103f757600080fd5b61040e600160a060020a0360043516602435611080565b005b341561041b57600080fd5b610380600160a060020a03600435811690602435906044351660643560843560a43515156110fb565b341561044f57600080fd5b6103bb600160a060020a0360043516611186565b341561046e57600080fd5b6103bb60046084818060806040519081016040529190828260808082843782019150505050509190806080019060048060200260405190810160405291908282608080828437509395505050823560ff169260208101359250604001359050611198565b34156104dd57600080fd5b610359600160a060020a0360043581169060243516604435611323565b341561050557600080fd5b610359600435602435604435606435600160a060020a0360843581169060a4351660ff60c4351660e435610104356115a1565b341561054357600080fd5b61040e60043560243561197b565b341561055c57600080fd5b610359600160a060020a03600435811690602435166119f3565b341561058157600080fd5b6103bb600435602435604435606435600160a060020a0360843581169060a43581169060ff60c435169060e4359061010435906101243516611a79565b34156105c957600080fd5b6103bb600435611cce565b34156105df57600080fd5b610359611dd6565b34156105f257600080fd5b6103bb600160a060020a0360043516602435611df7565b341561061457600080fd5b610359600160a060020a036004358116906024359060443516606435608435612024565b341561064357600080fd5b61038061205c565b341561065657600080fd5b610359600160a060020a036004351661206b565b341561067557600080fd5b61040e6004803560248101910135612071565b341561069357600080fd5b6103bb60043561210e565b34156106a957600080fd5b61040e600160a060020a0360043516612120565b34156106c857600080fd5b6103bb600160a060020a03600435811690602435166044356121a0565b34156106f057600080fd5b61040e600160a060020a03600435166123a6565b341561070f57600080fd5b6103bb6004608460ff6101043516610124356101443561016435610184351515612426565b341561073f57600080fd5b610359600160a060020a0360043581169060243516612d0b565b341561076457600080fd5b610380612d13565b341561077757600080fd5b6103bb600160a060020a0360043516612d22565b341561079657600080fd5b61040e600160a060020a0360043516612d34565b34156107b557600080fd5b610380612dc9565b34156107c857600080fd5b6103bb600160a060020a03600435811690602435906044351660643560843560a43560c4351515612dd8565b34156107ff57600080fd5b6103596004608461313e565b341561081657600080fd5b610359600160a060020a036004358116906024359060443516606435608435613278565b341561084557600080fd5b61040e600435151561331c565b341561085d57600080fd5b610359600160a060020a03600435811690602435811690604435166133af565b341561088857600080fd5b61038061343e565b341561089b57600080fd5b61040e600160a060020a036004351661344d565b34156108ba57600080fd5b6103bb600160a060020a03600435166134df565b34156108d957600080fd5b6103596004356134f1565b34156108ef57600080fd5b6103bb600160a060020a0360043516602435613506565b341561091157600080fd5b610935600160a060020a036004358116906024359060443516606435608435613739565b604051600160a060020a039283168152911660208201526040908101905180910390f35b610359600160a060020a0360043516613768565b341561097857600080fd5b61040e600160a060020a03600435166024351515613927565b341561099c57600080fd5b61040e600160a060020a03600435166139ad565b34156109bb57600080fd5b610359600160a060020a0360043516613a2d565b34156109da57600080fd5b61040e60048035600160a060020a0316906024803591604435918201910135613a42565b3415610a0957600080fd5b610380613cc0565b3415610a1c57600080fd5b6103bb600160a060020a0360043581169060243516613ccf565b6103bb613cec565b3415610a4957600080fd5b6103bb600160a060020a03600435811690602435906044351660643560843560a435613e73565b3415610a7b57600080fd5b6103bb60046084614102565b3415610a9257600080fd5b6103bb600160a060020a03600435811690602435906044351660643560843560a435614163565b3415610ac457600080fd5b6103bb60046084818060806040519081016040529190828260808082843782019150505050509190806080019060048060200260405190810160405291908282608080828437509395505060ff84351693602081013593506040810135925060608101359150600160a060020a036080820135169060a0013515156144e3565b3415610b4f57600080fd5b6103806147cd565b3415610b6257600080fd5b61040e6147dc565b3415610b7557600080fd5b61040e600160a060020a03600435166024351515614864565b3415610b9957600080fd5b610359600160a060020a03600435166148e6565b3415610bb857600080fd5b61040e600435602435604435606435600160a060020a03608435166148fb565b3415610be357600080fd5b6103bb600160a060020a0360043516602435614a09565b3415610c0557600080fd5b610359600160a060020a036004358116906024359060443516606435608435614bf6565b3415610c3457600080fd5b610359600160a060020a0360043516614d07565b3415610c5357600080fd5b6103bb600160a060020a03600435811690602435906044351660643560843560a435614d82565b3415610c8557600080fd5b61040e600160a060020a0360043516615168565b3415610ca457600080fd5b6103bb6004608481806080604051908101604052919082826080808284378201915050505050919080608001906004806020026040519081016040529190828260808082843750939550615206945050505050565b3415610d0457600080fd5b6103bb600460846152a1565b3415610d1b57600080fd5b6103bb6004356153b4565b3415610d3157600080fd5b6103bb600160a060020a03600435811690602435166153c6565b3415610d5657600080fd5b61040e600160a060020a03600435166153f1565b3415610d7557600080fd5b610380615486565b3415610d8857600080fd5b6103bb600160a060020a03600435811690602435906044351660643560843560a435615495565b60009392505050565b600854600160a060020a031681565b600160a060020a03166000908152601160209081526040808320548352601090915290205490565b600854600090600160a060020a03161515610e0957600080fd5b50600160a060020a038082166000818152600b6020908152604080832033909516835293815283822054928252600c90529190912054610e49908261570b565b600160a060020a038084166000818152600c6020908152604080832095909555600b8152848220339094168252929092529181205515610fa357600854600160a060020a038084169163095ea7b391168360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b1515610ee657600080fd5b6102c65a03f11515610ef757600080fd5b505050604051805190501515610f0c57600080fd5b600854600160a060020a031663193ccc2033848460006040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b1515610f7857600080fd5b6102c65a03f11515610f8957600080fd5b505050604051805190501515610f9e57600080fd5b611023565b600854600160a060020a031663a4c1e9c0823360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390911660048201526024016020604051808303818588803b1515610ffc57600080fd5b6125ee5a03f1151561100d57600080fd5b5050505060405180519050151561102357600080fd5b600854600160a060020a0380841691338216917f94d4dc6dd33e72ca4b4c13e4e446974b3c8c071fe8df2216d9bafd1093148911911684604051600160a060020a03909216825260208201526040908101905180910390a3919050565b600160a060020a03331660009081526003602052604090205460ff1615156001146110a757fe5b600160a060020a038216600081815260116020526040908190208390557fe18eae551c029460fd48b4be09b94874c38beaf07ae601c021bc4f7a4f3813379083905190815260200160405180910390a25050565b6000868686868686604051600160a060020a039687166c0100000000000000000000000090810282526014820196909652939095169093026034830152604882015260688101919091529015157f0100000000000000000000000000000000000000000000000000000000000000026088820152608901604051908190039020979650505050505050565b60116020526000908152604090205481565b6000806111a58787615206565b9050604086015143118061127057506040870151600160a060020a031660016009548360405191825260208201526040908101905180910390208787876040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f1151561124157600080fd5b505060206040510351600160a060020a03161415801561127057506000818152600d602052604090205460ff16155b1561127e5760009150611319565b61129786516000838152600e602052604090205461570b565b91506112f86112ee600b60008a60015b6020020151600160a060020a03168152602081019190915260409081016000908120918b0151600160a060020a031681526020810191909152604001600020548851615720565b602088015161574c565b82101561130457611319565b6113166112ee600b60008a60016112a7565b91505b5095945050505050565b60085460009074010000000000000000000000000000000000000000900460ff161561134e57600080fd5b600160a060020a0383161580159061136e5750600160a060020a03841615155b801561138c575030600160a060020a031684600160a060020a031614155b80156113aa575082600160a060020a031684600160a060020a031614155b80156114265750600654600160a060020a0316634bf0d3318560006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561140a57600080fd5b6102c65a03f1151561141b57600080fd5b505050604051805190505b151561143157600080fd5b600160a060020a038084166000908152600b6020908152604080832093881683529290522054611461908361576d565b600160a060020a038085166000818152600b60209081526040808320948a16835293815283822094909455908152600c9092529020546114a1908361576d565b600160a060020a0384166000818152600c60205260408082209390935590916323b872dd91339130918791516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b151561152057600080fd5b6102c65a03f1151561153157600080fd5b50505060405180519050151561154657600080fd5b33600160a060020a031684600160a060020a031684600160a060020a03167f7cfff908a4b583f36430b25d75964c458d8ede8a99bd61be750e97ee1b2f3a968560405190815260200160405180910390a45060019392505050565b600854600090819074010000000000000000000000000000000000000000900460ff16156115ce57600080fd5b6115d88b8b61576d565b600160a060020a038816600090815260008051602061599983398151915260205260409020541080159061162e5750600160a060020a038616158061162e575033600160a060020a031686600160a060020a0316145b80156116b257508915806116b25750600654600160a060020a0316634bf0d3313360006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561169657600080fd5b6102c65a03f115156116a757600080fd5b505050604051805190505b15156116bd57600080fd5b308b8b8b8b8b8b6040516c01000000000000000000000000600160a060020a039889168102825260148201979097526034810195909552605485019390935260748401919091528416830260948301529092160260a882015260bc016040519081900390206000818152600e60205260409020549091501561173e57600080fd5b86600160a060020a03166001600a548360405191825260208201526040908101905180910390208787876040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156117c757600080fd5b505060206040510351600160a060020a0316146117e357600080fd5b6000818152600e6020908152604080832060019055600160a060020a038a16835260008051602061599983398151915290915290205461182c906118278d8d61576d565b61570b565b600160a060020a0388811660009081526000805160206159998339815191526020526040808220939093553390911681522054611869908b61576d565b33600160a060020a03166000908152600080516020615999833981519152602090815260408220929092558052600c9052600080516020615979833981519152546118b4908c61570b565b60008052600c60205260008051602061597983398151915255600160a060020a033381169088167fb9f14766c06e8038e35b27e1588a575ca3850be279d75ecbc2fe7fa1c6939fc58d8d8d8d8c60405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a3600160a060020a0387168b156108fc028c604051600060405180830381858888f19350505050151561196a57600080fd5b5060019a9950505050505050505050565b60025433600160a060020a0390811691161461199357fe5b662386f26fc100008111156119a757600080fd5b6000828152601060205260409081902082905582907f545c9592f9cd7b727ca726b2735c9d4ae93190390b39316abcf8122074cfbd769083905190815260200160405180910390a25050565b600654600090600160a060020a031663657157e58484846040516020015260405160e060020a63ffffffff8516028152600160a060020a03928316600482015291166024820152604401602060405180830381600087803b1515611a5657600080fd5b6102c65a03f11515611a6757600080fd5b50505060405180519150505b92915050565b600080308c8c8c8c8c8c6040516c01000000000000000000000000600160a060020a039889168102825260148201979097526034810195909552605485019390935260748401919091528416830260948301529092160260a882015260bc0160405190819003902060085490915074010000000000000000000000000000000000000000900460ff1680611b3a5750611b128c8c61576d565b600160a060020a03891660009081526000805160206159998339815191526020526040902054105b80611b6a5750600160a060020a03871615801590611b6a575082600160a060020a031687600160a060020a031614155b80611b8257506000818152600e602052604090205415155b80611c26575087600160a060020a03166001600a548360405191825260208201526040908101905180910390208888886040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f11515611c1157600080fd5b505060206040510351600160a060020a031614155b80611cad575060008b118015611cad5750600654600160a060020a0316634bf0d3318460006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515611c9057600080fd5b6102c65a03f11515611ca157600080fd5b50505060405180519050155b15611cbb5760009150611cbf565b8b91505b509a9950505050505050505050565b33600160a060020a031660009081526000805160206159998339815191526020526040812054611cfe908361570b565b33600160a060020a03166000908152600080516020615999833981519152602090815260408220929092558052600c905260008051602061597983398151915254611d49908361570b565b60008052600c6020526000805160206159798339815191525533600160a060020a031682156108fc0283604051600060405180830381858888f193505050501515611d9357600080fd5b33600160a060020a031660007f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb8460405190815260200160405180910390a35090565b60085474010000000000000000000000000000000000000000900460ff1681565b60085460009074010000000000000000000000000000000000000000900460ff1615611e2257600080fd5b600160a060020a0383161515611e3757600080fd5b600654600160a060020a0316634bf0d3313360006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515611e9057600080fd5b6102c65a03f11515611ea157600080fd5b505050604051805190501515611eb657600080fd5b600160a060020a038084166000908152600b602090815260408083203390941683529290522054611ee7908361576d565b600160a060020a038085166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054611f28908361576d565b600160a060020a0384166000818152600c60205260408082209390935590916323b872dd91339130918791516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b1515611fa757600080fd5b6102c65a03f11515611fb857600080fd5b505050604051805190501515611fcd57600080fd5b33600160a060020a031633600160a060020a031684600160a060020a03167f7cfff908a4b583f36430b25d75964c458d8ede8a99bd61be750e97ee1b2f3a968560405190815260200160405180910390a450919050565b600080612036878787878760006110fb565b600160a060020a03166000908152600f602052604090205460ff16979650505050505050565b600254600160a060020a031681565b50600190565b60005433600160a060020a0390811691161461208957fe5b73d0a6e6c54dbc68db5db3a091b171a77407ff7ccf63f2c298be838360405160e060020a63ffffffff85160281526020600482019081526024820183905290819060440184848082843782019150509350505050600060405180830381600087803b15156120f657600080fd5b6102c65a03f1151561210757600080fd5b5050505050565b60106020526000908152604090205481565b60025433600160a060020a0390811691161461213857fe5b6006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f1efad85c2a61997ec31b9fe4d9dd1d158faca18c97fd28009498b4c9010d371c81604051600160a060020a03909116815260200160405180910390a150565b60085460009074010000000000000000000000000000000000000000900460ff16156121cb57600080fd5b600160a060020a038084166000908152600b60209081526040808320339094168352929052205482901080159061220a5750600160a060020a03841615155b8015612228575030600160a060020a031684600160a060020a031614155b8015612246575082600160a060020a031684600160a060020a031614155b80156122c25750600654600160a060020a0316634bf0d3318560006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b15156122a657600080fd5b6102c65a03f115156122b757600080fd5b505050604051805190505b15156122cd57600080fd5b600160a060020a038084166000908152600b6020908152604080832033909416835292905220546122fe908361570b565b600160a060020a038481166000908152600b602090815260408083203385168452909152808220939093559086168152205461233a908361576d565b600160a060020a038085166000818152600b602090815260408083208a8616808552925291829020949094553390921692917f77178bcf8f3c991d39734824771477a42787fe19b60d5a29c0ec72de167699b39086905190815260200160405180910390a45092915050565b60005433600160a060020a039081169116146123be57fe5b6008805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557fd38790e90ba6b65214ca5b65769c399473d52c0a013ab526c0f74a9392c2df6781604051600160a060020a03909116815260200160405180910390a150565b6008546000908190819074010000000000000000000000000000000000000000900460ff161561245557600080fd5b61249c8a6004608060405190810160405291908282608080828437508e93506004925060809150604090505190810160405291908282608080828437506152069350505050565b6000818152600e60205260409020549092506124ba908a359061570b565b925061255b612551600b60008d60015b6020020135600160a060020a0316600160a060020a0316600160a060020a0316815260200190815260200160002060008d600260048110151561250957fe5b6020020135600160a060020a0316600160a060020a0316600160a060020a03168152602001908152602001600020548b600060048110151561254757fe5b6020020135615720565b60208b013561574c565b83111561257757612574612551600b60008d60016124ca565b92505b84831115612583578492505b821515612659576000828152600e602052604090205489359010156125fb57600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600060405191825260208201526040908101905180910390a3612650565b600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600160405191825260208201526040908101905180910390a35b60009250612cfe565b60408901354311156126c257600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600260405191825260208201526040908101905180910390a360009250612cfe565b60018415151480156126d357508483105b1561273557600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600360405191825260208201526040908101905180910390a360009250612cfe565b600160a060020a03331660009081526011602090815260408083205483526010909152902054670de0b6b3a764000090612770908790615720565b81151561277957fe5b600160a060020a038c3581166000908152600b6020908152604080832033909416835292905220549190049150858201111561280c57600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600460405191825260208201526040908101905180910390a360009250612cfe565b8960026020020135600160a060020a0316600160a060020a031660016009548460405191825260208201526040908101905180910390208a8a8a6040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156128a557600080fd5b505060206040510351600160a060020a0316141580156128d457506000828152600d602052604090205460ff16155b1561293657600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600560405191825260208201526040908101905180910390a360009250612cfe565b600160a060020a0360608b01351615801590612964575060608a0135600160a060020a039081163390911614155b156129c657600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600660405191825260208201526040908101905180910390a360009250612cfe565b600160a060020a038a3516158015906129f85750600160a060020a038a35166000908152600f602052604090205460ff165b8015612a9d5750600654600160a060020a039081169063014b0732908c35168c60026020020135600160a060020a03163360006040516020015260405160e060020a63ffffffff8616028152600160a060020a03938416600482015291831660248301529091166044820152606401602060405180830381600087803b1515612a8057600080fd5b6102c65a03f11515612a9157600080fd5b50505060405180519050155b80612b845750600160a060020a0360208b01351615801590612adc575060208a810135600160a060020a03166000908152600f909152604090205460ff165b8015612b845750600654600160a060020a039081169063014b07329060208d0135168c60026020020135600160a060020a03163360006040516020015260405160e060020a63ffffffff8616028152600160a060020a03938416600482015291831660248301529091166044820152606401602060405180830381600087803b1515612b6757600080fd5b6102c65a03f11515612b7857600080fd5b50505060405180519050155b15612be657600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600760405191825260208201526040908101905180910390a360009250612cfe565b612c2d600160a060020a038b35168a600060209081029190910135908d0135600160a060020a03168c600160200201358e60026020020135600160a060020a03168861577d565b6000828152600e6020526040902054612c46908461576d565b6000838152600e602090815260409182902092909255600160a060020a0333811692918d01358116918d013581168d35909116818118917f9ceeff478781fc81e3097e68bf692d2aa7f685806c3b2a775cd5734ca6884b38918f60036020020135600160a060020a03168f8a8c604051600160a060020a038088168252868116602083015285166040820152606081018460808082843790910193845250501515602082015260409081019450925050505180910390a45b5050979650505050505050565b600092915050565b600454600160a060020a031681565b60126020526000908152604090205481565b60025433600160a060020a03908116911614612d4c57fe5b600160a060020a0381161515612d6157600080fd5b6004805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557fc548e761ed2980401c7f574c8ea8d65df43a8b8d1b043c767358f98a26cecc7a81604051600160a060020a03909116815260200160405180910390a150565b600754600160a060020a031681565b600854600090819074010000000000000000000000000000000000000000900460ff1615612e0557600080fd5b4385901115612e1357600080fd5b612e22898989898960006110fb565b600160a060020a03811660009081526012602052604090205492509050821580612e4c5750838210155b1515612e5757600080fd5b83821115612e63578391505b60008211612e7057600080fd5b600160a060020a0381166000908152600f602052604090205460ff161580612f105750600654600160a060020a031663657157e5823360006040516020015260405160e060020a63ffffffff8516028152600160a060020a03928316600482015291166024820152604401602060405180830381600087803b1515612ef457600080fd5b6102c65a03f11515612f0557600080fd5b505050604051805190505b1515612f1b57600080fd5b600160a060020a03808a166000908152600b602090815260408083203390941683529290522054612f6190611827612f538b86615720565b670de0b6b3a764000061574c565b600160a060020a038a81166000908152600b6020908152604080832033909416835292905281812092909255818052902054612fa990612fa4612f538b86615720565b61576d565b600160a060020a03808b166000908152600b60209081526040808320838052825280832094909455918416815260129091522054612fe7908361570b565b600160a060020a03808316600090815260126020908152604080832094909455600b8152838220339093168252919091522054613024908361576d565b600160a060020a038083166000908152600b602081815260408084203386168552825280842095909555928b1682528252828120818052909152205461307190611827612f538986615720565b600160a060020a038881166000908152600b602090815260408083208380529091528082209390935533909116815220546130b390612fa4612f538986615720565b600160a060020a038089166000818152600b602090815260408083203386168085529252918290209490945584831693927f7c3e473f7cd05f8fa3a978854672e37e141bd0670a99f045282e9f1babad4059928792918f161890889051928352602083019190915215156040808301919091526060909101905180910390a350979650505050505050565b600854600090819074010000000000000000000000000000000000000000900460ff161561316b57600080fd5b33600160a060020a039081166040860135919091161461318e5760009150613271565b6131d5846004608060405190810160405291908282608080828437508893506004925060809150604090505190810160405291908282608080828437506152069350505050565b6000818152600d60205260409020805460ff19166001908117909155909150600160a060020a0333169085906020020135600160a060020a03168560006020020135600160a060020a0316187fa6cf6535207b3f4262e23ded50583eeada16798ac676e36cda6d13189dd1cb3d8686604051808360808082843790910190508260808082843782019150509250505060405180910390a3600191505b5092915050565b600754600090600160a060020a0316633a88594d8787878787876040516020015260405160e060020a63ffffffff8816028152600160a060020a03958616600482015260248101949094529190931660448301526064820192909252608481019190915260a401602060405180830381600087803b15156132f857600080fd5b6102c65a03f1151561330957600080fd5b5050506040518051979650505050505050565b60025433600160a060020a0390811691161461333457fe5b600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000831515021790557fbf09afadf320e6bf6370ede8dd137c27879a895508c8b7745b929ee65cdce42d81604051901515815260200160405180910390a150565b600654600090600160a060020a031663014b0732858585856040516020015260405160e060020a63ffffffff8616028152600160a060020a03938416600482015291831660248301529091166044820152606401602060405180830381600087803b151561341c57600080fd5b6102c65a03f1151561342d57600080fd5b505050604051805195945050505050565b600054600160a060020a031681565b60005433600160a060020a0390811691161461346557fe5b600160a060020a038116151561347a57600080fd5b80600160a060020a03167f5589a1df7a257347b14b97cb6fe06862c960ff64e9a0c2908632929098bb013060405160405180910390a26002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600c6020526000908152604090205481565b600d6020526000908152604090205460ff1681565b6000600160a060020a03831615156135e25733600160a060020a031660009081526000805160206159998339815191526020526040902054613548908361570b565b33600160a060020a03166000908152600080516020615999833981519152602090815260408220929092558052600c905260008051602061597983398151915254613593908361570b565b60008052600c6020526000805160206159798339815191525533600160a060020a031682156108fc0283604051600060405180830381858888f1935050505015156135dd57600080fd5b6136ec565b600160a060020a038084166000908152600b602090815260408083203390941683529290522054613613908361570b565b600160a060020a038085166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054613654908361570b565b600160a060020a0384166000818152600c602052604080822093909355909163a9059cbb913391869190516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b15156136c657600080fd5b6102c65a03f115156136d757600080fd5b5050506040518051905015156136ec57600080fd5b33600160a060020a031683600160a060020a03167f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb8460405190815260200160405180910390a350919050565b60008061374b878787878760006110fb565b915061375c878787878760016110fb565b90509550959350505050565b60085460009074010000000000000000000000000000000000000000900460ff161561379357600080fd5b600160a060020a038216158015906137bd575030600160a060020a031682600160a060020a031614155b80156138395750600654600160a060020a0316634bf0d3318360006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561381d57600080fd5b6102c65a03f1151561382e57600080fd5b505050604051805190505b151561384457600080fd5b600160a060020a03821660009081526000805160206159998339815191526020526040902054613874903461576d565b600160a060020a0383166000908152600080516020615999833981519152602090815260408220929092558052600c9052600080516020615979833981519152546138bf903461576d565b6000808052600c60205260008051602061597983398151915291909155600160a060020a0333811691908416907f7cfff908a4b583f36430b25d75964c458d8ede8a99bd61be750e97ee1b2f3a963460405190815260200160405180910390a4506001919050565b600160a060020a03331660009081526003602052604090205460ff16151560011461394e57fe5b600160a060020a0382166000818152600f602052604090819020805460ff19168415151790557ff4633ca7832e2617e9641765f342dbd191acc7e482b57d5871ebca5bbcc5b7fe90839051901515815260200160405180910390a25050565b60025433600160a060020a039081169116146139c557fe5b6007805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f7a0ee36b0dd624c0e5e79330cd2941e28c0d34311e8ecfd1d9362127f82f0d3381604051600160a060020a03909116815260200160405180910390a150565b60036020526000908152604090205460ff1681565b6008546000908190819074010000000000000000000000000000000000000000900460ff1615613a7157600080fd5b8692506014841415613a865760783591508192505b600160a060020a03831615801590613ab0575030600160a060020a031683600160a060020a031614155b8015613ace575033600160a060020a031683600160a060020a031614155b8015613b4a5750600654600160a060020a0316634bf0d3318460006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515613b2e57600080fd5b6102c65a03f11515613b3f57600080fd5b505050604051805190505b1515613b5557600080fd5b50333b60008111613b6557600080fd5b600160a060020a0333166000908152600c6020526040902054613b88908761576d565b600160a060020a033381166000908152600c6020908152604080832094909455600b81528382209287168252919091522054613bc4908761576d565b600160a060020a033381166000818152600b60209081526040808320948916835293905282812093909355889290916370a08231913091516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515613c3e57600080fd5b6102c65a03f11515613c4f57600080fd5b5050506040518051905010151515613c6657600080fd5b86600160a060020a031683600160a060020a031633600160a060020a03167f7cfff908a4b583f36430b25d75964c458d8ede8a99bd61be750e97ee1b2f3a968960405190815260200160405180910390a450505050505050565b600554600160a060020a031681565b600b60209081526000928352604080842090915290825290205481565b60085460009074010000000000000000000000000000000000000000900460ff1615613d1757600080fd5b600654600160a060020a0316634bf0d3313360006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515613d7057600080fd5b6102c65a03f11515613d8157600080fd5b505050604051805190501515613d9657600080fd5b33600160a060020a031660009081526000805160206159998339815191526020526040902054613dc6903461576d565b33600160a060020a03166000908152600080516020615999833981519152602090815260408220929092558052600c905260008051602061597983398151915254613e11903461576d565b6000808052600c6020526000805160206159798339815191529190915533600160a060020a03169081907f7cfff908a4b583f36430b25d75964c458d8ede8a99bd61be750e97ee1b2f3a963460405190815260200160405180910390a4503490565b6000806000613e87898989898960006110fb565b9150613e98898989898960016110fb565b600160a060020a038084166000908152600b602090815260408083203390941683529290522054909150849010801590613ef95750600160a060020a038082166000908152600b602090815260408083203390941683529290522054849010155b1515613f0457600080fd5b600160a060020a038082166000908152600b602090815260408083203390941683529290522054613f35908561570b565b600160a060020a038083166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054613f76908561570b565b600160a060020a038083166000908152600c60209081526040808320949094558583168252600b8152838220339093168252919091522054613fb8908561570b565b600160a060020a038084166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054613ff9908561570b565b600160a060020a038084166000908152600c6020908152604080832094909455918c168152600b8252828120818052909152205461403e90611827612f538b88615720565b600160a060020a038a81166000908152600b6020908152604080832083805290915280822093909355339091168152205461408090612fa4612f538b88615720565b600160a060020a03808b166000818152600b6020908152604080832033861680855292529182902094909455848316938684169390927fbb5fb196fd6ae6343696c34e402990d3bef7d04acc12ac37166c0fbe554735a5928a928e16909118905191825260208201526040908101905180910390a45091979650505050505050565b60008061414c846004608060405190810160405291908282608080828437508893506004925060809150604090505190810160405291908282608080828437506152069350505050565b6000908152600e6020526040902054949350505050565b6000808080804387901161417657600080fd5b6141858b8b8b8b8b60006110fb565b93506141968b8b8b8b8b60016110fb565b600160a060020a038082166000908152600b60209081526040808320339094168352929052205495509250858510156141ce57600080fd5b858511156141da578594505b600085116141e757600080fd5b600160a060020a038084166000908152600b602090815260408083203390941683529290522054614218908661570b565b600160a060020a038085166000818152600b60209081526040808320339095168352938152838220949094559081526012909252902054614259908661576d565b600160a060020a0384166000908152601260205260409020556142c16142a3614285612f53888c615720565b600160a060020a038716600090815260126020526040902054615720565b600160a060020a0386166000908152600c602052604090205461574c565b915061430a6142a36142d6612f53888e615720565b600160a060020a0387166000908152600c6020908152604080832054601290925290912054614305919061570b565b615720565b600160a060020a038a166000908152600b6020908152604080832083805290915290205490915061433b908361570b565b600160a060020a03808b166000908152600b60208181526040808420848052825280842095909555928f1682528252828120818052909152205461437f908261570b565b600160a060020a03808d166000908152600b602081815260408084208480528252808420959095558d841683529081528382203390931682529190915220546143c8908361576d565b600b60008b600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a0316815260200190815260200160002081905550614466600b60008d600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a03168152602001908152602001600020548261576d565b600160a060020a03808d166000818152600b602090815260408083203386168085529252918290209490945586831693927f832eb3b5b655da0aa0c29e06b47f7360c5deadb5153ea14d1837dd4944fbc4f9928a92918f1618905191825260208201526040908101905180910390a3505050509695505050505050565b600160a060020a0382166000908152601160209081526040808320548352601090915281205481908190670de0b6b3a764000090614522908890615720565b81151561452b57fe5b600854919004925074010000000000000000000000000000000000000000900460ff1680614622575060008b51600160a060020a03161415801561458e5750600f60008c51600160a060020a0316815260208101919091526040016000205460ff165b80156146225750600654600160a060020a031663014b07328c5160408e01518860006040516020015260405160e060020a63ffffffff8616028152600160a060020a03938416600482015291831660248301529091166044820152606401602060405180830381600087803b151561460557600080fd5b6102c65a03f1151561461657600080fd5b50505060405180519050155b806146ff5750600060208c0151600160a060020a0316141580156146685750600f600060208d0151600160a060020a0316815260208101919091526040016000205460ff165b80156146ff5750600654600160a060020a031663014b073260208d015160408e01518860006040516020015260405160e060020a63ffffffff8616028152600160a060020a03938416600482015291831660248301529091166044820152606401602060405180830381600087803b15156146e257600080fd5b6102c65a03f115156146f357600080fd5b50505060405180519050155b8061473a5750600b60008c51600160a060020a0390811682526020808301939093526040918201600090812091891681529252902054868301115b806147745750600060608c0151600160a060020a0316141580156147745750600160a060020a03851660608c0151600160a060020a031614155b1561478257600092506147bf565b61478f8b8b8b8b8b611198565b90508581111561479c5750845b60018415151480156147ad57508581105b156147bb57600092506147bf565b8092505b505098975050505050505050565b600154600160a060020a031681565b60015433600160a060020a039081169116146147f457fe5b600154600054600160a060020a0391821691167f646fe5eeb20d96ea45a9caafcb508854a2fb5660885ced7772e12a633c97457160405160405180910390a36001546000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055565b60025433600160a060020a0390811691161461487c57fe5b81600160a060020a03167feb4b54e166d09942fe049406526365c69945115063ac3b8b0f7c3a0f0495a54482604051901515815260200160405180910390a2600160a060020a03919091166000908152600360205260409020805460ff1916911515919091179055565b600f6020526000908152604090205460ff1681565b6000308686868633876040516c01000000000000000000000000600160a060020a039889168102825260148201979097526034810195909552605485019390935260748401919091528416830260948301529092160260a882015260bc016040518091039020905033600160a060020a03167fe36534d3086ffa6e0e487d9ee3837ef476fad47478ad2035bd2c383cfbfdd0fe8787878787600e600089600019166000191681526020019081526020016000205460405195865260208601949094526040808601939093526060850191909152600160a060020a0316608084015260a083019190915260c0909101905180910390a26000908152600e60205260409020600190555050505050565b60055460009033600160a060020a03908116911614614a2457fe5b600160a060020a038084166000908152600b6020908152604080832060055490941683529290522054614a57908361576d565b600160a060020a038085166000818152600b60209081526040808320600554909516835293815283822094909455908152600c909252902054614a9a908361576d565b600160a060020a0384166000818152600c602052604090209190915515614b565782600160a060020a03166370a082313060006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515614b1257600080fd5b6102c65a03f11515614b2357600080fd5b5050506040518051600160a060020a0385166000908152600c602052604090205411159050614b5157600080fd5b614b86565b60008052600c60205260008051602061597983398151915254600160a060020a03301631901115614b8657600080fd5b600160a060020a038381166000818152600b6020908152604080832060055486168452909152908190205433909316927f468284922c196e792dd8af95d8d884fce7be422d6bd1169b7e05904977a18a33918691905191825260208201526040908101905180910390a350919050565b6000806000614c0a888888888860006110fb565b600160a060020a0381166000908152600f602052604090205490925060ff1615614c375760009250614cfc565b614c46888888888860016110fb565b600160a060020a038381166000818152600f60205260408082208054600160ff1991821681179092558686168085529383902080549091169091179055939450929091898116908c1618907fdc81877cc75ce5b9616eb8266d567de063774b7e5df00a488e9ce280ba6209a8908c908c908c908c908c9051600160a060020a0395861681526020810194909452919093166040808401919091526060830193909352608082015260a001905180910390a4600192505b505095945050505050565b600654600090600160a060020a0316634bf0d33183836040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515614d6257600080fd5b6102c65a03f11515614d7357600080fd5b50505060405180519392505050565b6008546000908190819074010000000000000000000000000000000000000000900460ff1615614db157600080fd5b43859010614dbe57600080fd5b600160a060020a0389166000908152600b60209081526040808320838052909152902054614df390612fa4612f538b88615720565b600160a060020a038a81166000908152600b60209081526040808320838052909152808220939093553390911681522054614e3590611827612f538b88615720565b600160a060020a03808b166000908152600b6020908152604080832033909416835292905290812091909155614e74908a908a908a908a908a906110fb565b9150614e85898989898960016110fb565b600160a060020a038082166000908152600b602090815260408083203390941683529290522054909150614eb9908561576d565b600160a060020a038083166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054614efa908561576d565b600160a060020a038083166000908152600c60209081526040808320949094558583168252600b8152838220339093168252919091522054614f3c908561576d565b600160a060020a038084166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054614f7d908561576d565b600c600084600160a060020a0316600160a060020a031681526020019081526020016000208190555080600160a060020a031682600160a060020a031633600160a060020a03167fb42c6b1349c88a10208a87a5be744f0a7962f8d91c71841d32dfbca7b7066be4878b600160a060020a03166001028e600160a060020a03166001021860405191825260208201526040908101905180910390a4600754600160a060020a0316633a88594d8a8a8a8a8a60006040516020015260405160e060020a63ffffffff8816028152600160a060020a03958616600482015260248101949094529190931660448301526064820192909252608481019190915260a401602060405180830381600087803b151561509657600080fd5b6102c65a03f115156150a757600080fd5b50505060405180511515905061515b57600754600160a060020a031663ec0da0cd8a8a8a8a8a60006040516020015260405160e060020a63ffffffff8816028152600160a060020a03958616600482015260248101949094529190931660448301526064820192909252608481019190915260a401602060405180830381600087803b151561513557600080fd5b6102c65a03f1151561514657600080fd5b50505060405180519050151561515b57600080fd5b5091979650505050505050565b60005433600160a060020a0390811691161461518057fe5b600054600160a060020a038281169116141561519b57600080fd5b600054600160a060020a0380831691167ff4e75b79500ab730f8a026ed3cba6d55331bcb64c9e9f60c548e371356e5e3c060405160405180910390a36001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60003083518351602086015160208601516040870151606088015160408a015160608b01516040516c01000000000000000000000000600160a060020a039a8b1681028252988a1689026014820152602881019790975294881687026048870152605c860193909352607c850191909152609c8401528416830260bc8301529092160260d082015260e4016040518091039020905092915050565b60008033600160a060020a03908116604086013591909116146152c357600080fd5b61530a846004608060405190810160405291908282608080828437508893506004925060809150604090505190810160405291908282608080828437506152069350505050565b6000818152600e60205260409020549091506153289084359061570b565b6000828152600e602090815260409182902086359055919350600160a060020a03338116928701358116873590911618907f0f1206423b754face2dd8203a94256739c90ead9d2248998206fcdc5b0c627829087908790879051808460808082843790910190508360808082843790910192835250506020019150604090505180910390a35092915050565b600e6020526000908152604090205481565b600160a060020a039182166000908152600b6020908152604080832093909416825291909152205490565b60025433600160a060020a0390811691161461540957fe5b600160a060020a038116151561541e57600080fd5b6005805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f7ddc968f5ff0f568096d761b25819097ee9902bd80a2cc5c525b8a6e64df946281604051600160a060020a03909116815260200160405180910390a150565b600654600160a060020a031681565b60008043849011156154a657600080fd5b6154b5888888888860006110fb565b600160a060020a038082166000908152600b60209081526040808320339094168352929052205492509050828210156154ed57600080fd5b828211156154f9578291505b6000821161550657600080fd5b600160a060020a038082166000908152600b602090815260408083203390941683529290522054615537908361570b565b600160a060020a038083166000818152600b60209081526040808320339095168352938152838220949094559081526012909252902054615578908361576d565b600160a060020a038083166000908152601260209081526040808320949094558983168252600b81528382203390931682529190915220546155c190611827612f538886615720565b600160a060020a038781166000908152600b602090815260408083203390941683529290528181209290925581805290205461560490612fa4612f538886615720565b600160a060020a038088166000908152600b60208181526040808420848052825280842095909555928c1682528252828120818052909152205461564f90611827612f538a86615720565b600160a060020a038981166000908152600b6020908152604080832083805290915280822093909355339091168152205461569190612fa4612f538a86615720565b600160a060020a03808a166000818152600b602090815260408083203386168085529252918290209490945584831693927f57f69113272de4dd9c983a929da28280f81d87417b489e4f34ca8cfef37c7838928792918c1618905191825260208201526040908101905180910390a3509695505050505050565b60008282111561571a57600080fd5b50900390565b600082151561573157506000611a73565b5081810281838281151561574157fe5b0414611a7357600080fd5b600080821161575a57600080fd5b818381151561576557fe5b049392505050565b81810182811015611a7357600080fd5b600080861161578b57600080fd5b600160a060020a03331660009081526011602090815260408083205483526010909152902054670de0b6b3a7640000906157c6908490615720565b8115156157cf57fe5b600160a060020a03808a166000908152600b60209081526040808320938916835292905220549190049150615804908361576d565b600160a060020a038881166000908152600b60209081526040808320888516845290915280822093909355339091168152205461584590611827848461576d565b600160a060020a038089166000908152600b602081815260408084203386168552825280842095909555898416835290815283822092871682529190915220546158a390876158948786615720565b81151561589d57fe5b0461570b565b600160a060020a038681166000908152600b6020908152604080832088851684529091528082209390935533909116815220546158f490876158e58786615720565b8115156158ee57fe5b0461576d565b600160a060020a038087166000908152600b6020818152604080842033861685528252808420959095558b841683529081528382206004549093168252919091522054615941908261576d565b600160a060020a039788166000908152600b60209081526040808320600454909b1683529990529790972096909655505050505050560013649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8df7de25b7f1fd6d0b5205f0e18f1f35bd7b8d84cce336588d184533ce43a6f76a165627a7a72305820317153de19af478b43d81e97e1c28efe4b98fc942063e2b31a630fa1d22bb9480029

Deployed Bytecode

0x60606040526004361061031e5763ffffffff60e060020a600035041663014b0732811461032e5780630380fd031461036d578063060f58c31461039c5780630900f010146103cd5780630c3257d0146103ec5780630e9fb0ed14610410578063136cc10a146104445780631651fc0014610463578063193ccc20146104d25780631d5eeb50146104fa5780631fd2e006146105385780632726403a146105515780632d957790146105765780632e1a7d4d146105be578063324cb3cb146105d4578063338b5dea146105e75780633a88594d14610609578063481c6a75146106385780634bf0d3311461064b5780635293f22f1461066a578063539313a414610688578063582945751461069e57806359e026f7146106bd5780635ea98520146106e5578063616ab6eb14610704578063657157e51461073457806365e17c9d146107595780636ca449f31461076c57806371ffcb161461078b5780637be68454146107aa57806382bd4ec5146107bd57806385914201146107f457806386cc5a1d1461080b578063897cceee1461083a578063899c4434146108525780638da5cb5b1461087d578063906e940014610890578063916a5606146108af5780639c3f1e90146108ce5780639e281a98146108e45780639f839d2214610906578063a4c1e9c014610959578063a7cb6edc1461096d578063bd499af314610991578063bfe00daa146109b0578063c0ee0b8a146109cf578063c166ee38146109fe578063c23f001f14610a11578063d0e30db014610a36578063d1023e7214610a3e578063d3bf64b114610a70578063d40c142914610a87578063d4be5c5214610ab9578063d4ee1d9014610b44578063d5d1e77014610b57578063d9d210b814610b6a578063dd5bcd9514610b8e578063df2c789114610bad578063e28deda514610bd8578063ec0da0cd14610bfa578063ec4b48ad14610c29578063ed45cc7214610c48578063f2fde38b14610c7a578063f3f728f114610c99578063f414348214610cf9578063f7213db614610d10578063f7888aec14610d26578063fd28392a14610d4b578063fda7992514610d6a578063fed1d73d14610d7d575b341561032957600080fd5b600080fd5b341561033957600080fd5b610359600160a060020a0360043581169060243581169060443516610daf565b604051901515815260200160405180910390f35b341561037857600080fd5b610380610db8565b604051600160a060020a03909116815260200160405180910390f35b34156103a757600080fd5b6103bb600160a060020a0360043516610dc7565b60405190815260200160405180910390f35b34156103d857600080fd5b6103bb600160a060020a0360043516610def565b34156103f757600080fd5b61040e600160a060020a0360043516602435611080565b005b341561041b57600080fd5b610380600160a060020a03600435811690602435906044351660643560843560a43515156110fb565b341561044f57600080fd5b6103bb600160a060020a0360043516611186565b341561046e57600080fd5b6103bb60046084818060806040519081016040529190828260808082843782019150505050509190806080019060048060200260405190810160405291908282608080828437509395505050823560ff169260208101359250604001359050611198565b34156104dd57600080fd5b610359600160a060020a0360043581169060243516604435611323565b341561050557600080fd5b610359600435602435604435606435600160a060020a0360843581169060a4351660ff60c4351660e435610104356115a1565b341561054357600080fd5b61040e60043560243561197b565b341561055c57600080fd5b610359600160a060020a03600435811690602435166119f3565b341561058157600080fd5b6103bb600435602435604435606435600160a060020a0360843581169060a43581169060ff60c435169060e4359061010435906101243516611a79565b34156105c957600080fd5b6103bb600435611cce565b34156105df57600080fd5b610359611dd6565b34156105f257600080fd5b6103bb600160a060020a0360043516602435611df7565b341561061457600080fd5b610359600160a060020a036004358116906024359060443516606435608435612024565b341561064357600080fd5b61038061205c565b341561065657600080fd5b610359600160a060020a036004351661206b565b341561067557600080fd5b61040e6004803560248101910135612071565b341561069357600080fd5b6103bb60043561210e565b34156106a957600080fd5b61040e600160a060020a0360043516612120565b34156106c857600080fd5b6103bb600160a060020a03600435811690602435166044356121a0565b34156106f057600080fd5b61040e600160a060020a03600435166123a6565b341561070f57600080fd5b6103bb6004608460ff6101043516610124356101443561016435610184351515612426565b341561073f57600080fd5b610359600160a060020a0360043581169060243516612d0b565b341561076457600080fd5b610380612d13565b341561077757600080fd5b6103bb600160a060020a0360043516612d22565b341561079657600080fd5b61040e600160a060020a0360043516612d34565b34156107b557600080fd5b610380612dc9565b34156107c857600080fd5b6103bb600160a060020a03600435811690602435906044351660643560843560a43560c4351515612dd8565b34156107ff57600080fd5b6103596004608461313e565b341561081657600080fd5b610359600160a060020a036004358116906024359060443516606435608435613278565b341561084557600080fd5b61040e600435151561331c565b341561085d57600080fd5b610359600160a060020a03600435811690602435811690604435166133af565b341561088857600080fd5b61038061343e565b341561089b57600080fd5b61040e600160a060020a036004351661344d565b34156108ba57600080fd5b6103bb600160a060020a03600435166134df565b34156108d957600080fd5b6103596004356134f1565b34156108ef57600080fd5b6103bb600160a060020a0360043516602435613506565b341561091157600080fd5b610935600160a060020a036004358116906024359060443516606435608435613739565b604051600160a060020a039283168152911660208201526040908101905180910390f35b610359600160a060020a0360043516613768565b341561097857600080fd5b61040e600160a060020a03600435166024351515613927565b341561099c57600080fd5b61040e600160a060020a03600435166139ad565b34156109bb57600080fd5b610359600160a060020a0360043516613a2d565b34156109da57600080fd5b61040e60048035600160a060020a0316906024803591604435918201910135613a42565b3415610a0957600080fd5b610380613cc0565b3415610a1c57600080fd5b6103bb600160a060020a0360043581169060243516613ccf565b6103bb613cec565b3415610a4957600080fd5b6103bb600160a060020a03600435811690602435906044351660643560843560a435613e73565b3415610a7b57600080fd5b6103bb60046084614102565b3415610a9257600080fd5b6103bb600160a060020a03600435811690602435906044351660643560843560a435614163565b3415610ac457600080fd5b6103bb60046084818060806040519081016040529190828260808082843782019150505050509190806080019060048060200260405190810160405291908282608080828437509395505060ff84351693602081013593506040810135925060608101359150600160a060020a036080820135169060a0013515156144e3565b3415610b4f57600080fd5b6103806147cd565b3415610b6257600080fd5b61040e6147dc565b3415610b7557600080fd5b61040e600160a060020a03600435166024351515614864565b3415610b9957600080fd5b610359600160a060020a03600435166148e6565b3415610bb857600080fd5b61040e600435602435604435606435600160a060020a03608435166148fb565b3415610be357600080fd5b6103bb600160a060020a0360043516602435614a09565b3415610c0557600080fd5b610359600160a060020a036004358116906024359060443516606435608435614bf6565b3415610c3457600080fd5b610359600160a060020a0360043516614d07565b3415610c5357600080fd5b6103bb600160a060020a03600435811690602435906044351660643560843560a435614d82565b3415610c8557600080fd5b61040e600160a060020a0360043516615168565b3415610ca457600080fd5b6103bb6004608481806080604051908101604052919082826080808284378201915050505050919080608001906004806020026040519081016040529190828260808082843750939550615206945050505050565b3415610d0457600080fd5b6103bb600460846152a1565b3415610d1b57600080fd5b6103bb6004356153b4565b3415610d3157600080fd5b6103bb600160a060020a03600435811690602435166153c6565b3415610d5657600080fd5b61040e600160a060020a03600435166153f1565b3415610d7557600080fd5b610380615486565b3415610d8857600080fd5b6103bb600160a060020a03600435811690602435906044351660643560843560a435615495565b60009392505050565b600854600160a060020a031681565b600160a060020a03166000908152601160209081526040808320548352601090915290205490565b600854600090600160a060020a03161515610e0957600080fd5b50600160a060020a038082166000818152600b6020908152604080832033909516835293815283822054928252600c90529190912054610e49908261570b565b600160a060020a038084166000818152600c6020908152604080832095909555600b8152848220339094168252929092529181205515610fa357600854600160a060020a038084169163095ea7b391168360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b1515610ee657600080fd5b6102c65a03f11515610ef757600080fd5b505050604051805190501515610f0c57600080fd5b600854600160a060020a031663193ccc2033848460006040516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b1515610f7857600080fd5b6102c65a03f11515610f8957600080fd5b505050604051805190501515610f9e57600080fd5b611023565b600854600160a060020a031663a4c1e9c0823360006040516020015260405160e060020a63ffffffff8516028152600160a060020a0390911660048201526024016020604051808303818588803b1515610ffc57600080fd5b6125ee5a03f1151561100d57600080fd5b5050505060405180519050151561102357600080fd5b600854600160a060020a0380841691338216917f94d4dc6dd33e72ca4b4c13e4e446974b3c8c071fe8df2216d9bafd1093148911911684604051600160a060020a03909216825260208201526040908101905180910390a3919050565b600160a060020a03331660009081526003602052604090205460ff1615156001146110a757fe5b600160a060020a038216600081815260116020526040908190208390557fe18eae551c029460fd48b4be09b94874c38beaf07ae601c021bc4f7a4f3813379083905190815260200160405180910390a25050565b6000868686868686604051600160a060020a039687166c0100000000000000000000000090810282526014820196909652939095169093026034830152604882015260688101919091529015157f0100000000000000000000000000000000000000000000000000000000000000026088820152608901604051908190039020979650505050505050565b60116020526000908152604090205481565b6000806111a58787615206565b9050604086015143118061127057506040870151600160a060020a031660016009548360405191825260208201526040908101905180910390208787876040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f1151561124157600080fd5b505060206040510351600160a060020a03161415801561127057506000818152600d602052604090205460ff16155b1561127e5760009150611319565b61129786516000838152600e602052604090205461570b565b91506112f86112ee600b60008a60015b6020020151600160a060020a03168152602081019190915260409081016000908120918b0151600160a060020a031681526020810191909152604001600020548851615720565b602088015161574c565b82101561130457611319565b6113166112ee600b60008a60016112a7565b91505b5095945050505050565b60085460009074010000000000000000000000000000000000000000900460ff161561134e57600080fd5b600160a060020a0383161580159061136e5750600160a060020a03841615155b801561138c575030600160a060020a031684600160a060020a031614155b80156113aa575082600160a060020a031684600160a060020a031614155b80156114265750600654600160a060020a0316634bf0d3318560006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561140a57600080fd5b6102c65a03f1151561141b57600080fd5b505050604051805190505b151561143157600080fd5b600160a060020a038084166000908152600b6020908152604080832093881683529290522054611461908361576d565b600160a060020a038085166000818152600b60209081526040808320948a16835293815283822094909455908152600c9092529020546114a1908361576d565b600160a060020a0384166000818152600c60205260408082209390935590916323b872dd91339130918791516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b151561152057600080fd5b6102c65a03f1151561153157600080fd5b50505060405180519050151561154657600080fd5b33600160a060020a031684600160a060020a031684600160a060020a03167f7cfff908a4b583f36430b25d75964c458d8ede8a99bd61be750e97ee1b2f3a968560405190815260200160405180910390a45060019392505050565b600854600090819074010000000000000000000000000000000000000000900460ff16156115ce57600080fd5b6115d88b8b61576d565b600160a060020a038816600090815260008051602061599983398151915260205260409020541080159061162e5750600160a060020a038616158061162e575033600160a060020a031686600160a060020a0316145b80156116b257508915806116b25750600654600160a060020a0316634bf0d3313360006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561169657600080fd5b6102c65a03f115156116a757600080fd5b505050604051805190505b15156116bd57600080fd5b308b8b8b8b8b8b6040516c01000000000000000000000000600160a060020a039889168102825260148201979097526034810195909552605485019390935260748401919091528416830260948301529092160260a882015260bc016040519081900390206000818152600e60205260409020549091501561173e57600080fd5b86600160a060020a03166001600a548360405191825260208201526040908101905180910390208787876040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156117c757600080fd5b505060206040510351600160a060020a0316146117e357600080fd5b6000818152600e6020908152604080832060019055600160a060020a038a16835260008051602061599983398151915290915290205461182c906118278d8d61576d565b61570b565b600160a060020a0388811660009081526000805160206159998339815191526020526040808220939093553390911681522054611869908b61576d565b33600160a060020a03166000908152600080516020615999833981519152602090815260408220929092558052600c9052600080516020615979833981519152546118b4908c61570b565b60008052600c60205260008051602061597983398151915255600160a060020a033381169088167fb9f14766c06e8038e35b27e1588a575ca3850be279d75ecbc2fe7fa1c6939fc58d8d8d8d8c60405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a3600160a060020a0387168b156108fc028c604051600060405180830381858888f19350505050151561196a57600080fd5b5060019a9950505050505050505050565b60025433600160a060020a0390811691161461199357fe5b662386f26fc100008111156119a757600080fd5b6000828152601060205260409081902082905582907f545c9592f9cd7b727ca726b2735c9d4ae93190390b39316abcf8122074cfbd769083905190815260200160405180910390a25050565b600654600090600160a060020a031663657157e58484846040516020015260405160e060020a63ffffffff8516028152600160a060020a03928316600482015291166024820152604401602060405180830381600087803b1515611a5657600080fd5b6102c65a03f11515611a6757600080fd5b50505060405180519150505b92915050565b600080308c8c8c8c8c8c6040516c01000000000000000000000000600160a060020a039889168102825260148201979097526034810195909552605485019390935260748401919091528416830260948301529092160260a882015260bc0160405190819003902060085490915074010000000000000000000000000000000000000000900460ff1680611b3a5750611b128c8c61576d565b600160a060020a03891660009081526000805160206159998339815191526020526040902054105b80611b6a5750600160a060020a03871615801590611b6a575082600160a060020a031687600160a060020a031614155b80611b8257506000818152600e602052604090205415155b80611c26575087600160a060020a03166001600a548360405191825260208201526040908101905180910390208888886040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f11515611c1157600080fd5b505060206040510351600160a060020a031614155b80611cad575060008b118015611cad5750600654600160a060020a0316634bf0d3318460006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515611c9057600080fd5b6102c65a03f11515611ca157600080fd5b50505060405180519050155b15611cbb5760009150611cbf565b8b91505b509a9950505050505050505050565b33600160a060020a031660009081526000805160206159998339815191526020526040812054611cfe908361570b565b33600160a060020a03166000908152600080516020615999833981519152602090815260408220929092558052600c905260008051602061597983398151915254611d49908361570b565b60008052600c6020526000805160206159798339815191525533600160a060020a031682156108fc0283604051600060405180830381858888f193505050501515611d9357600080fd5b33600160a060020a031660007f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb8460405190815260200160405180910390a35090565b60085474010000000000000000000000000000000000000000900460ff1681565b60085460009074010000000000000000000000000000000000000000900460ff1615611e2257600080fd5b600160a060020a0383161515611e3757600080fd5b600654600160a060020a0316634bf0d3313360006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515611e9057600080fd5b6102c65a03f11515611ea157600080fd5b505050604051805190501515611eb657600080fd5b600160a060020a038084166000908152600b602090815260408083203390941683529290522054611ee7908361576d565b600160a060020a038085166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054611f28908361576d565b600160a060020a0384166000818152600c60205260408082209390935590916323b872dd91339130918791516020015260405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401602060405180830381600087803b1515611fa757600080fd5b6102c65a03f11515611fb857600080fd5b505050604051805190501515611fcd57600080fd5b33600160a060020a031633600160a060020a031684600160a060020a03167f7cfff908a4b583f36430b25d75964c458d8ede8a99bd61be750e97ee1b2f3a968560405190815260200160405180910390a450919050565b600080612036878787878760006110fb565b600160a060020a03166000908152600f602052604090205460ff16979650505050505050565b600254600160a060020a031681565b50600190565b60005433600160a060020a0390811691161461208957fe5b73d0a6e6c54dbc68db5db3a091b171a77407ff7ccf63f2c298be838360405160e060020a63ffffffff85160281526020600482019081526024820183905290819060440184848082843782019150509350505050600060405180830381600087803b15156120f657600080fd5b6102c65a03f1151561210757600080fd5b5050505050565b60106020526000908152604090205481565b60025433600160a060020a0390811691161461213857fe5b6006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f1efad85c2a61997ec31b9fe4d9dd1d158faca18c97fd28009498b4c9010d371c81604051600160a060020a03909116815260200160405180910390a150565b60085460009074010000000000000000000000000000000000000000900460ff16156121cb57600080fd5b600160a060020a038084166000908152600b60209081526040808320339094168352929052205482901080159061220a5750600160a060020a03841615155b8015612228575030600160a060020a031684600160a060020a031614155b8015612246575082600160a060020a031684600160a060020a031614155b80156122c25750600654600160a060020a0316634bf0d3318560006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b15156122a657600080fd5b6102c65a03f115156122b757600080fd5b505050604051805190505b15156122cd57600080fd5b600160a060020a038084166000908152600b6020908152604080832033909416835292905220546122fe908361570b565b600160a060020a038481166000908152600b602090815260408083203385168452909152808220939093559086168152205461233a908361576d565b600160a060020a038085166000818152600b602090815260408083208a8616808552925291829020949094553390921692917f77178bcf8f3c991d39734824771477a42787fe19b60d5a29c0ec72de167699b39086905190815260200160405180910390a45092915050565b60005433600160a060020a039081169116146123be57fe5b6008805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557fd38790e90ba6b65214ca5b65769c399473d52c0a013ab526c0f74a9392c2df6781604051600160a060020a03909116815260200160405180910390a150565b6008546000908190819074010000000000000000000000000000000000000000900460ff161561245557600080fd5b61249c8a6004608060405190810160405291908282608080828437508e93506004925060809150604090505190810160405291908282608080828437506152069350505050565b6000818152600e60205260409020549092506124ba908a359061570b565b925061255b612551600b60008d60015b6020020135600160a060020a0316600160a060020a0316600160a060020a0316815260200190815260200160002060008d600260048110151561250957fe5b6020020135600160a060020a0316600160a060020a0316600160a060020a03168152602001908152602001600020548b600060048110151561254757fe5b6020020135615720565b60208b013561574c565b83111561257757612574612551600b60008d60016124ca565b92505b84831115612583578492505b821515612659576000828152600e602052604090205489359010156125fb57600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600060405191825260208201526040908101905180910390a3612650565b600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600160405191825260208201526040908101905180910390a35b60009250612cfe565b60408901354311156126c257600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600260405191825260208201526040908101905180910390a360009250612cfe565b60018415151480156126d357508483105b1561273557600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600360405191825260208201526040908101905180910390a360009250612cfe565b600160a060020a03331660009081526011602090815260408083205483526010909152902054670de0b6b3a764000090612770908790615720565b81151561277957fe5b600160a060020a038c3581166000908152600b6020908152604080832033909416835292905220549190049150858201111561280c57600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600460405191825260208201526040908101905180910390a360009250612cfe565b8960026020020135600160a060020a0316600160a060020a031660016009548460405191825260208201526040908101905180910390208a8a8a6040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156128a557600080fd5b505060206040510351600160a060020a0316141580156128d457506000828152600d602052604090205460ff16155b1561293657600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600560405191825260208201526040908101905180910390a360009250612cfe565b600160a060020a0360608b01351615801590612964575060608a0135600160a060020a039081163390911614155b156129c657600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600660405191825260208201526040908101905180910390a360009250612cfe565b600160a060020a038a3516158015906129f85750600160a060020a038a35166000908152600f602052604090205460ff165b8015612a9d5750600654600160a060020a039081169063014b0732908c35168c60026020020135600160a060020a03163360006040516020015260405160e060020a63ffffffff8616028152600160a060020a03938416600482015291831660248301529091166044820152606401602060405180830381600087803b1515612a8057600080fd5b6102c65a03f11515612a9157600080fd5b50505060405180519050155b80612b845750600160a060020a0360208b01351615801590612adc575060208a810135600160a060020a03166000908152600f909152604090205460ff165b8015612b845750600654600160a060020a039081169063014b07329060208d0135168c60026020020135600160a060020a03163360006040516020015260405160e060020a63ffffffff8616028152600160a060020a03938416600482015291831660248301529091166044820152606401602060405180830381600087803b1515612b6757600080fd5b6102c65a03f11515612b7857600080fd5b50505060405180519050155b15612be657600160a060020a033381169060208c013581168c35909116187fffb8a29f31e482433dc873bac0a4d7a6c9b6a47ccc3aeca1c4b6052ce8d68bca84600760405191825260208201526040908101905180910390a360009250612cfe565b612c2d600160a060020a038b35168a600060209081029190910135908d0135600160a060020a03168c600160200201358e60026020020135600160a060020a03168861577d565b6000828152600e6020526040902054612c46908461576d565b6000838152600e602090815260409182902092909255600160a060020a0333811692918d01358116918d013581168d35909116818118917f9ceeff478781fc81e3097e68bf692d2aa7f685806c3b2a775cd5734ca6884b38918f60036020020135600160a060020a03168f8a8c604051600160a060020a038088168252868116602083015285166040820152606081018460808082843790910193845250501515602082015260409081019450925050505180910390a45b5050979650505050505050565b600092915050565b600454600160a060020a031681565b60126020526000908152604090205481565b60025433600160a060020a03908116911614612d4c57fe5b600160a060020a0381161515612d6157600080fd5b6004805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557fc548e761ed2980401c7f574c8ea8d65df43a8b8d1b043c767358f98a26cecc7a81604051600160a060020a03909116815260200160405180910390a150565b600754600160a060020a031681565b600854600090819074010000000000000000000000000000000000000000900460ff1615612e0557600080fd5b4385901115612e1357600080fd5b612e22898989898960006110fb565b600160a060020a03811660009081526012602052604090205492509050821580612e4c5750838210155b1515612e5757600080fd5b83821115612e63578391505b60008211612e7057600080fd5b600160a060020a0381166000908152600f602052604090205460ff161580612f105750600654600160a060020a031663657157e5823360006040516020015260405160e060020a63ffffffff8516028152600160a060020a03928316600482015291166024820152604401602060405180830381600087803b1515612ef457600080fd5b6102c65a03f11515612f0557600080fd5b505050604051805190505b1515612f1b57600080fd5b600160a060020a03808a166000908152600b602090815260408083203390941683529290522054612f6190611827612f538b86615720565b670de0b6b3a764000061574c565b600160a060020a038a81166000908152600b6020908152604080832033909416835292905281812092909255818052902054612fa990612fa4612f538b86615720565b61576d565b600160a060020a03808b166000908152600b60209081526040808320838052825280832094909455918416815260129091522054612fe7908361570b565b600160a060020a03808316600090815260126020908152604080832094909455600b8152838220339093168252919091522054613024908361576d565b600160a060020a038083166000908152600b602081815260408084203386168552825280842095909555928b1682528252828120818052909152205461307190611827612f538986615720565b600160a060020a038881166000908152600b602090815260408083208380529091528082209390935533909116815220546130b390612fa4612f538986615720565b600160a060020a038089166000818152600b602090815260408083203386168085529252918290209490945584831693927f7c3e473f7cd05f8fa3a978854672e37e141bd0670a99f045282e9f1babad4059928792918f161890889051928352602083019190915215156040808301919091526060909101905180910390a350979650505050505050565b600854600090819074010000000000000000000000000000000000000000900460ff161561316b57600080fd5b33600160a060020a039081166040860135919091161461318e5760009150613271565b6131d5846004608060405190810160405291908282608080828437508893506004925060809150604090505190810160405291908282608080828437506152069350505050565b6000818152600d60205260409020805460ff19166001908117909155909150600160a060020a0333169085906020020135600160a060020a03168560006020020135600160a060020a0316187fa6cf6535207b3f4262e23ded50583eeada16798ac676e36cda6d13189dd1cb3d8686604051808360808082843790910190508260808082843782019150509250505060405180910390a3600191505b5092915050565b600754600090600160a060020a0316633a88594d8787878787876040516020015260405160e060020a63ffffffff8816028152600160a060020a03958616600482015260248101949094529190931660448301526064820192909252608481019190915260a401602060405180830381600087803b15156132f857600080fd5b6102c65a03f1151561330957600080fd5b5050506040518051979650505050505050565b60025433600160a060020a0390811691161461333457fe5b600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000831515021790557fbf09afadf320e6bf6370ede8dd137c27879a895508c8b7745b929ee65cdce42d81604051901515815260200160405180910390a150565b600654600090600160a060020a031663014b0732858585856040516020015260405160e060020a63ffffffff8616028152600160a060020a03938416600482015291831660248301529091166044820152606401602060405180830381600087803b151561341c57600080fd5b6102c65a03f1151561342d57600080fd5b505050604051805195945050505050565b600054600160a060020a031681565b60005433600160a060020a0390811691161461346557fe5b600160a060020a038116151561347a57600080fd5b80600160a060020a03167f5589a1df7a257347b14b97cb6fe06862c960ff64e9a0c2908632929098bb013060405160405180910390a26002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600c6020526000908152604090205481565b600d6020526000908152604090205460ff1681565b6000600160a060020a03831615156135e25733600160a060020a031660009081526000805160206159998339815191526020526040902054613548908361570b565b33600160a060020a03166000908152600080516020615999833981519152602090815260408220929092558052600c905260008051602061597983398151915254613593908361570b565b60008052600c6020526000805160206159798339815191525533600160a060020a031682156108fc0283604051600060405180830381858888f1935050505015156135dd57600080fd5b6136ec565b600160a060020a038084166000908152600b602090815260408083203390941683529290522054613613908361570b565b600160a060020a038085166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054613654908361570b565b600160a060020a0384166000818152600c602052604080822093909355909163a9059cbb913391869190516020015260405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401602060405180830381600087803b15156136c657600080fd5b6102c65a03f115156136d757600080fd5b5050506040518051905015156136ec57600080fd5b33600160a060020a031683600160a060020a03167f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb8460405190815260200160405180910390a350919050565b60008061374b878787878760006110fb565b915061375c878787878760016110fb565b90509550959350505050565b60085460009074010000000000000000000000000000000000000000900460ff161561379357600080fd5b600160a060020a038216158015906137bd575030600160a060020a031682600160a060020a031614155b80156138395750600654600160a060020a0316634bf0d3318360006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561381d57600080fd5b6102c65a03f1151561382e57600080fd5b505050604051805190505b151561384457600080fd5b600160a060020a03821660009081526000805160206159998339815191526020526040902054613874903461576d565b600160a060020a0383166000908152600080516020615999833981519152602090815260408220929092558052600c9052600080516020615979833981519152546138bf903461576d565b6000808052600c60205260008051602061597983398151915291909155600160a060020a0333811691908416907f7cfff908a4b583f36430b25d75964c458d8ede8a99bd61be750e97ee1b2f3a963460405190815260200160405180910390a4506001919050565b600160a060020a03331660009081526003602052604090205460ff16151560011461394e57fe5b600160a060020a0382166000818152600f602052604090819020805460ff19168415151790557ff4633ca7832e2617e9641765f342dbd191acc7e482b57d5871ebca5bbcc5b7fe90839051901515815260200160405180910390a25050565b60025433600160a060020a039081169116146139c557fe5b6007805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f7a0ee36b0dd624c0e5e79330cd2941e28c0d34311e8ecfd1d9362127f82f0d3381604051600160a060020a03909116815260200160405180910390a150565b60036020526000908152604090205460ff1681565b6008546000908190819074010000000000000000000000000000000000000000900460ff1615613a7157600080fd5b8692506014841415613a865760783591508192505b600160a060020a03831615801590613ab0575030600160a060020a031683600160a060020a031614155b8015613ace575033600160a060020a031683600160a060020a031614155b8015613b4a5750600654600160a060020a0316634bf0d3318460006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515613b2e57600080fd5b6102c65a03f11515613b3f57600080fd5b505050604051805190505b1515613b5557600080fd5b50333b60008111613b6557600080fd5b600160a060020a0333166000908152600c6020526040902054613b88908761576d565b600160a060020a033381166000908152600c6020908152604080832094909455600b81528382209287168252919091522054613bc4908761576d565b600160a060020a033381166000818152600b60209081526040808320948916835293905282812093909355889290916370a08231913091516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515613c3e57600080fd5b6102c65a03f11515613c4f57600080fd5b5050506040518051905010151515613c6657600080fd5b86600160a060020a031683600160a060020a031633600160a060020a03167f7cfff908a4b583f36430b25d75964c458d8ede8a99bd61be750e97ee1b2f3a968960405190815260200160405180910390a450505050505050565b600554600160a060020a031681565b600b60209081526000928352604080842090915290825290205481565b60085460009074010000000000000000000000000000000000000000900460ff1615613d1757600080fd5b600654600160a060020a0316634bf0d3313360006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515613d7057600080fd5b6102c65a03f11515613d8157600080fd5b505050604051805190501515613d9657600080fd5b33600160a060020a031660009081526000805160206159998339815191526020526040902054613dc6903461576d565b33600160a060020a03166000908152600080516020615999833981519152602090815260408220929092558052600c905260008051602061597983398151915254613e11903461576d565b6000808052600c6020526000805160206159798339815191529190915533600160a060020a03169081907f7cfff908a4b583f36430b25d75964c458d8ede8a99bd61be750e97ee1b2f3a963460405190815260200160405180910390a4503490565b6000806000613e87898989898960006110fb565b9150613e98898989898960016110fb565b600160a060020a038084166000908152600b602090815260408083203390941683529290522054909150849010801590613ef95750600160a060020a038082166000908152600b602090815260408083203390941683529290522054849010155b1515613f0457600080fd5b600160a060020a038082166000908152600b602090815260408083203390941683529290522054613f35908561570b565b600160a060020a038083166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054613f76908561570b565b600160a060020a038083166000908152600c60209081526040808320949094558583168252600b8152838220339093168252919091522054613fb8908561570b565b600160a060020a038084166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054613ff9908561570b565b600160a060020a038084166000908152600c6020908152604080832094909455918c168152600b8252828120818052909152205461403e90611827612f538b88615720565b600160a060020a038a81166000908152600b6020908152604080832083805290915280822093909355339091168152205461408090612fa4612f538b88615720565b600160a060020a03808b166000818152600b6020908152604080832033861680855292529182902094909455848316938684169390927fbb5fb196fd6ae6343696c34e402990d3bef7d04acc12ac37166c0fbe554735a5928a928e16909118905191825260208201526040908101905180910390a45091979650505050505050565b60008061414c846004608060405190810160405291908282608080828437508893506004925060809150604090505190810160405291908282608080828437506152069350505050565b6000908152600e6020526040902054949350505050565b6000808080804387901161417657600080fd5b6141858b8b8b8b8b60006110fb565b93506141968b8b8b8b8b60016110fb565b600160a060020a038082166000908152600b60209081526040808320339094168352929052205495509250858510156141ce57600080fd5b858511156141da578594505b600085116141e757600080fd5b600160a060020a038084166000908152600b602090815260408083203390941683529290522054614218908661570b565b600160a060020a038085166000818152600b60209081526040808320339095168352938152838220949094559081526012909252902054614259908661576d565b600160a060020a0384166000908152601260205260409020556142c16142a3614285612f53888c615720565b600160a060020a038716600090815260126020526040902054615720565b600160a060020a0386166000908152600c602052604090205461574c565b915061430a6142a36142d6612f53888e615720565b600160a060020a0387166000908152600c6020908152604080832054601290925290912054614305919061570b565b615720565b600160a060020a038a166000908152600b6020908152604080832083805290915290205490915061433b908361570b565b600160a060020a03808b166000908152600b60208181526040808420848052825280842095909555928f1682528252828120818052909152205461437f908261570b565b600160a060020a03808d166000908152600b602081815260408084208480528252808420959095558d841683529081528382203390931682529190915220546143c8908361576d565b600b60008b600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a0316815260200190815260200160002081905550614466600b60008d600160a060020a0316600160a060020a03168152602001908152602001600020600033600160a060020a0316600160a060020a03168152602001908152602001600020548261576d565b600160a060020a03808d166000818152600b602090815260408083203386168085529252918290209490945586831693927f832eb3b5b655da0aa0c29e06b47f7360c5deadb5153ea14d1837dd4944fbc4f9928a92918f1618905191825260208201526040908101905180910390a3505050509695505050505050565b600160a060020a0382166000908152601160209081526040808320548352601090915281205481908190670de0b6b3a764000090614522908890615720565b81151561452b57fe5b600854919004925074010000000000000000000000000000000000000000900460ff1680614622575060008b51600160a060020a03161415801561458e5750600f60008c51600160a060020a0316815260208101919091526040016000205460ff165b80156146225750600654600160a060020a031663014b07328c5160408e01518860006040516020015260405160e060020a63ffffffff8616028152600160a060020a03938416600482015291831660248301529091166044820152606401602060405180830381600087803b151561460557600080fd5b6102c65a03f1151561461657600080fd5b50505060405180519050155b806146ff5750600060208c0151600160a060020a0316141580156146685750600f600060208d0151600160a060020a0316815260208101919091526040016000205460ff165b80156146ff5750600654600160a060020a031663014b073260208d015160408e01518860006040516020015260405160e060020a63ffffffff8616028152600160a060020a03938416600482015291831660248301529091166044820152606401602060405180830381600087803b15156146e257600080fd5b6102c65a03f115156146f357600080fd5b50505060405180519050155b8061473a5750600b60008c51600160a060020a0390811682526020808301939093526040918201600090812091891681529252902054868301115b806147745750600060608c0151600160a060020a0316141580156147745750600160a060020a03851660608c0151600160a060020a031614155b1561478257600092506147bf565b61478f8b8b8b8b8b611198565b90508581111561479c5750845b60018415151480156147ad57508581105b156147bb57600092506147bf565b8092505b505098975050505050505050565b600154600160a060020a031681565b60015433600160a060020a039081169116146147f457fe5b600154600054600160a060020a0391821691167f646fe5eeb20d96ea45a9caafcb508854a2fb5660885ced7772e12a633c97457160405160405180910390a36001546000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055565b60025433600160a060020a0390811691161461487c57fe5b81600160a060020a03167feb4b54e166d09942fe049406526365c69945115063ac3b8b0f7c3a0f0495a54482604051901515815260200160405180910390a2600160a060020a03919091166000908152600360205260409020805460ff1916911515919091179055565b600f6020526000908152604090205460ff1681565b6000308686868633876040516c01000000000000000000000000600160a060020a039889168102825260148201979097526034810195909552605485019390935260748401919091528416830260948301529092160260a882015260bc016040518091039020905033600160a060020a03167fe36534d3086ffa6e0e487d9ee3837ef476fad47478ad2035bd2c383cfbfdd0fe8787878787600e600089600019166000191681526020019081526020016000205460405195865260208601949094526040808601939093526060850191909152600160a060020a0316608084015260a083019190915260c0909101905180910390a26000908152600e60205260409020600190555050505050565b60055460009033600160a060020a03908116911614614a2457fe5b600160a060020a038084166000908152600b6020908152604080832060055490941683529290522054614a57908361576d565b600160a060020a038085166000818152600b60209081526040808320600554909516835293815283822094909455908152600c909252902054614a9a908361576d565b600160a060020a0384166000818152600c602052604090209190915515614b565782600160a060020a03166370a082313060006040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515614b1257600080fd5b6102c65a03f11515614b2357600080fd5b5050506040518051600160a060020a0385166000908152600c602052604090205411159050614b5157600080fd5b614b86565b60008052600c60205260008051602061597983398151915254600160a060020a03301631901115614b8657600080fd5b600160a060020a038381166000818152600b6020908152604080832060055486168452909152908190205433909316927f468284922c196e792dd8af95d8d884fce7be422d6bd1169b7e05904977a18a33918691905191825260208201526040908101905180910390a350919050565b6000806000614c0a888888888860006110fb565b600160a060020a0381166000908152600f602052604090205490925060ff1615614c375760009250614cfc565b614c46888888888860016110fb565b600160a060020a038381166000818152600f60205260408082208054600160ff1991821681179092558686168085529383902080549091169091179055939450929091898116908c1618907fdc81877cc75ce5b9616eb8266d567de063774b7e5df00a488e9ce280ba6209a8908c908c908c908c908c9051600160a060020a0395861681526020810194909452919093166040808401919091526060830193909352608082015260a001905180910390a4600192505b505095945050505050565b600654600090600160a060020a0316634bf0d33183836040516020015260405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515614d6257600080fd5b6102c65a03f11515614d7357600080fd5b50505060405180519392505050565b6008546000908190819074010000000000000000000000000000000000000000900460ff1615614db157600080fd5b43859010614dbe57600080fd5b600160a060020a0389166000908152600b60209081526040808320838052909152902054614df390612fa4612f538b88615720565b600160a060020a038a81166000908152600b60209081526040808320838052909152808220939093553390911681522054614e3590611827612f538b88615720565b600160a060020a03808b166000908152600b6020908152604080832033909416835292905290812091909155614e74908a908a908a908a908a906110fb565b9150614e85898989898960016110fb565b600160a060020a038082166000908152600b602090815260408083203390941683529290522054909150614eb9908561576d565b600160a060020a038083166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054614efa908561576d565b600160a060020a038083166000908152600c60209081526040808320949094558583168252600b8152838220339093168252919091522054614f3c908561576d565b600160a060020a038084166000818152600b6020908152604080832033909516835293815283822094909455908152600c909252902054614f7d908561576d565b600c600084600160a060020a0316600160a060020a031681526020019081526020016000208190555080600160a060020a031682600160a060020a031633600160a060020a03167fb42c6b1349c88a10208a87a5be744f0a7962f8d91c71841d32dfbca7b7066be4878b600160a060020a03166001028e600160a060020a03166001021860405191825260208201526040908101905180910390a4600754600160a060020a0316633a88594d8a8a8a8a8a60006040516020015260405160e060020a63ffffffff8816028152600160a060020a03958616600482015260248101949094529190931660448301526064820192909252608481019190915260a401602060405180830381600087803b151561509657600080fd5b6102c65a03f115156150a757600080fd5b50505060405180511515905061515b57600754600160a060020a031663ec0da0cd8a8a8a8a8a60006040516020015260405160e060020a63ffffffff8816028152600160a060020a03958616600482015260248101949094529190931660448301526064820192909252608481019190915260a401602060405180830381600087803b151561513557600080fd5b6102c65a03f1151561514657600080fd5b50505060405180519050151561515b57600080fd5b5091979650505050505050565b60005433600160a060020a0390811691161461518057fe5b600054600160a060020a038281169116141561519b57600080fd5b600054600160a060020a0380831691167ff4e75b79500ab730f8a026ed3cba6d55331bcb64c9e9f60c548e371356e5e3c060405160405180910390a36001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60003083518351602086015160208601516040870151606088015160408a015160608b01516040516c01000000000000000000000000600160a060020a039a8b1681028252988a1689026014820152602881019790975294881687026048870152605c860193909352607c850191909152609c8401528416830260bc8301529092160260d082015260e4016040518091039020905092915050565b60008033600160a060020a03908116604086013591909116146152c357600080fd5b61530a846004608060405190810160405291908282608080828437508893506004925060809150604090505190810160405291908282608080828437506152069350505050565b6000818152600e60205260409020549091506153289084359061570b565b6000828152600e602090815260409182902086359055919350600160a060020a03338116928701358116873590911618907f0f1206423b754face2dd8203a94256739c90ead9d2248998206fcdc5b0c627829087908790879051808460808082843790910190508360808082843790910192835250506020019150604090505180910390a35092915050565b600e6020526000908152604090205481565b600160a060020a039182166000908152600b6020908152604080832093909416825291909152205490565b60025433600160a060020a0390811691161461540957fe5b600160a060020a038116151561541e57600080fd5b6005805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790557f7ddc968f5ff0f568096d761b25819097ee9902bd80a2cc5c525b8a6e64df946281604051600160a060020a03909116815260200160405180910390a150565b600654600160a060020a031681565b60008043849011156154a657600080fd5b6154b5888888888860006110fb565b600160a060020a038082166000908152600b60209081526040808320339094168352929052205492509050828210156154ed57600080fd5b828211156154f9578291505b6000821161550657600080fd5b600160a060020a038082166000908152600b602090815260408083203390941683529290522054615537908361570b565b600160a060020a038083166000818152600b60209081526040808320339095168352938152838220949094559081526012909252902054615578908361576d565b600160a060020a038083166000908152601260209081526040808320949094558983168252600b81528382203390931682529190915220546155c190611827612f538886615720565b600160a060020a038781166000908152600b602090815260408083203390941683529290528181209290925581805290205461560490612fa4612f538886615720565b600160a060020a038088166000908152600b60208181526040808420848052825280842095909555928c1682528252828120818052909152205461564f90611827612f538a86615720565b600160a060020a038981166000908152600b6020908152604080832083805290915280822093909355339091168152205461569190612fa4612f538a86615720565b600160a060020a03808a166000818152600b602090815260408083203386168085529252918290209490945584831693927f57f69113272de4dd9c983a929da28280f81d87417b489e4f34ca8cfef37c7838928792918c1618905191825260208201526040908101905180910390a3509695505050505050565b60008282111561571a57600080fd5b50900390565b600082151561573157506000611a73565b5081810281838281151561574157fe5b0414611a7357600080fd5b600080821161575a57600080fd5b818381151561576557fe5b049392505050565b81810182811015611a7357600080fd5b600080861161578b57600080fd5b600160a060020a03331660009081526011602090815260408083205483526010909152902054670de0b6b3a7640000906157c6908490615720565b8115156157cf57fe5b600160a060020a03808a166000908152600b60209081526040808320938916835292905220549190049150615804908361576d565b600160a060020a038881166000908152600b60209081526040808320888516845290915280822093909355339091168152205461584590611827848461576d565b600160a060020a038089166000908152600b602081815260408084203386168552825280842095909555898416835290815283822092871682529190915220546158a390876158948786615720565b81151561589d57fe5b0461570b565b600160a060020a038681166000908152600b6020908152604080832088851684529091528082209390935533909116815220546158f490876158e58786615720565b8115156158ee57fe5b0461576d565b600160a060020a038087166000908152600b6020818152604080842033861685528252808420959095558b841683529081528382206004549093168252919091522054615941908261576d565b600160a060020a039788166000908152600b60209081526040808320600454909b1683529990529790972096909655505050505050560013649b2456f1b42fef0f0040b3aaeabcd21a76a0f3f5defd4f583839455116e8df7de25b7f1fd6d0b5205f0e18f1f35bd7b8d84cce336588d184533ce43a6f76a165627a7a72305820317153de19af478b43d81e97e1c28efe4b98fc942063e2b31a630fa1d22bb9480029

Swarm Source

bzzr://317153de19af478b43d81e97e1c28efe4b98fc942063e2b31a630fa1d22bb948

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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