ETH Price: $3,414.02 (+3.08%)

Contract

0x3A2F286AC96051489A544fB91b2E1E5eBBcEA34F
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0x6080604092823582020-01-15 0:12:051774 days ago1579047125IN
 Create: LinearAuctionLiquidator
0 ETH0.021077088

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
LinearAuctionLiquidator

Compiler Version
v0.5.7+commit.6da8b019

Optimization Enabled:
Yes with 200 runs

Other Settings:
byzantium EvmVersion, Apache-2.0 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-01-15
*/

// File: openzeppelin-solidity/contracts/math/SafeMath.sol

pragma solidity ^0.5.2;

/**
 * @title SafeMath
 * @dev Unsigned math operations with safety checks that revert on error
 */
library SafeMath {
    /**
     * @dev Multiplies two unsigned integers, reverts on overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b);

        return c;
    }

    /**
     * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Adds two unsigned integers, reverts on overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

    /**
     * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
     * reverts when dividing by zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
    }
}

// File: contracts/core/interfaces/ICore.sol

/*
    Copyright 2018 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;


/**
 * @title ICore
 * @author Set Protocol
 *
 * The ICore Contract defines all the functions exposed in the Core through its
 * various extensions and is a light weight way to interact with the contract.
 */
interface ICore {
    /**
     * Return transferProxy address.
     *
     * @return address       transferProxy address
     */
    function transferProxy()
        external
        view
        returns (address);

    /**
     * Return vault address.
     *
     * @return address       vault address
     */
    function vault()
        external
        view
        returns (address);

    /**
     * Return address belonging to given exchangeId.
     *
     * @param  _exchangeId       ExchangeId number
     * @return address           Address belonging to given exchangeId
     */
    function exchangeIds(
        uint8 _exchangeId
    )
        external
        view
        returns (address);

    /*
     * Returns if valid set
     *
     * @return  bool      Returns true if Set created through Core and isn't disabled
     */
    function validSets(address)
        external
        view
        returns (bool);

    /*
     * Returns if valid module
     *
     * @return  bool      Returns true if valid module
     */
    function validModules(address)
        external
        view
        returns (bool);

    /**
     * Return boolean indicating if address is a valid Rebalancing Price Library.
     *
     * @param  _priceLibrary    Price library address
     * @return bool             Boolean indicating if valid Price Library
     */
    function validPriceLibraries(
        address _priceLibrary
    )
        external
        view
        returns (bool);

    /**
     * Exchanges components for Set Tokens
     *
     * @param  _set          Address of set to issue
     * @param  _quantity     Quantity of set to issue
     */
    function issue(
        address _set,
        uint256 _quantity
    )
        external;

    /**
     * Issues a specified Set for a specified quantity to the recipient
     * using the caller's components from the wallet and vault.
     *
     * @param  _recipient    Address to issue to
     * @param  _set          Address of the Set to issue
     * @param  _quantity     Number of tokens to issue
     */
    function issueTo(
        address _recipient,
        address _set,
        uint256 _quantity
    )
        external;

    /**
     * Converts user's components into Set Tokens held directly in Vault instead of user's account
     *
     * @param _set          Address of the Set
     * @param _quantity     Number of tokens to redeem
     */
    function issueInVault(
        address _set,
        uint256 _quantity
    )
        external;

    /**
     * Function to convert Set Tokens into underlying components
     *
     * @param _set          The address of the Set token
     * @param _quantity     The number of tokens to redeem. Should be multiple of natural unit.
     */
    function redeem(
        address _set,
        uint256 _quantity
    )
        external;

    /**
     * Redeem Set token and return components to specified recipient. The components
     * are left in the vault
     *
     * @param _recipient    Recipient of Set being issued
     * @param _set          Address of the Set
     * @param _quantity     Number of tokens to redeem
     */
    function redeemTo(
        address _recipient,
        address _set,
        uint256 _quantity
    )
        external;

    /**
     * Function to convert Set Tokens held in vault into underlying components
     *
     * @param _set          The address of the Set token
     * @param _quantity     The number of tokens to redeem. Should be multiple of natural unit.
     */
    function redeemInVault(
        address _set,
        uint256 _quantity
    )
        external;

    /**
     * Composite method to redeem and withdraw with a single transaction
     *
     * Normally, you should expect to be able to withdraw all of the tokens.
     * However, some have central abilities to freeze transfers (e.g. EOS). _toExclude
     * allows you to optionally specify which component tokens to exclude when
     * redeeming. They will remain in the vault under the users' addresses.
     *
     * @param _set          Address of the Set
     * @param _to           Address to withdraw or attribute tokens to
     * @param _quantity     Number of tokens to redeem
     * @param _toExclude    Mask of indexes of tokens to exclude from withdrawing
     */
    function redeemAndWithdrawTo(
        address _set,
        address _to,
        uint256 _quantity,
        uint256 _toExclude
    )
        external;

    /**
     * Deposit multiple tokens to the vault. Quantities should be in the
     * order of the addresses of the tokens being deposited.
     *
     * @param  _tokens           Array of the addresses of the ERC20 tokens
     * @param  _quantities       Array of the number of tokens to deposit
     */
    function batchDeposit(
        address[] calldata _tokens,
        uint256[] calldata _quantities
    )
        external;

    /**
     * Withdraw multiple tokens from the vault. Quantities should be in the
     * order of the addresses of the tokens being withdrawn.
     *
     * @param  _tokens            Array of the addresses of the ERC20 tokens
     * @param  _quantities        Array of the number of tokens to withdraw
     */
    function batchWithdraw(
        address[] calldata _tokens,
        uint256[] calldata _quantities
    )
        external;

    /**
     * Deposit any quantity of tokens into the vault.
     *
     * @param  _token           The address of the ERC20 token
     * @param  _quantity        The number of tokens to deposit
     */
    function deposit(
        address _token,
        uint256 _quantity
    )
        external;

    /**
     * Withdraw a quantity of tokens from the vault.
     *
     * @param  _token           The address of the ERC20 token
     * @param  _quantity        The number of tokens to withdraw
     */
    function withdraw(
        address _token,
        uint256 _quantity
    )
        external;

    /**
     * Transfer tokens associated with the sender's account in vault to another user's
     * account in vault.
     *
     * @param  _token           Address of token being transferred
     * @param  _to              Address of user receiving tokens
     * @param  _quantity        Amount of tokens being transferred
     */
    function internalTransfer(
        address _token,
        address _to,
        uint256 _quantity
    )
        external;

    /**
     * Deploys a new Set Token and adds it to the valid list of SetTokens
     *
     * @param  _factory              The address of the Factory to create from
     * @param  _components           The address of component tokens
     * @param  _units                The units of each component token
     * @param  _naturalUnit          The minimum unit to be issued or redeemed
     * @param  _name                 The bytes32 encoded name of the new Set
     * @param  _symbol               The bytes32 encoded symbol of the new Set
     * @param  _callData             Byte string containing additional call parameters
     * @return setTokenAddress       The address of the new Set
     */
    function createSet(
        address _factory,
        address[] calldata _components,
        uint256[] calldata _units,
        uint256 _naturalUnit,
        bytes32 _name,
        bytes32 _symbol,
        bytes calldata _callData
    )
        external
        returns (address);

    /**
     * Exposes internal function that deposits a quantity of tokens to the vault and attributes
     * the tokens respectively, to system modules.
     *
     * @param  _from            Address to transfer tokens from
     * @param  _to              Address to credit for deposit
     * @param  _token           Address of token being deposited
     * @param  _quantity        Amount of tokens to deposit
     */
    function depositModule(
        address _from,
        address _to,
        address _token,
        uint256 _quantity
    )
        external;

    /**
     * Exposes internal function that withdraws a quantity of tokens from the vault and
     * deattributes the tokens respectively, to system modules.
     *
     * @param  _from            Address to decredit for withdraw
     * @param  _to              Address to transfer tokens to
     * @param  _token           Address of token being withdrawn
     * @param  _quantity        Amount of tokens to withdraw
     */
    function withdrawModule(
        address _from,
        address _to,
        address _token,
        uint256 _quantity
    )
        external;

    /**
     * Exposes internal function that deposits multiple tokens to the vault, to system
     * modules. Quantities should be in the order of the addresses of the tokens being
     * deposited.
     *
     * @param  _from              Address to transfer tokens from
     * @param  _to                Address to credit for deposits
     * @param  _tokens            Array of the addresses of the tokens being deposited
     * @param  _quantities        Array of the amounts of tokens to deposit
     */
    function batchDepositModule(
        address _from,
        address _to,
        address[] calldata _tokens,
        uint256[] calldata _quantities
    )
        external;

    /**
     * Exposes internal function that withdraws multiple tokens from the vault, to system
     * modules. Quantities should be in the order of the addresses of the tokens being withdrawn.
     *
     * @param  _from              Address to decredit for withdrawals
     * @param  _to                Address to transfer tokens to
     * @param  _tokens            Array of the addresses of the tokens being withdrawn
     * @param  _quantities        Array of the amounts of tokens to withdraw
     */
    function batchWithdrawModule(
        address _from,
        address _to,
        address[] calldata _tokens,
        uint256[] calldata _quantities
    )
        external;

    /**
     * Expose internal function that exchanges components for Set tokens,
     * accepting any owner, to system modules
     *
     * @param  _owner        Address to use tokens from
     * @param  _recipient    Address to issue Set to
     * @param  _set          Address of the Set to issue
     * @param  _quantity     Number of tokens to issue
     */
    function issueModule(
        address _owner,
        address _recipient,
        address _set,
        uint256 _quantity
    )
        external;

    /**
     * Expose internal function that exchanges Set tokens for components,
     * accepting any owner, to system modules
     *
     * @param  _burnAddress         Address to burn token from
     * @param  _incrementAddress    Address to increment component tokens to
     * @param  _set                 Address of the Set to redeem
     * @param  _quantity            Number of tokens to redeem
     */
    function redeemModule(
        address _burnAddress,
        address _incrementAddress,
        address _set,
        uint256 _quantity
    )
        external;

    /**
     * Expose vault function that increments user's balance in the vault.
     * Available to system modules
     *
     * @param  _tokens          The addresses of the ERC20 tokens
     * @param  _owner           The address of the token owner
     * @param  _quantities      The numbers of tokens to attribute to owner
     */
    function batchIncrementTokenOwnerModule(
        address[] calldata _tokens,
        address _owner,
        uint256[] calldata _quantities
    )
        external;

    /**
     * Expose vault function that decrement user's balance in the vault
     * Only available to system modules.
     *
     * @param  _tokens          The addresses of the ERC20 tokens
     * @param  _owner           The address of the token owner
     * @param  _quantities      The numbers of tokens to attribute to owner
     */
    function batchDecrementTokenOwnerModule(
        address[] calldata _tokens,
        address _owner,
        uint256[] calldata _quantities
    )
        external;

    /**
     * Expose vault function that transfer vault balances between users
     * Only available to system modules.
     *
     * @param  _tokens           Addresses of tokens being transferred
     * @param  _from             Address tokens being transferred from
     * @param  _to               Address tokens being transferred to
     * @param  _quantities       Amounts of tokens being transferred
     */
    function batchTransferBalanceModule(
        address[] calldata _tokens,
        address _from,
        address _to,
        uint256[] calldata _quantities
    )
        external;

    /**
     * Transfers token from one address to another using the transfer proxy.
     * Only available to system modules.
     *
     * @param  _token          The address of the ERC20 token
     * @param  _quantity       The number of tokens to transfer
     * @param  _from           The address to transfer from
     * @param  _to             The address to transfer to
     */
    function transferModule(
        address _token,
        uint256 _quantity,
        address _from,
        address _to
    )
        external;

    /**
     * Expose transfer proxy function to transfer tokens from one address to another
     * Only available to system modules.
     *
     * @param  _tokens         The addresses of the ERC20 token
     * @param  _quantities     The numbers of tokens to transfer
     * @param  _from           The address to transfer from
     * @param  _to             The address to transfer to
     */
    function batchTransferModule(
        address[] calldata _tokens,
        uint256[] calldata _quantities,
        address _from,
        address _to
    )
        external;
}

// File: contracts/core/interfaces/ISetToken.sol

/*
    Copyright 2018 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;

/**
 * @title ISetToken
 * @author Set Protocol
 *
 * The ISetToken interface provides a light-weight, structured way to interact with the
 * SetToken contract from another contract.
 */
interface ISetToken {

    /* ============ External Functions ============ */

    /*
     * Get natural unit of Set
     *
     * @return  uint256       Natural unit of Set
     */
    function naturalUnit()
        external
        view
        returns (uint256);

    /*
     * Get addresses of all components in the Set
     *
     * @return  componentAddresses       Array of component tokens
     */
    function getComponents()
        external
        view
        returns (address[] memory);

    /*
     * Get units of all tokens in Set
     *
     * @return  units       Array of component units
     */
    function getUnits()
        external
        view
        returns (uint256[] memory);

    /*
     * Checks to make sure token is component of Set
     *
     * @param  _tokenAddress     Address of token being checked
     * @return  bool             True if token is component of Set
     */
    function tokenIsComponent(
        address _tokenAddress
    )
        external
        view
        returns (bool);

    /*
     * Mint set token for given address.
     * Can only be called by authorized contracts.
     *
     * @param  _issuer      The address of the issuing account
     * @param  _quantity    The number of sets to attribute to issuer
     */
    function mint(
        address _issuer,
        uint256 _quantity
    )
        external;

    /*
     * Burn set token for given address
     * Can only be called by authorized contracts
     *
     * @param  _from        The address of the redeeming account
     * @param  _quantity    The number of sets to burn from redeemer
     */
    function burn(
        address _from,
        uint256 _quantity
    )
        external;

    /**
    * Transfer token for a specified address
    *
    * @param to The address to transfer to.
    * @param value The amount to be transferred.
    */
    function transfer(
        address to,
        uint256 value
    )
        external;
}

// File: contracts/core/lib/RebalancingLibrary.sol

/*
    Copyright 2018 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;


/**
 * @title RebalancingLibrary
 * @author Set Protocol
 *
 * The RebalancingLibrary contains functions for facilitating the rebalancing process for
 * Rebalancing Set Tokens. Removes the old calculation functions
 *
 */
library RebalancingLibrary {

    /* ============ Enums ============ */

    enum State { Default, Proposal, Rebalance, Drawdown }

    /* ============ Structs ============ */

    struct AuctionPriceParameters {
        uint256 auctionStartTime;
        uint256 auctionTimeToPivot;
        uint256 auctionStartPrice;
        uint256 auctionPivotPrice;
    }

    struct BiddingParameters {
        uint256 minimumBid;
        uint256 remainingCurrentSets;
        uint256[] combinedCurrentUnits;
        uint256[] combinedNextSetUnits;
        address[] combinedTokenArray;
    }
}

// File: contracts/core/interfaces/IRebalancingSetToken.sol

/*
    Copyright 2018 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;


/**
 * @title IRebalancingSetToken
 * @author Set Protocol
 *
 * The IRebalancingSetToken interface provides a light-weight, structured way to interact with the
 * RebalancingSetToken contract from another contract.
 */

interface IRebalancingSetToken {

    /*
     * Get the auction library contract used for the current rebalance
     *
     * @return address    Address of auction library used in the upcoming auction
     */
    function auctionLibrary()
        external
        view
        returns (address);

    /*
     * Get totalSupply of Rebalancing Set
     *
     * @return  totalSupply
     */
    function totalSupply()
        external
        view
        returns (uint256);

    /*
     * Get proposalTimeStamp of Rebalancing Set
     *
     * @return  proposalTimeStamp
     */
    function proposalStartTime()
        external
        view
        returns (uint256);

    /*
     * Get lastRebalanceTimestamp of Rebalancing Set
     *
     * @return  lastRebalanceTimestamp
     */
    function lastRebalanceTimestamp()
        external
        view
        returns (uint256);

    /*
     * Get rebalanceInterval of Rebalancing Set
     *
     * @return  rebalanceInterval
     */
    function rebalanceInterval()
        external
        view
        returns (uint256);

    /*
     * Get rebalanceState of Rebalancing Set
     *
     * @return RebalancingLibrary.State    Current rebalance state of the RebalancingSetToken
     */
    function rebalanceState()
        external
        view
        returns (RebalancingLibrary.State);

    /*
     * Get the starting amount of current SetToken for the current auction
     *
     * @return  rebalanceState
     */
    function startingCurrentSetAmount()
        external
        view
        returns (uint256);

    /**
     * Gets the balance of the specified address.
     *
     * @param owner      The address to query the balance of.
     * @return           A uint256 representing the amount owned by the passed address.
     */
    function balanceOf(
        address owner
    )
        external
        view
        returns (uint256);

    /**
     * Function used to set the terms of the next rebalance and start the proposal period
     *
     * @param _nextSet                      The Set to rebalance into
     * @param _auctionLibrary               The library used to calculate the Dutch Auction price
     * @param _auctionTimeToPivot           The amount of time for the auction to go ffrom start to pivot price
     * @param _auctionStartPrice            The price to start the auction at
     * @param _auctionPivotPrice            The price at which the price curve switches from linear to exponential
     */
    function propose(
        address _nextSet,
        address _auctionLibrary,
        uint256 _auctionTimeToPivot,
        uint256 _auctionStartPrice,
        uint256 _auctionPivotPrice
    )
        external;

    /*
     * Get natural unit of Set
     *
     * @return  uint256       Natural unit of Set
     */
    function naturalUnit()
        external
        view
        returns (uint256);

    /**
     * Returns the address of the current base SetToken with the current allocation
     *
     * @return           A address representing the base SetToken
     */
    function currentSet()
        external
        view
        returns (address);

    /**
     * Returns the address of the next base SetToken with the post auction allocation
     *
     * @return  address    Address representing the base SetToken
     */
    function nextSet()
        external
        view
        returns (address);

    /*
     * Get the unit shares of the rebalancing Set
     *
     * @return  unitShares       Unit Shares of the base Set
     */
    function unitShares()
        external
        view
        returns (uint256);

    /*
     * Burn set token for given address.
     * Can only be called by authorized contracts.
     *
     * @param  _from        The address of the redeeming account
     * @param  _quantity    The number of sets to burn from redeemer
     */
    function burn(
        address _from,
        uint256 _quantity
    )
        external;

    /*
     * Place bid during rebalance auction. Can only be called by Core.
     *
     * @param _quantity                 The amount of currentSet to be rebalanced
     * @return combinedTokenArray       Array of token addresses invovled in rebalancing
     * @return inflowUnitArray          Array of amount of tokens inserted into system in bid
     * @return outflowUnitArray         Array of amount of tokens taken out of system in bid
     */
    function placeBid(
        uint256 _quantity
    )
        external
        returns (address[] memory, uint256[] memory, uint256[] memory);

    /*
     * Get combinedTokenArray of Rebalancing Set
     *
     * @return  combinedTokenArray
     */
    function getCombinedTokenArrayLength()
        external
        view
        returns (uint256);

    /*
     * Get combinedTokenArray of Rebalancing Set
     *
     * @return  combinedTokenArray
     */
    function getCombinedTokenArray()
        external
        view
        returns (address[] memory);

    /*
     * Get failedAuctionWithdrawComponents of Rebalancing Set
     *
     * @return  failedAuctionWithdrawComponents
     */
    function getFailedAuctionWithdrawComponents()
        external
        view
        returns (address[] memory);

    /*
     * Get auctionPriceParameters for current auction
     *
     * @return uint256[4]    AuctionPriceParameters for current rebalance auction
     */
    function getAuctionPriceParameters()
        external
        view
        returns (uint256[] memory);

    /*
     * Get biddingParameters for current auction
     *
     * @return uint256[2]    BiddingParameters for current rebalance auction
     */
    function getBiddingParameters()
        external
        view
        returns (uint256[] memory);

    /*
     * Get token inflows and outflows required for bid. Also the amount of Rebalancing
     * Sets that would be generated.
     *
     * @param _quantity               The amount of currentSet to be rebalanced
     * @return inflowUnitArray        Array of amount of tokens inserted into system in bid
     * @return outflowUnitArray       Array of amount of tokens taken out of system in bid
     */
    function getBidPrice(
        uint256 _quantity
    )
        external
        view
        returns (uint256[] memory, uint256[] memory);

}

// File: contracts/core/lib/Rebalance.sol

/*
    Copyright 2019 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;



/**
 * @title Rebalance
 * @author Set Protocol
 *
 * Types and functions for Rebalance-related data.
 */
library Rebalance {

    struct TokenFlow {
        address[] addresses;
        uint256[] inflow;
        uint256[] outflow;
    }

    function composeTokenFlow(
        address[] memory _addresses,
        uint256[] memory _inflow,
        uint256[] memory _outflow
    )
        internal
        pure
        returns(TokenFlow memory)
    {
        return TokenFlow({addresses: _addresses, inflow: _inflow, outflow: _outflow });
    }

    function decomposeTokenFlow(TokenFlow memory _tokenFlow)
        internal
        pure
        returns (address[] memory, uint256[] memory, uint256[] memory)
    {
        return (_tokenFlow.addresses, _tokenFlow.inflow, _tokenFlow.outflow);
    }

    function decomposeTokenFlowToBidPrice(TokenFlow memory _tokenFlow)
        internal
        pure
        returns (uint256[] memory, uint256[] memory)
    {
        return (_tokenFlow.inflow, _tokenFlow.outflow);
    }

    /**
     * Get token flows array of addresses, inflows and outflows
     *
     * @param    _rebalancingSetToken   The rebalancing Set Token instance
     * @param    _quantity              The amount of currentSet to be rebalanced
     * @return   combinedTokenArray     Array of token addresses
     * @return   inflowArray            Array of amount of tokens inserted into system in bid
     * @return   outflowArray           Array of amount of tokens returned from system in bid
     */
    function getTokenFlows(
        IRebalancingSetToken _rebalancingSetToken,
        uint256 _quantity
    )
        internal
        view
        returns (address[] memory, uint256[] memory, uint256[] memory)
    {
        // Get token addresses
        address[] memory combinedTokenArray = _rebalancingSetToken.getCombinedTokenArray();

        // Get inflow and outflow arrays for the given bid quantity
        (
            uint256[] memory inflowArray,
            uint256[] memory outflowArray
        ) = _rebalancingSetToken.getBidPrice(_quantity);

        return (combinedTokenArray, inflowArray, outflowArray);
    }
}

// File: contracts/core/interfaces/ILiquidator.sol

/*
    Copyright 2019 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;




/**
 * @title ILiquidator
 * @author Set Protocol
 *
 */
interface ILiquidator {

    /* ============ External Functions ============ */

    function startRebalance(
        ISetToken _currentSet,
        ISetToken _nextSet,
        uint256 _startingCurrentSetQuantity,
        bytes calldata _liquidatorData
    )
        external;

    function getBidPrice(
        address _set,
        uint256 _quantity
    )
        external
        view
        returns (Rebalance.TokenFlow memory);

    function placeBid(
        uint256 _quantity
    )
        external
        returns (Rebalance.TokenFlow memory);


    function settleRebalance()
        external;

    function endFailedRebalance() external;

    // ----------------------------------------------------------------------
    // Auction Price
    // ----------------------------------------------------------------------

    function auctionPriceParameters(address _set)
        external
        view
        returns (RebalancingLibrary.AuctionPriceParameters memory);

    // ----------------------------------------------------------------------
    // Auction
    // ----------------------------------------------------------------------

    function hasRebalanceFailed(address _set) external view returns (bool);
    function minimumBid(address _set) external view returns (uint256);
    function startingCurrentSets(address _set) external view returns (uint256);
    function remainingCurrentSets(address _set) external view returns (uint256);
    function getCombinedCurrentSetUnits(address _set) external view returns (uint256[] memory);
    function getCombinedNextSetUnits(address _set) external view returns (uint256[] memory);
    function getCombinedTokenArray(address _set) external view returns (address[] memory);
}

// File: contracts/core/interfaces/IOracleWhiteList.sol

/*
    Copyright 2019 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;

/**
 * @title IOracleWhiteList
 * @author Set Protocol
 *
 * The IWhiteList interface exposes the whitelist mapping to check components
 */
interface IOracleWhiteList {

    /* ============ External Functions ============ */

    /**
     * Returns oracle of passed token address (not in array form)
     *
     * @param  _tokenAddress       Address to check
     * @return bool                Whether passed in address is whitelisted
     */
    function oracleWhiteList(
        address _tokenAddress
    )
        external
        view
        returns (address);

    /**
     * Verifies an array of token addresses against the whitelist
     *
     * @param  _addresses    Array of addresses to verify
     * @return bool          Whether all addresses in the list are whitelsited
     */
    function areValidAddresses(
        address[] calldata _addresses
    )
        external
        view
        returns (bool);

    /**
     * Return array of oracle addresses based on passed in token addresses
     *
     * @param  _tokenAddresses    Array of token addresses to get oracle addresses for
     * @return address[]          Array of oracle addresses
     */
    function getOracleAddressesByToken(
        address[] calldata _tokenAddresses
    )
        external
        view
        returns (address[] memory);

    function getOracleAddressByToken(
        address _token
    )
        external
        view
        returns (address);
}

// File: openzeppelin-solidity/contracts/math/Math.sol

pragma solidity ^0.5.2;

/**
 * @title Math
 * @dev Assorted math operations
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Calculates the average of two numbers. Since these are integers,
     * averages of an even and odd number cannot be represented, and will be
     * rounded down.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

// File: set-protocol-strategies/contracts/meta-oracles/interfaces/IOracle.sol

/*
    Copyright 2019 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;


/**
 * @title IOracle
 * @author Set Protocol
 *
 * Interface for operating with any external Oracle that returns uint256 or
 * an adapting contract that converts oracle output to uint256
 */
interface IOracle {

    /**
     * Returns the queried data from an oracle returning uint256
     *
     * @return  Current price of asset represented in uint256
     */
    function read()
        external
        view
        returns (uint256);
}

// File: contracts/lib/AddressArrayUtils.sol

// Pulled in from Cryptofin Solidity package in order to control Solidity compiler version
// https://github.com/cryptofinlabs/cryptofin-solidity/blob/master/contracts/array-utils/AddressArrayUtils.sol

pragma solidity 0.5.7;


library AddressArrayUtils {

    /**
     * Finds the index of the first occurrence of the given element.
     * @param A The input array to search
     * @param a The value to find
     * @return Returns (index and isIn) for the first occurrence starting from index 0
     */
    function indexOf(address[] memory A, address a) internal pure returns (uint256, bool) {
        uint256 length = A.length;
        for (uint256 i = 0; i < length; i++) {
            if (A[i] == a) {
                return (i, true);
            }
        }
        return (0, false);
    }

    /**
    * Returns true if the value is present in the list. Uses indexOf internally.
    * @param A The input array to search
    * @param a The value to find
    * @return Returns isIn for the first occurrence starting from index 0
    */
    function contains(address[] memory A, address a) internal pure returns (bool) {
        bool isIn;
        (, isIn) = indexOf(A, a);
        return isIn;
    }

    /**
     * Returns the combination of the two arrays
     * @param A The first array
     * @param B The second array
     * @return Returns A extended by B
     */
    function extend(address[] memory A, address[] memory B) internal pure returns (address[] memory) {
        uint256 aLength = A.length;
        uint256 bLength = B.length;
        address[] memory newAddresses = new address[](aLength + bLength);
        for (uint256 i = 0; i < aLength; i++) {
            newAddresses[i] = A[i];
        }
        for (uint256 j = 0; j < bLength; j++) {
            newAddresses[aLength + j] = B[j];
        }
        return newAddresses;
    }

    /**
     * Returns the array with a appended to A.
     * @param A The first array
     * @param a The value to append
     * @return Returns A appended by a
     */
    function append(address[] memory A, address a) internal pure returns (address[] memory) {
        address[] memory newAddresses = new address[](A.length + 1);
        for (uint256 i = 0; i < A.length; i++) {
            newAddresses[i] = A[i];
        }
        newAddresses[A.length] = a;
        return newAddresses;
    }

    /**
     * Returns the intersection of two arrays. Arrays are treated as collections, so duplicates are kept.
     * @param A The first array
     * @param B The second array
     * @return The intersection of the two arrays
     */
    function intersect(address[] memory A, address[] memory B) internal pure returns (address[] memory) {
        uint256 length = A.length;
        bool[] memory includeMap = new bool[](length);
        uint256 newLength = 0;
        for (uint256 i = 0; i < length; i++) {
            if (contains(B, A[i])) {
                includeMap[i] = true;
                newLength++;
            }
        }
        address[] memory newAddresses = new address[](newLength);
        uint256 j = 0;
        for (uint256 k = 0; k < length; k++) {
            if (includeMap[k]) {
                newAddresses[j] = A[k];
                j++;
            }
        }
        return newAddresses;
    }

    /**
     * Returns the union of the two arrays. Order is not guaranteed.
     * @param A The first array
     * @param B The second array
     * @return The union of the two arrays
     */
    function union(address[] memory A, address[] memory B) internal pure returns (address[] memory) {
        address[] memory leftDifference = difference(A, B);
        address[] memory rightDifference = difference(B, A);
        address[] memory intersection = intersect(A, B);
        return extend(leftDifference, extend(intersection, rightDifference));
    }

    /**
     * Computes the difference of two arrays. Assumes there are no duplicates.
     * @param A The first array
     * @param B The second array
     * @return The difference of the two arrays
     */
    function difference(address[] memory A, address[] memory B) internal pure returns (address[] memory) {
        uint256 length = A.length;
        bool[] memory includeMap = new bool[](length);
        uint256 count = 0;
        // First count the new length because can't push for in-memory arrays
        for (uint256 i = 0; i < length; i++) {
            address e = A[i];
            if (!contains(B, e)) {
                includeMap[i] = true;
                count++;
            }
        }
        address[] memory newAddresses = new address[](count);
        uint256 j = 0;
        for (uint256 k = 0; k < length; k++) {
            if (includeMap[k]) {
                newAddresses[j] = A[k];
                j++;
            }
        }
        return newAddresses;
    }

    /**
    * Removes specified index from array
    * Resulting ordering is not guaranteed
    * @return Returns the new array and the removed entry
    */
    function pop(address[] memory A, uint256 index)
        internal
        pure
        returns (address[] memory, address)
    {
        uint256 length = A.length;
        address[] memory newAddresses = new address[](length - 1);
        for (uint256 i = 0; i < index; i++) {
            newAddresses[i] = A[i];
        }
        for (uint256 j = index + 1; j < length; j++) {
            newAddresses[j - 1] = A[j];
        }
        return (newAddresses, A[index]);
    }

    /**
     * @return Returns the new array
     */
    function remove(address[] memory A, address a)
        internal
        pure
        returns (address[] memory)
    {
        (uint256 index, bool isIn) = indexOf(A, a);
        if (!isIn) {
            revert();
        } else {
            (address[] memory _A,) = pop(A, index);
            return _A;
        }
    }

    /**
     * Returns whether or not there's a duplicate. Runs in O(n^2).
     * @param A Array to search
     * @return Returns true if duplicate, false otherwise
     */
    function hasDuplicate(address[] memory A) internal pure returns (bool) {
        if (A.length == 0) {
            return false;
        }
        for (uint256 i = 0; i < A.length - 1; i++) {
            for (uint256 j = i + 1; j < A.length; j++) {
                if (A[i] == A[j]) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Returns whether the two arrays are equal.
     * @param A The first array
     * @param B The second array
     * @return True is the arrays are equal, false if not.
     */
    function isEqual(address[] memory A, address[] memory B) internal pure returns (bool) {
        if (A.length != B.length) {
            return false;
        }
        for (uint256 i = 0; i < A.length; i++) {
            if (A[i] != B[i]) {
                return false;
            }
        }
        return true;
    }
}

// File: contracts/core/lib/SetMath.sol

/*
    Copyright 2019 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;



/**
 * @title SetMath
 * @author Set Protocol
 */
library SetMath {
    using SafeMath for uint256;


    /**
     * Converts SetToken quantity to component quantity
     */
    function setToComponent(
        uint256 _setQuantity,
        uint256 _componentUnit,
        uint256 _naturalUnit
    )
        internal
        pure
        returns(uint256)
    {
        return _setQuantity.mul(_componentUnit).div(_naturalUnit);
    }

    /**
     * Converts component quantity to Set quantity
     */
    function componentToSet(
        uint256 _componentQuantity,
        uint256 _componentUnit,
        uint256 _naturalUnit
    )
        internal
        pure
        returns(uint256)
    {
        return _componentQuantity.mul(_naturalUnit).div(_componentUnit);
    }
}

// File: contracts/core/liquidators/impl/Auction.sol

/*
    Copyright 2019 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;










/**
 * @title Auction
 * @author Set Protocol
 *
 * Contract containing utility functions for liquidators that use auctions processes. Contains
 * helper functions to value collateral SetTokens and determine parameters used in bidding
 * processes. Meant to be inherited.
 */
contract Auction {
    using SafeMath for uint256;
    using AddressArrayUtils for address[];

    /* ============ Structs ============ */
    struct Setup {
        uint256 maxNaturalUnit;
        uint256 minimumBid;
        uint256 startTime;
        uint256 startingCurrentSets;
        uint256 remainingCurrentSets;
        address[] combinedTokenArray;
        uint256[] combinedCurrentSetUnits;
        uint256[] combinedNextSetUnits;
    }

    /* ============ Structs ============ */
    uint256 constant private CURVE_DENOMINATOR = 10 ** 18;

    /* ============ Auction Struct Methods ============ */

    /*
     * Sets the Auction Setup struct variables.
     *
     * @param _auction                      Auction Setup object
     * @param _currentSet                   The Set to rebalance from
     * @param _nextSet                      The Set to rebalance to
     * @param _startingCurrentSetQuantity   Quantity of currentSet to rebalance
     */
    function initializeAuction(
        Setup storage _auction,
        ISetToken _currentSet,
        ISetToken _nextSet,
        uint256 _startingCurrentSetQuantity
    )
        internal
    {
        _auction.maxNaturalUnit = Math.max(
            _currentSet.naturalUnit(),
            _nextSet.naturalUnit()
        );

        _auction.startingCurrentSets = _startingCurrentSetQuantity;
        _auction.remainingCurrentSets = _startingCurrentSetQuantity;
        _auction.startTime = block.timestamp;
        _auction.combinedTokenArray = getCombinedTokenArray(_currentSet, _nextSet);
        _auction.combinedCurrentSetUnits = calculateCombinedUnitArray(_auction, _currentSet);
        _auction.combinedNextSetUnits = calculateCombinedUnitArray(_auction, _nextSet);
    }

    function reduceRemainingCurrentSets(Setup storage _auction, uint256 _quantity) internal {
        _auction.remainingCurrentSets = _auction.remainingCurrentSets.sub(_quantity);
    }

    /*
     * Validate bid is a multiple of minimum bid and that amount is less than remaining.
     */
    function validateBidQuantity(Setup storage _auction, uint256 _quantity) internal view {
        require(
            _quantity.mod(_auction.minimumBid) == 0,
            "Auction.validateBidQuantity: Must bid multiple of minimum bid"
        );

        require(
            _quantity <= _auction.remainingCurrentSets,
            "Auction.validateBidQuantity: Bid exceeds remaining current sets"
        );
    }

    /*
     * Asserts whether the auction has been completed, which is when all currentSets have been
     * rebalanced.
     */
    function validateAuctionCompletion(Setup storage _auction) internal view {
        require(
            !hasBiddableQuantity(_auction),
            "Auction.settleRebalance: Rebalance not completed"
        );
    }

    /**
     * Returns whether the remainingSets is still a quantity equal or greater than the minimum bid
     */
    function hasBiddableQuantity(Setup storage _auction) internal view returns(bool) {
        return _auction.remainingCurrentSets >= _auction.minimumBid;
    }

    /**
     * Returns whether the auction is active
     */
    function isAuctionActive(Setup storage _auction) internal view returns(bool) {
        return _auction.startTime > 0;
    }

    /*
     * Calculates TokenFlows
     *
     * @param _auction              Auction Setup object
     * @param _quantity             Amount of currentSets bidder is seeking to rebalance
     * @param _price                Value representing the auction numeartor
     */
    function calculateTokenFlow(
        Setup storage _auction,
        uint256 _quantity,
        uint256 _price
    )
        internal
        view
        returns (Rebalance.TokenFlow memory)
    {
        // Normalized quantity amount
        uint256 unitsMultiplier = _quantity.div(_auction.maxNaturalUnit);

        address[] memory memCombinedTokenArray = _auction.combinedTokenArray;

        uint256 combinedTokenCount = memCombinedTokenArray.length;
        uint256[] memory inflowUnitArray = new uint256[](combinedTokenCount);
        uint256[] memory outflowUnitArray = new uint256[](combinedTokenCount);

        // Cycle through each token in combinedTokenArray, calculate inflow/outflow and store
        // result in array
        for (uint256 i = 0; i < combinedTokenCount; i++) {
            (
                inflowUnitArray[i],
                outflowUnitArray[i]
            ) = calculateInflowOutflow(
                _auction.combinedCurrentSetUnits[i],
                _auction.combinedNextSetUnits[i],
                unitsMultiplier,
                _price
            );
        }

        return Rebalance.composeTokenFlow(memCombinedTokenArray, inflowUnitArray, outflowUnitArray);
    }

    /**
     * Computes the union of the currentSet and nextSet components
     *
     * @param _currentSet               The Set to rebalance from
     * @param _nextSet                  The Set to rebalance to
     * @return                          Aggregated components array
     */
    function getCombinedTokenArray(
        ISetToken _currentSet,
        ISetToken _nextSet
    )
        internal
        view
        returns(address[] memory)
    {
        address[] memory currentSetComponents = _currentSet.getComponents();
        address[] memory nextSetComponents = _nextSet.getComponents();
        return currentSetComponents.union(nextSetComponents);
    }

    /*
     * Calculates token inflow/outflow for single component in combinedTokenArray
     *
     * @param _currentUnit          Amount of token i in currentSet per minimum bid amount
     * @param _nextSetUnit          Amount of token i in nextSet per minimum bid amount
     * @param _unitsMultiplier      Bid amount normalized to number of minimum bid amounts
     * @param _price                Auction price numerator with 10 ** 18 as denominator
     * @return inflowUnit           Amount of token i transferred into the system
     * @return outflowUnit          Amount of token i transferred to the bidder
     */
    function calculateInflowOutflow(
        uint256 _currentUnit,
        uint256 _nextSetUnit,
        uint256 _unitsMultiplier,
        uint256 _price
    )
        internal
        pure
        returns (uint256, uint256)
    {
        /*
         * Below is a mathematically simplified formula for calculating token inflows and
         * outflows, the following is it's derivation:
         * token_flow = (bidQuantity/price)*(nextUnit - price*currentUnit)
         *
         * Where,
         * 1) price = (priceNumerator/priceDivisor),
         * 2) nextUnit and currentUnit are the amount of component i needed for a
         * standardAmount of sets to be rebalanced where one standardAmount =
         * max(natural unit nextSet, natural unit currentSet), and
         * 3) bidQuantity is a normalized amount in terms of the standardAmount used
         * to calculate nextUnit and currentUnit. This is represented by the unitsMultiplier
         * variable.
         *
         * Given these definitions we can derive the below formula as follows:
         * token_flow = (unitsMultiplier/(priceNumerator/priceDivisor))*
         * (nextUnit - (priceNumerator/priceDivisor)*currentUnit)
         *
         * We can then multiply this equation by (priceDivisor/priceDivisor)
         * which simplifies the above equation to:
         *
         * (unitsMultiplier/priceNumerator)* (nextUnit*priceDivisor - currentUnit*priceNumerator)
         *
         * This is the equation seen below, but since unsigned integers are used we must check to see if
         * nextUnit*priceDivisor > currentUnit*priceNumerator, otherwise those two terms must be
         * flipped in the equation.
         */
        uint256 inflowUnit;
        uint256 outflowUnit;

        // Use if statement to check if token inflow or outflow
        if (_nextSetUnit.mul(CURVE_DENOMINATOR) > _currentUnit.mul(_price)) {
            // Calculate inflow amount
            inflowUnit = _unitsMultiplier.mul(
                _nextSetUnit.mul(CURVE_DENOMINATOR).sub(_currentUnit.mul(_price))
            ).div(_price);

            // Set outflow amount to 0 for component i, since tokens need to be injected in rebalance
            outflowUnit = 0;
        } else {
            // Calculate outflow amount
            outflowUnit = _unitsMultiplier.mul(
                _currentUnit.mul(_price).sub(_nextSetUnit.mul(CURVE_DENOMINATOR))
            ).div(_price);

            // Set inflow amount to 0 for component i, since tokens need to be returned in rebalance
            inflowUnit = 0;
        }

        return (inflowUnit, outflowUnit);
    }

    /* ============ Token Array Creation Helpers ============ */

    /**
     * Create uint256 arrays that represents all components in currentSet and nextSet.
     * Calcualate unit difference between both sets relative to the largest natural
     * unit of the two sets.
     *
     * @param _auction           Auction Setup object
     * @param _set               The Set to generate units for
     * @return combinedUnits
     */
    function calculateCombinedUnitArray(
        Setup storage _auction,
        ISetToken _set
    )
        internal
        view
        returns (uint256[] memory)
    {
        address[] memory combinedTokenArray = _auction.combinedTokenArray;
        uint256[] memory combinedUnits = new uint256[](combinedTokenArray.length);
        for (uint256 i = 0; i < combinedTokenArray.length; i++) {
            combinedUnits[i] = calculateCombinedUnit(
                _set,
                _auction.maxNaturalUnit,
                combinedTokenArray[i]
            );
        }

        return combinedUnits;
    }

    /**
     * Calculations the unit amount of Token to include in the the combined Set units.
     *
     * @param _setToken                 Information on the SetToken
     * @param _maxNaturalUnit           Max natural unit of two sets in rebalance
     * @param _component                Current component in iteration
     * @return                          Unit inflow/outflow
     */
    function calculateCombinedUnit(
        ISetToken _setToken,
        uint256 _maxNaturalUnit,
        address _component
    )
        private
        view
        returns (uint256)
    {
        // Check if component in arrays and get index if it is
        (
            uint256 indexCurrent,
            bool isComponent
        ) = _setToken.getComponents().indexOf(_component);

        // Compute unit amounts of token in Set
        if (isComponent) {
            return calculateTransferValue(
                _setToken.getUnits()[indexCurrent],
                _setToken.naturalUnit(),
                _maxNaturalUnit
            );
        }

        return 0;
    }

   /**
     * Function to calculate the transfer value of a component given a standardized bid amount
     * (minimumBid/priceDivisor)
     *
     * @param   _unit               Units of the component token
     * @param   _naturalUnit        Natural unit of the Set token
     * @param   _maxNaturalUnit     Max natural unit of two sets in rebalance
     * @return  uint256             Amount of tokens per standard bid amount (minimumBid/priceDivisor)
     */
    function calculateTransferValue(
        uint256 _unit,
        uint256 _naturalUnit,
        uint256 _maxNaturalUnit
    )
        private
        pure
        returns (uint256)
    {
        return SetMath.setToComponent(_maxNaturalUnit, _unit, _naturalUnit);
    }
}

// File: contracts/core/liquidators/impl/LinearAuction.sol

/*
    Copyright 2019 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;






/**
 * @title LinearAuction
 * @author Set Protocol
 *
 * Library containing utility functions for computing auction Price for a linear price auction.
 */
contract LinearAuction is Auction {
    using SafeMath for uint256;

    /* ============ Structs ============ */
    struct State {
        Auction.Setup auction;
        uint256 endTime;
        uint256 startPrice;
        uint256 endPrice;
    }

    /* ============ State Variables ============ */
    uint256 public auctionPeriod; // Length in seconds of auction

    /**
     * LinearAuction constructor
     *
     * @param _auctionPeriod          Length of auction
     */
    constructor(
        uint256 _auctionPeriod
    )
        public
    {
        auctionPeriod = _auctionPeriod;
    }

    /* ============ Internal Functions ============ */

    /**
     * Populates the linear auction struct following an auction initiation.
     *
     * @param _linearAuction                LinearAuction State object
     * @param _currentSet                   The Set to rebalance from
     * @param _nextSet                      The Set to rebalance to
     * @param _startingCurrentSetQuantity   Quantity of currentSet to rebalance
     */
    function initializeLinearAuction(
        State storage _linearAuction,
        ISetToken _currentSet,
        ISetToken _nextSet,
        uint256 _startingCurrentSetQuantity
    )
        internal
    {
        initializeAuction(
            _linearAuction.auction,
            _currentSet,
            _nextSet,
            _startingCurrentSetQuantity
        );

        uint256 minimumBid = calculateMinimumBid(_linearAuction.auction, _currentSet, _nextSet);

        // remainingCurrentSets must be greater than minimumBid or no bidding would be allowed
        require(
            _startingCurrentSetQuantity.div(minimumBid) >= 100,
            "Auction.initializeAuction: Minimum bid must be less than or equal to 1% of collateral."
        );

        _linearAuction.auction.minimumBid = minimumBid;

        _linearAuction.startPrice = calculateStartPrice(_linearAuction.auction, _currentSet, _nextSet);
        _linearAuction.endPrice = calculateEndPrice(_linearAuction.auction, _currentSet, _nextSet);

        _linearAuction.endTime = block.timestamp.add(auctionPeriod);
    }

    /* ============ Internal View Functions ============ */

    /**
     * Returns the TokenFlow based on the current price
     */
    function getTokenFlow(
        State storage _linearAuction,
        uint256 _quantity
    )
        internal
        view
        returns (Rebalance.TokenFlow memory)
    {
        return Auction.calculateTokenFlow(
            _linearAuction.auction,
            _quantity,
            getPrice(_linearAuction)
        );
    }

    /**
     * Auction failed is defined the timestamp breacnhing the auction end time and
     * the auction not being complete
     */
    function hasAuctionFailed(State storage _linearAuction) internal view returns(bool) {
        bool endTimeExceeded = block.timestamp >= _linearAuction.endTime;
        bool setsNotAuctioned = hasBiddableQuantity(_linearAuction.auction);

        return (endTimeExceeded && setsNotAuctioned);
    }

    /**
     * Returns the price based on the current timestamp. Returns the endPrice
     * if time has exceeded the auction period
     *
     * @param _linearAuction            Linear Auction State object
     * @return price                    uint representing the current price
     */
    function getPrice(State storage _linearAuction) internal view returns (uint256) {
        uint256 elapsed = block.timestamp.sub(_linearAuction.auction.startTime);

        // If current time has elapsed
        if (elapsed >= auctionPeriod) {
            return _linearAuction.endPrice;
        } else {
            uint256 range = _linearAuction.endPrice.sub(_linearAuction.startPrice);
            uint256 elapsedPrice = elapsed.mul(range).div(auctionPeriod);

            return _linearAuction.startPrice.add(elapsedPrice);
        }
    }

    /**
     * Abstract function that must be implemented.
     * Calculate the minimumBid allowed for the rebalance.
     *
     * @param _auction            Auction object
     * @param _currentSet         The Set to rebalance from
     * @param _nextSet            The Set to rebalance to
     * @return                    Minimum bid amount
     */
    function calculateMinimumBid(
        Setup storage _auction,
        ISetToken _currentSet,
        ISetToken _nextSet
    )
        internal
        view
        returns (uint256);

    /**
     * Abstract function that must be implemented.
     * Calculates the linear auction start price
     */
    function calculateStartPrice(
        Auction.Setup storage _auction,
        ISetToken _currentSet,
        ISetToken _nextSet
    )
        internal
        view
        returns(uint256);

    /**
     * Abstract function that must be implemented.
     * Calculates the linear auction end price
     */
    function calculateEndPrice(
        Auction.Setup storage _auction,
        ISetToken _currentSet,
        ISetToken _nextSet
    )
        internal
        view
        returns(uint256);
}

// File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol

pragma solidity ^0.5.2;

/**
 * @title ERC20 interface
 * @dev see https://eips.ethereum.org/EIPS/eip-20
 */
interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);

    function approve(address spender, uint256 value) external returns (bool);

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

    function totalSupply() external view returns (uint256);

    function balanceOf(address who) external view returns (uint256);

    function allowance(address owner, address spender) external view returns (uint256);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// File: openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol

pragma solidity ^0.5.2;


/**
 * @title ERC20Detailed token
 * @dev The decimals are only for visualization purposes.
 * All the operations are done using the smallest and indivisible token unit,
 * just as on Ethereum all the operations are done in wei.
 */
contract ERC20Detailed is IERC20 {
    string private _name;
    string private _symbol;
    uint8 private _decimals;

    constructor (string memory name, string memory symbol, uint8 decimals) public {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;
    }

    /**
     * @return the name of the token.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @return the symbol of the token.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @return the number of decimals of the token.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }
}

// File: contracts/lib/CommonMath.sol

/*
    Copyright 2018 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;



library CommonMath {
    using SafeMath for uint256;

    uint256 public constant SCALE_FACTOR = 10 ** 18;
    uint256 public constant MAX_UINT_256 = 2 ** 256 - 1;

    /**
     * Returns scale factor equal to 10 ** 18
     *
     * @return  10 ** 18
     */
    function scaleFactor()
        internal
        pure
        returns (uint256)
    {
        return SCALE_FACTOR;
    }

    /**
     * Calculates and returns the maximum value for a uint256
     *
     * @return  The maximum value for uint256
     */
    function maxUInt256()
        internal
        pure
        returns (uint256)
    {
        return MAX_UINT_256;
    }

    /**
     * Increases a value by the scale factor to allow for additional precision
     * during mathematical operations
     */
    function scale(
        uint256 a
    )
        internal
        pure
        returns (uint256)
    {
        return a.mul(SCALE_FACTOR);
    }

    /**
     * Divides a value by the scale factor to allow for additional precision
     * during mathematical operations
    */
    function deScale(
        uint256 a
    )
        internal
        pure
        returns (uint256)
    {
        return a.div(SCALE_FACTOR);
    }

    /**
    * @dev Performs the power on a specified value, reverts on overflow.
    */
    function safePower(
        uint256 a,
        uint256 pow
    )
        internal
        pure
        returns (uint256)
    {
        require(a > 0);

        uint256 result = 1;
        for (uint256 i = 0; i < pow; i++){
            uint256 previousResult = result;

            // Using safemath multiplication prevents overflows
            result = previousResult.mul(a);
        }

        return result;
    }

    /**
    * @dev Performs division where if there is a modulo, the value is rounded up
    */
    function divCeil(uint256 a, uint256 b)
        internal
        pure
        returns(uint256)
    {
        return a.mod(b) > 0 ? a.div(b).add(1) : a.div(b);
    }

    /**
     * Checks for rounding errors and returns value of potential partial amounts of a principal
     *
     * @param  _principal       Number fractional amount is derived from
     * @param  _numerator       Numerator of fraction
     * @param  _denominator     Denominator of fraction
     * @return uint256          Fractional amount of principal calculated
     */
    function getPartialAmount(
        uint256 _principal,
        uint256 _numerator,
        uint256 _denominator
    )
        internal
        pure
        returns (uint256)
    {
        // Get remainder of partial amount (if 0 not a partial amount)
        uint256 remainder = mulmod(_principal, _numerator, _denominator);

        // Return if not a partial amount
        if (remainder == 0) {
            return _principal.mul(_numerator).div(_denominator);
        }

        // Calculate error percentage
        uint256 errPercentageTimes1000000 = remainder.mul(1000000).div(_numerator.mul(_principal));

        // Require error percentage is less than 0.1%.
        require(
            errPercentageTimes1000000 < 1000,
            "CommonMath.getPartialAmount: Rounding error exceeds bounds"
        );

        return _principal.mul(_numerator).div(_denominator);
    }

    /*
     * Gets the rounded up log10 of passed value
     *
     * @param  _value         Value to calculate ceil(log()) on
     * @return uint256        Output value
     */
    function ceilLog10(
        uint256 _value
    )
        internal
        pure
        returns (uint256)
    {
        // Make sure passed value is greater than 0
        require (
            _value > 0,
            "CommonMath.ceilLog10: Value must be greater than zero."
        );

        // Since log10(1) = 0, if _value = 1 return 0
        if (_value == 1) return 0;

        // Calcualte ceil(log10())
        uint256 x = _value - 1;

        uint256 result = 0;

        if (x >= 10 ** 64) {
            x /= 10 ** 64;
            result += 64;
        }
        if (x >= 10 ** 32) {
            x /= 10 ** 32;
            result += 32;
        }
        if (x >= 10 ** 16) {
            x /= 10 ** 16;
            result += 16;
        }
        if (x >= 10 ** 8) {
            x /= 10 ** 8;
            result += 8;
        }
        if (x >= 10 ** 4) {
            x /= 10 ** 4;
            result += 4;
        }
        if (x >= 100) {
            x /= 100;
            result += 2;
        }
        if (x >= 10) {
            result += 1;
        }

        return result + 1;
    }
}

// File: contracts/core/liquidators/impl/TwoAssetPriceBoundedLinearAuction.sol

/*
    Copyright 2019 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;











/**
 * @title TwoAssetPriceBoundedLinearAuction
 * @author Set Protocol
 *
 * Contract to calculate minimumBid and auction start bounds for auctions containing only
 * an asset pair.
 */
contract TwoAssetPriceBoundedLinearAuction is LinearAuction {
    using SafeMath for uint256;
    using CommonMath for uint256;

    /* ============ Struct ============ */
    struct AssetInfo {
        uint256 price;
        uint256 fullUnit;
    }

    /* ============ Constants ============ */
    uint256 constant private CURVE_DENOMINATOR = 10 ** 18;
    uint256 constant private ONE = 1;
    // Minimum token flow allowed at spot price in auction
    uint256 constant private MIN_SPOT_TOKEN_FLOW_SCALED = 10 ** 21;
    uint256 constant private ONE_HUNDRED = 100;

    /* ============ State Variables ============ */
    IOracleWhiteList public oracleWhiteList;
    uint256 public rangeStart; // Percentage below FairValue to begin auction at
    uint256 public rangeEnd;  // Percentage above FairValue to end auction at

    /**
     * TwoAssetPriceBoundedLinearAuction constructor
     *
     * @param _auctionPeriod          Length of auction
     * @param _rangeStart             Percentage below FairValue to begin auction at
     * @param _rangeEnd               Percentage above FairValue to end auction at
     */
    constructor(
        IOracleWhiteList _oracleWhiteList,
        uint256 _auctionPeriod,
        uint256 _rangeStart,
        uint256 _rangeEnd
    )
        public
        LinearAuction(_auctionPeriod)
    {
        oracleWhiteList = _oracleWhiteList;
        rangeStart = _rangeStart;
        rangeEnd = _rangeEnd;
    }

    /* ============ Internal Functions ============ */

    /**
     * Validates that the auction only includes two components and the components are valid.
     */
    function validateTwoAssetPriceBoundedAuction(
        ISetToken _currentSet,
        ISetToken _nextSet
    )
        internal
        view
    {
        address[] memory combinedTokenArray = Auction.getCombinedTokenArray(_currentSet, _nextSet);
        require(
            combinedTokenArray.length == 2,
            "TwoAssetPriceBoundedLinearAuction: Only two components are allowed."
        );

        require(
            oracleWhiteList.areValidAddresses(combinedTokenArray),
            "TwoAssetPriceBoundedLinearAuction: Passed token does not have matching oracle."
        );
    }

    /**
     * Calculates the minimumBid. First calculates the minimum token flow for the pair at fair value using
     * maximum natural unit of two Sets. If that token flow is below 1000 units then calculate minimumBid
     * as such:
     *
     * minimumBid = maxNaturalUnit*1000/min(tokenFlow)
     *
     * Else, set minimumBid equal to maxNaturalUnit. This is to ensure that around fair value there is ample
     * granualarity in asset pair price changes and not large discontinuities.
     *
     * @param _auction            Auction object
     * @param _currentSet         CurrentSet, unused in this implementation
     * @param _nextSet            NextSet, unused in this implementation
     */
    function calculateMinimumBid(
        Auction.Setup storage _auction,
        ISetToken _currentSet,
        ISetToken _nextSet
    )
        internal
        view
        returns (uint256)
    {
        // Get full Unit amount and price for each asset
        AssetInfo memory assetOne = getAssetInfo(_auction.combinedTokenArray[0]);
        AssetInfo memory assetTwo = getAssetInfo(_auction.combinedTokenArray[1]);

        // Calculate current spot price as assetOne/assetTwo
        uint256 spotPrice = calculateSpotPrice(assetOne.price, assetTwo.price);

        // Calculate auction price at current asset pair spot price
        uint256 auctionFairValue = convertAssetPairPriceToAuctionPrice(
            _auction,
            spotPrice,
            assetOne.fullUnit,
            assetTwo.fullUnit
        );

        uint256 minimumBidMultiplier = 0;
        for (uint8 i = 0; i < _auction.combinedTokenArray.length; i++) {
            // Get token flow at fair value for asset i, using an amount equal to ONE maxNaturalUnit
            // Hence the ONE.scale()
            (
                uint256 tokenInflowScaled,
                uint256 tokenOutflowScaled
            ) = Auction.calculateInflowOutflow(
                _auction.combinedCurrentSetUnits[i],
                _auction.combinedNextSetUnits[i],
                ONE.scale(),
                auctionFairValue
            );

            // One returned number from previous function will be zero so use max to get tokenFlow
            uint256 tokenFlowScaled = Math.max(tokenInflowScaled, tokenOutflowScaled);

            // Divide minimum spot token flow (1000 units) by token flow if more than minimumBidMultiplier
            // update minimumBidMultiplier
            uint256 currentMinBidMultiplier = MIN_SPOT_TOKEN_FLOW_SCALED.divCeil(tokenFlowScaled);
            minimumBidMultiplier = currentMinBidMultiplier > minimumBidMultiplier ?
                currentMinBidMultiplier :
                minimumBidMultiplier;
        }

        // Multiply the minimumBidMultiplier by maxNaturalUnit to get minimumBid
        return _auction.maxNaturalUnit.mul(minimumBidMultiplier);
    }

    /**
     * Calculates the linear auction start price. A target asset pair (i.e. ETH/DAI) price is calculated
     * to start the auction at, that asset pair price is then translated into the equivalent auction price.
     *
     * @param _auction            Auction object
     * @param _currentSet         CurrentSet, unused in this implementation
     * @param _nextSet            NextSet, unused in this implementation
     */
    function calculateStartPrice(
        Auction.Setup storage _auction,
        ISetToken _currentSet,
        ISetToken _nextSet
    )
        internal
        view
        returns(uint256)
    {
        // Get full Unit amount and price for each asset
        AssetInfo memory assetOne = getAssetInfo(_auction.combinedTokenArray[0]);
        AssetInfo memory assetTwo = getAssetInfo(_auction.combinedTokenArray[1]);

        // Calculate current asset pair spot price as assetOne/assetTwo
        uint256 spotPrice = calculateSpotPrice(assetOne.price, assetTwo.price);

        // Check to see if asset pair price is increasing or decreasing as time passes
        bool isTokenFlowIncreasing = isTokenFlowIncreasing(
            _auction,
            spotPrice,
            assetOne.fullUnit,
            assetTwo.fullUnit
        );

        // If price implied by token flows is increasing then target price we are using for lower bound
        // is below current spot price, if flows decreasing set target price above spotPrice
        uint256 startPairPrice;
        if (isTokenFlowIncreasing) {
            startPairPrice = spotPrice.mul(ONE_HUNDRED.sub(rangeStart)).div(ONE_HUNDRED);
        } else {
            startPairPrice = spotPrice.mul(ONE_HUNDRED.add(rangeStart)).div(ONE_HUNDRED);
        }

        // Convert start asset pair price to equivalent auction price
        return convertAssetPairPriceToAuctionPrice(
            _auction,
            startPairPrice,
            assetOne.fullUnit,
            assetTwo.fullUnit
        );
    }

    /**
     * Calculates the linear auction end price. A target asset pair (i.e. ETH/DAI) price is calculated
     * to end the auction at, that asset pair price is then translated into the equivalent auction price.
     *
     * @param _auction            Auction object
     * @param _currentSet         CurrentSet, unused in this implementation
     * @param _nextSet            NextSet, unused in this implementation
     */
    function calculateEndPrice(
        Auction.Setup storage _auction,
        ISetToken _currentSet,
        ISetToken _nextSet
    )
        internal
        view
        returns(uint256)
    {
        // Get full Unit amount and price for each asset
        AssetInfo memory assetOne = getAssetInfo(_auction.combinedTokenArray[0]);
        AssetInfo memory assetTwo = getAssetInfo(_auction.combinedTokenArray[1]);

        // Calculate current spot price as assetOne/assetTwo
        uint256 spotPrice = calculateSpotPrice(assetOne.price, assetTwo.price);

        // Check to see if asset pair price is increasing or decreasing as time passes
        bool isTokenFlowIncreasing = isTokenFlowIncreasing(
            _auction,
            spotPrice,
            assetOne.fullUnit,
            assetTwo.fullUnit
        );

        // If price implied by token flows is increasing then target price we are using for upper bound
        // is above current spot price, if flows decreasing set target price below spotPrice
        uint256 endPairPrice;
        if (isTokenFlowIncreasing) {
            endPairPrice = spotPrice.mul(ONE_HUNDRED.add(rangeEnd)).div(ONE_HUNDRED);
        } else {
            endPairPrice = spotPrice.mul(ONE_HUNDRED.sub(rangeEnd)).div(ONE_HUNDRED);
        }

        // Convert end asset pair price to equivalent auction price
        return convertAssetPairPriceToAuctionPrice(
            _auction,
            endPairPrice,
            assetOne.fullUnit,
            assetTwo.fullUnit
        );
    }

    /* ============ Private Functions ============ */

    /**
     * Determines if asset pair price is increasing or decreasing as time passed in auction. Used to set the
     * auction price bounds. Below a refers to any asset and subscripts c, n, d mean currentSetUnit, nextSetUnit
     * and fullUnit amount, respectively. pP and pD refer to auction price and auction denominator. Asset pair
     * price is defined as such:
     *
     * assetPrice = abs(assetTwoOutflow/assetOneOutflow)
     *
     * The equation for an outflow is given by (a_c/a_d)*pP - (a_n/a_d)*pD). It can be proven that the derivative
     * of this equation is always increasing. Thus by determining the sign of the assetOneOutflow (where a negative
     * amount signifies an inflow) it can be determined whether the asset pair price is increasing or decreasing.
     *
     * For example, if assetOneOutflow is negative it means that the denominator is getting smaller as time passes
     * and thus the assetPrice is increasing during the auction.
     *
     * @param _auction              Auction object
     * @param _spotPrice            Current spot price provided by asset oracles
     * @param _assetOneFullUnit     Units in one full unit of assetOne
     * @param _assetTwoFullUnit     Units in one full unit of assetTwo
     */
    function isTokenFlowIncreasing(
        Auction.Setup storage _auction,
        uint256 _spotPrice,
        uint256 _assetOneFullUnit,
        uint256 _assetTwoFullUnit
    )
        private
        view
        returns (bool)
    {
        // Calculate auction price at current asset pair spot price
        uint256 auctionFairValue = convertAssetPairPriceToAuctionPrice(
            _auction,
            _spotPrice,
            _assetOneFullUnit,
            _assetTwoFullUnit
        );

        // Determine whether outflow for assetOne is positive or negative, if positive then asset pair price is
        // increasing, else decreasing.
        return _auction.combinedNextSetUnits[0].mul(CURVE_DENOMINATOR) >
            _auction.combinedCurrentSetUnits[0].mul(auctionFairValue);
    }

    /**
     * Convert an asset pair price to the equivalent auction price where a1 refers to assetOne and a2 refers to assetTwo
     * and subscripts c, n, d mean currentSetUnit, nextSetUnit and fullUnit amount, respectively. pP and pD refer to auction
     * price and auction denominator:
     *
     * assetPrice = abs(assetTwoOutflow/assetOneOutflow)
     *
     * assetPrice = ((a2_c/a2_d)*pP - (a2_n/a2_d)*pD) / ((a1_c/a1_d)*pP - (a1_n/a1_d)*pD)
     *
     * We know assetPrice so we isolate for pP:
     *
     * pP = pD((a2_n/a2_d)+assetPrice*(a1_n/a1_d)) / (a2_c/a2_d)+assetPrice*(a1_c/a1_d)
     *
     * This gives us the auction price that matches with the passed asset pair price.
     *
     * @param _auction              Auction object
     * @param _targetPrice          Target asset pair price
     * @param _assetOneFullUnit     Units in one full unit of assetOne
     * @param _assetTwoFullUnit     Units in one full unit of assetTwo
     */
    function convertAssetPairPriceToAuctionPrice(
        Auction.Setup storage _auction,
        uint256 _targetPrice,
        uint256 _assetOneFullUnit,
        uint256 _assetTwoFullUnit
    )
        private
        view
        returns (uint256)
    {
        // Calculate the numerator for the above equation. In order to ensure no rounding down errors we distribute the auction
        // denominator. Additionally, since the price is passed as an 18 decimal number in order to maintain consistency we
        // have to scale the first term up accordingly
        uint256 calcNumerator = _auction.combinedNextSetUnits[1].mul(CURVE_DENOMINATOR).scale().div(_assetTwoFullUnit).add(
            _targetPrice.mul(_auction.combinedNextSetUnits[0]).mul(CURVE_DENOMINATOR).div(_assetOneFullUnit)
        );

        // Calculate the denominator for the above equation. As above we we have to scale the first term match the 18 decimal
        // price. Furthermore since we are not guaranteed that targetPrice * a1_c > a1_d we have to scale the second term and
        // thus also the first term in order to match (hence the two scale() in the first term)
        uint256 calcDenominator = _auction.combinedCurrentSetUnits[1].scale().scale().div(_assetTwoFullUnit).add(
           _targetPrice.mul(_auction.combinedCurrentSetUnits[0]).scale().div(_assetOneFullUnit)
        );

        // Here the scale required to account for the 18 decimal price cancels out since it was applied to both the numerator
        // and denominator. However, there was an extra scale applied to the denominator that we need to remove, in order to
        // do so we'll just apply another scale to the numerator before dividing since 1/(1/10 ** 18) = 10 ** 18!
        return calcNumerator.scale().div(calcDenominator);
    }

    /**
     * Get fullUnit amount and price of given asset.
     *
     * @param _asset            Address of auction to get information from
     */
    function getAssetInfo(address _asset) private view returns(AssetInfo memory) {
        address assetOracle = oracleWhiteList.getOracleAddressByToken(_asset);
        uint256 assetPrice = IOracle(assetOracle).read();

        uint256 decimals = ERC20Detailed(_asset).decimals();

        return AssetInfo({
            price: assetPrice,
            fullUnit: CommonMath.safePower(10, decimals)
        });
    }

    /**
     * Calculate asset pair price given two prices.
     */
    function calculateSpotPrice(uint256 _assetOnePrice, uint256 _assetTwoPrice) private view returns(uint256) {
        return _assetOnePrice.scale().div(_assetTwoPrice);
    }
}

// File: contracts/core/liquidators/LinearAuctionLiquidator.sol

/*
    Copyright 2019 Set Labs Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

pragma solidity 0.5.7;
pragma experimental "ABIEncoderV2";












/**
 * @title LinearAuctionLiquidator
 * @author Set Protocol
 *
 * Contract that holds all the state and functionality required for setting up, returning prices, and tearing
 * down linear auction rebalances for RebalancingSetTokens.
 */
contract LinearAuctionLiquidator is TwoAssetPriceBoundedLinearAuction, ILiquidator {
    using SafeMath for uint256;

    ICore public core;
    string public name;
    mapping(address => LinearAuction.State) public auctions;

    /* ============ Modifier ============ */
    modifier isValidSet() {
        requireValidSet(msg.sender);
        _;
    }

    /**
     * LinearAuctionLiquidator constructor
     *
     * @param _core                   Core instance
     * @param _oracleWhiteList        Oracle WhiteList instance
     * @param _auctionPeriod          Length of auction
     * @param _rangeStart             Percentage above FairValue to begin auction at
     * @param _rangeEnd               Percentage below FairValue to end auction at
     * @param _name                   Descriptive name of Liquidator
     */
    constructor(
        ICore _core,
        IOracleWhiteList _oracleWhiteList,
        uint256 _auctionPeriod,
        uint256 _rangeStart,
        uint256 _rangeEnd,
        string memory _name
    )
        public
        TwoAssetPriceBoundedLinearAuction(
            _oracleWhiteList,
            _auctionPeriod,
            _rangeStart,
            _rangeEnd
        )
    {
        core = _core;
        name = _name;
    }

    /* ============ External Functions ============ */

    /**
     * Initiates a linear auction. Can only be called by a SetToken.
     *
     * @param _currentSet                   The Set to rebalance from
     * @param _nextSet                      The Set to rebalance to
     * @param _startingCurrentSetQuantity   The currentSet quantity to rebalance
     * @param _liquidatorData                  Bytecode formatted data with liquidator-specific arguments
     */
    function startRebalance(
        ISetToken _currentSet,
        ISetToken _nextSet,
        uint256 _startingCurrentSetQuantity,
        bytes calldata _liquidatorData
    )
        external
        isValidSet
    {
        _liquidatorData; // Pass linting

        TwoAssetPriceBoundedLinearAuction.validateTwoAssetPriceBoundedAuction(
            _currentSet,
            _nextSet
        );

        LinearAuction.initializeLinearAuction(
            linearAuction(msg.sender),
            _currentSet,
            _nextSet,
            _startingCurrentSetQuantity
        );
    }

    /**
     * Reduces the remainingCurrentSet quantity and retrieves the current
     * bid price.
     * Can only be called by a SetToken during an active auction
     *
     * @param _quantity               The currentSetQuantity to rebalance
     * @return TokenFlow              Struct with array, inflow, and outflow data
     */
    function placeBid(
        uint256 _quantity
    )
        external
        isValidSet
        returns (Rebalance.TokenFlow memory)
    {
        Auction.validateBidQuantity(auction(msg.sender), _quantity);

        Auction.reduceRemainingCurrentSets(auction(msg.sender), _quantity);

        return getBidPrice(msg.sender, _quantity);
    }

    /**
     * Retrieves the current auction price for the particular Set
     *
     * @param _set                    Address of the SetToken
     * @param _quantity               The currentSetQuantity to rebalance
     * @return TokenFlow              Struct with array, inflow, and outflow data
     */
    function getBidPrice(
        address _set,
        uint256 _quantity
    )
        public
        view
        returns (Rebalance.TokenFlow memory)
    {
        return LinearAuction.getTokenFlow(linearAuction(_set), _quantity);
    }

    /**
     * Validates auction completion and clears auction state.
     */
    function settleRebalance() external isValidSet {

        Auction.validateAuctionCompletion(auction(msg.sender));

        clearAuctionState(msg.sender);
    }

    /**
     * Clears auction state.
     */
    function endFailedRebalance() external isValidSet {

        clearAuctionState(msg.sender);
    }

    /* ============ Getters Functions ============ */

    function hasRebalanceFailed(address _set) external view returns (bool) {
        return LinearAuction.hasAuctionFailed(linearAuction(_set));
    }

    function minimumBid(address _set) external view returns (uint256) {
        return auction(_set).minimumBid;
    }

    function remainingCurrentSets(address _set) external view returns (uint256) {
        return auction(_set).remainingCurrentSets;
    }

    function startingCurrentSets(address _set) external view returns (uint256) {
        return auction(_set).startingCurrentSets;
    }

    function getCombinedTokenArray(address _set) external view returns (address[] memory) {
        return auction(_set).combinedTokenArray;
    }

    function getCombinedCurrentSetUnits(address _set) external view returns (uint256[] memory) {
        return auction(_set).combinedCurrentSetUnits;
    }

    function getCombinedNextSetUnits(address _set) external view returns (uint256[] memory) {
        return auction(_set).combinedNextSetUnits;
    }

    function auctionPriceParameters(address _set)
        external
        view
        returns (RebalancingLibrary.AuctionPriceParameters memory)
    {
        return RebalancingLibrary.AuctionPriceParameters({
            auctionStartTime: auction(_set).startTime,
            auctionTimeToPivot: auctionPeriod,
            auctionStartPrice: linearAuction(_set).startPrice,
            auctionPivotPrice: linearAuction(_set).endPrice
        });
    }

    /* ============ Private Functions ============ */

    function clearAuctionState(address _set) private {
        delete auctions[_set];
    }

    function auction(address _set) private view returns(Auction.Setup storage) {
        return linearAuction(_set).auction;
    }

    function linearAuction(address _set) private view returns(LinearAuction.State storage) {
        return auctions[_set];
    }

    function requireValidSet(address _set) private view {
        require(
            core.validSets(_set),
            "LinearAuctionLiquidator: Invalid or disabled proposed SetToken address"
        );
    }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"name":"_set","type":"address"}],"name":"minimumBid","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"auctionPeriod","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_set","type":"address"},{"name":"_quantity","type":"uint256"}],"name":"getBidPrice","outputs":[{"components":[{"name":"addresses","type":"address[]"},{"name":"inflow","type":"uint256[]"},{"name":"outflow","type":"uint256[]"}],"name":"","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_set","type":"address"}],"name":"getCombinedCurrentSetUnits","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"auctions","outputs":[{"components":[{"name":"maxNaturalUnit","type":"uint256"},{"name":"minimumBid","type":"uint256"},{"name":"startTime","type":"uint256"},{"name":"startingCurrentSets","type":"uint256"},{"name":"remainingCurrentSets","type":"uint256"},{"name":"combinedTokenArray","type":"address[]"},{"name":"combinedCurrentSetUnits","type":"uint256[]"},{"name":"combinedNextSetUnits","type":"uint256[]"}],"name":"auction","type":"tuple"},{"name":"endTime","type":"uint256"},{"name":"startPrice","type":"uint256"},{"name":"endPrice","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_set","type":"address"}],"name":"getCombinedNextSetUnits","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_set","type":"address"}],"name":"hasRebalanceFailed","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_set","type":"address"}],"name":"remainingCurrentSets","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_set","type":"address"}],"name":"auctionPriceParameters","outputs":[{"components":[{"name":"auctionStartTime","type":"uint256"},{"name":"auctionTimeToPivot","type":"uint256"},{"name":"auctionStartPrice","type":"uint256"},{"name":"auctionPivotPrice","type":"uint256"}],"name":"","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_set","type":"address"}],"name":"startingCurrentSets","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rangeEnd","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_set","type":"address"}],"name":"getCombinedTokenArray","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rangeStart","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"endFailedRebalance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_quantity","type":"uint256"}],"name":"placeBid","outputs":[{"components":[{"name":"addresses","type":"address[]"},{"name":"inflow","type":"uint256[]"},{"name":"outflow","type":"uint256[]"}],"name":"","type":"tuple"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"oracleWhiteList","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"core","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"settleRebalance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_currentSet","type":"address"},{"name":"_nextSet","type":"address"},{"name":"_startingCurrentSetQuantity","type":"uint256"},{"name":"_liquidatorData","type":"bytes"}],"name":"startRebalance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_core","type":"address"},{"name":"_oracleWhiteList","type":"address"},{"name":"_auctionPeriod","type":"uint256"},{"name":"_rangeStart","type":"uint256"},{"name":"_rangeEnd","type":"uint256"},{"name":"_name","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]

60806040523480156200001157600080fd5b5060405162002f6638038062002f668339810180604052620000379190810190620001bc565b600084905560018054600160a060020a03808816600160a060020a03199283161790925560028590556003849055600480549289169290911691909117905580516200008b90600590602084019062000098565b5050505050505062000316565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000db57805160ff19168380011785556200010b565b828001600101855582156200010b579182015b828111156200010b578251825591602001919060010190620000ee565b50620001199291506200011d565b5090565b6200013a91905b8082111562000119576000815560010162000124565b90565b60006200014b8251620002ca565b9392505050565b600082601f8301126200016457600080fd5b81516200017b62000175826200028f565b62000268565b915080825260208301602083018583830111156200019857600080fd5b620001a5838284620002e3565b50505092915050565b60006200014b82516200013a565b60008060008060008060c08789031215620001d657600080fd5b6000620001e489896200013d565b9650506020620001f789828a016200013d565b95505060406200020a89828a01620001ae565b94505060606200021d89828a01620001ae565b93505060806200023089828a01620001ae565b92505060a08701516001604060020a038111156200024d57600080fd5b6200025b89828a0162000152565b9150509295509295509295565b6040518181016001604060020a03811182821017156200028757600080fd5b604052919050565b60006001604060020a03821115620002a657600080fd5b506020601f91909101601f19160190565b6000620002c482620002d7565b92915050565b6000620002c482620002b7565b600160a060020a031690565b60005b8381101562000300578181015183820152602001620002e6565b8381111562000310576000848401525b50505050565b612c4080620003266000396000f3fe608060405234801561001057600080fd5b50600436106101305760003560e060020a9004806357dc13ec116100b15780639979ef45116100755780639979ef4514610291578063aa6f6082146102a4578063f2f4eb26146102b9578063fa2d8c90146102c1578063ffd9cc35146102c957610130565b806357dc13ec146102445780635c99ee011461025757806377b7a8d81461025f5780637920c1271461027f5780638a411b761461028757610130565b80631d59410a116100f85780631d59410a146101bb57806322c1107a146101de5780633b52de3b146101f15780634845443314610211578063558a7c061461022457610130565b8063060f02031461013557806306fdde031461015e5780630cccfc5814610173578063102d32c01461017b5780631273a6661461019b575b600080fd5b61014861014336600461220c565b6102dc565b6040516101559190612b3a565b60405180910390f35b6101666102f3565b6040516101559190612a60565b610148610381565b61018e610189366004612248565b610387565b6040516101559190612b29565b6101ae6101a936600461220c565b6103aa565b6040516101559190612a33565b6101ce6101c936600461220c565b61040e565b6040516101559493929190612aef565b6101ae6101ec36600461220c565b61057e565b6102046101ff36600461220c565b6105e0565b6040516101559190612a44565b61014861021f36600461220c565b6105f3565b61023761023236600461220c565b610608565b6040516101559190612ae1565b61014861025236600461220c565b61065c565b610148610671565b61027261026d36600461220c565b610677565b6040516101559190612a22565b6101486106e4565b61028f6106ea565b005b61018e61029f366004612388565b6106fe565b6102ac61073d565b6040516101559190612a52565b6102ac61074c565b61028f61075b565b61028f6102d736600461230a565b610775565b60006102e7826107a3565b6001015490505b919050565b6005805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103795780601f1061034e57610100808354040283529160200191610379565b820191906000526020600020905b81548152906001019060200180831161035c57829003601f168201915b505050505081565b60005481565b61038f611eff565b6103a161039b846107aa565b836107c4565b90505b92915050565b60606103b5826107a3565b60060180548060200260200160405190810160405280929190818152602001828054801561040257602002820191906000526020600020905b8154815260200190600101908083116103ee575b50505050509050919050565b60066020908152600091825260409182902082516101008101845281548152600182015481840152600282015481850152600382015460608201526004820154608082015260058201805485518186028101860190965280865292949193859360a086019392918301828280156104ae57602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610490575b505050505081526020016006820180548060200260200160405190810160405280929190818152602001828054801561050657602002820191906000526020600020905b8154815260200190600101908083116104f2575b505050505081526020016007820180548060200260200160405190810160405280929190818152602001828054801561055e57602002820191906000526020600020905b81548152602001906001019080831161054a575b5050505050815250509080600801549080600901549080600a0154905084565b6060610589826107a3565b60070180548060200260200160405190810160405280929190818152602001828054801561040257602002820191906000526020600020908154815260200190600101908083116103ee5750505050509050919050565b60006103a46105ee836107aa565b6107df565b60006105fe826107a3565b6004015492915050565b610610611f20565b6040518060800160405280610624846107a3565b600201548152602001600054815260200161063e846107aa565b600901548152602001610650846107aa565b600a0154905292915050565b6000610667826107a3565b6003015492915050565b60035481565b6060610682826107a3565b60050180548060200260200160405190810160405280929190818152602001828054801561040257602002820191906000526020600020905b8154600160a060020a031681526001909101906020018083116106bb5750505050509050919050565b60025481565b6106f333610808565b6106fc336108cb565b565b610706611eff565b61070f33610808565b61072161071b336107a3565b8361094d565b61073361072d336107a3565b836109ae565b6103a43383610387565b600154600160a060020a031681565b600454600160a060020a031681565b61076433610808565b6106f3610770336107a3565b6109cf565b61077e33610808565b61078885856109f8565b61079c610794336107aa565b868686610ae7565b5050505050565b60006103a4825b600160a060020a0316600090815260066020526040902090565b6107cc611eff565b6103a183836107da82610b7f565b610c19565b6008810154600090421015816107f484610d98565b90508180156108005750805b949350505050565b600480546040517ffef3ee73000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163fef3ee739161085091859101612a14565b60206040518083038186803b15801561086857600080fd5b505afa15801561087c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108a091908101906122ec565b6108c85760405160e560020a62461bcd0281526004016108bf90612a91565b60405180910390fd5b50565b600160a060020a0381166000908152600660205260408120818155600181018290556002810182905560038101829055600481018290559081816109126005830182611f48565b610920600683016000611f48565b61092e600783016000611f48565b505060088201600090556009820160009055600a820160009055505050565b600182015461096390829063ffffffff610da816565b156109835760405160e560020a62461bcd0281526004016108bf90612ab1565b81600401548111156109aa5760405160e560020a62461bcd0281526004016108bf90612a71565b5050565b60048201546109c3908263ffffffff610dc516565b82600401819055505050565b6109d881610d98565b156108c85760405160e560020a62461bcd0281526004016108bf90612ad1565b6060610a048383610dda565b90508051600214610a2a5760405160e560020a62461bcd0281526004016108bf90612a81565b6001546040517f32ed010e000000000000000000000000000000000000000000000000000000008152600160a060020a03909116906332ed010e90610a73908490600401612a22565b60206040518083038186803b158015610a8b57600080fd5b505afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ac391908101906122ec565b610ae25760405160e560020a62461bcd0281526004016108bf90612aa1565b505050565b610af384848484610eec565b6000610b00858585611054565b90506064610b14838363ffffffff61119e16565b1015610b355760405160e560020a62461bcd0281526004016108bf90612ac1565b60018501819055610b478585856111c0565b6009860155610b57858585611299565b600a860155600054610b7090429063ffffffff61134716565b85600801819055505050505050565b60028101546000908190610b9a90429063ffffffff610dc516565b90506000548110610bb1575050600a8101546102ee565b6000610bce846009015485600a0154610dc590919063ffffffff16565b90506000610bf7600054610beb848661135990919063ffffffff16565b9063ffffffff61119e16565b6009860154909150610c0f908263ffffffff61134716565b93505050506102ee565b610c21611eff565b8354600090610c3790859063ffffffff61119e16565b9050606085600501805480602002602001604051908101604052809291908181526020018280548015610c9357602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610c75575b50505050509050600081519050606081604051908082528060200260200182016040528015610ccc578160200160208202803883390190505b509050606082604051908082528060200260200182016040528015610cfb578160200160208202803883390190505b50905060005b83811015610d7d57610d478a6006018281548110610d1b57fe5b90600052602060002001548b6007018381548110610d3557fe5b9060005260206000200154888b611380565b848381518110610d5357fe5b60200260200101848481518110610d6657fe5b602090810291909101019190915252600101610d01565b50610d8984838361144f565b955050505050505b9392505050565b6001810154600490910154101590565b600081610db457600080fd5b818381610dbd57fe5b069392505050565b600082821115610dd457600080fd5b50900390565b60608083600160a060020a03166399d50d5d6040518163ffffffff1660e060020a02815260040160006040518083038186803b158015610e1957600080fd5b505afa158015610e2d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e559190810190612282565b9050606083600160a060020a03166399d50d5d6040518163ffffffff1660e060020a02815260040160006040518083038186803b158015610e9557600080fd5b505afa158015610ea9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ed19190810190612282565b9050610ee3828263ffffffff61147416565b95945050505050565b610fdc83600160a060020a03166342a7cfd56040518163ffffffff1660e060020a02815260040160206040518083038186803b158015610f2b57600080fd5b505afa158015610f3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f6391908101906123a6565b83600160a060020a03166342a7cfd56040518163ffffffff1660e060020a02815260040160206040518083038186803b158015610f9f57600080fd5b505afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610fd791908101906123a6565b6114bc565b84556003840181905560048401819055426002850155610ffc8383610dda565b8051611012916005870191602090910190611f66565b5061101d84846114d3565b8051611033916006870191602090910190611fd8565b5061103e84836114d3565b805161079c916007870191602090910190611fd8565b600061105e61201f565b61108b8560050160008154811061107157fe5b600091825260209091200154600160a060020a03166115bb565b905061109561201f565b6110a88660050160018154811061107157fe5b905060006110be83600001518360000151611779565b905060006110d6888386602001518660200151611788565b90506000805b60058a015460ff8216101561118b5760008061113b8c6006018460ff168154811061110357fe5b90600052602060002001548d6007018560ff168154811061112057fe5b90600052602060002001546111356001611889565b88611380565b91509150600061114b83836114bc565b90506000611168683635c9adc5dea000008363ffffffff6118a316565b90508581116111775785611179565b805b955050600190930192506110dc915050565b508854610d89908263ffffffff61135916565b60008082116111ac57600080fd5b60008284816111b757fe5b04949350505050565b60006111ca61201f565b6111dd8560050160008154811061107157fe5b90506111e761201f565b6111fa8660050160018154811061107157fe5b9050600061121083600001518360000151611779565b905060006112288883866020015186602001516118e5565b9050600081156112645761125d6064610beb6112506002546064610dc590919063ffffffff16565b869063ffffffff61135916565b9050611285565b6112826064610beb611250600254606461134790919063ffffffff16565b90505b610d89898287602001518760200151611788565b60006112a361201f565b6112b68560050160008154811061107157fe5b90506112c061201f565b6112d38660050160018154811061107157fe5b905060006112e983600001518360000151611779565b905060006113018883866020015186602001516118e5565b9050600081156113295761125d6064610beb611250600354606461134790919063ffffffff16565b6112826064610beb6112506003546064610dc590919063ffffffff16565b6000828201838110156103a157600080fd5b600082611368575060006103a4565b8282028284828161137557fe5b04146103a157600080fd5b6000808080611395888663ffffffff61135916565b6113ad88670de0b6b3a764000063ffffffff61135916565b1115611409576113fe85610beb6113f16113cd8c8463ffffffff61135916565b6113e58c670de0b6b3a764000063ffffffff61135916565b9063ffffffff610dc516565b899063ffffffff61135916565b915060009050611442565b61143b85610beb6113f161142b8b670de0b6b3a764000063ffffffff61135916565b6113e58d8b63ffffffff61135916565b9050600091505b9097909650945050505050565b611457611eff565b506040805160608101825293845260208401929092529082015290565b6060806114818484611931565b9050606061148f8486611931565b9050606061149d8686611a71565b90506114b2836114ad8385611b9f565b611b9f565b9695505050505050565b6000818310156114cc57816103a1565b5090919050565b6060808360050180548060200260200160405190810160405280929190818152602001828054801561152e57602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311611510575b5050505050905060608151604051908082528060200260200182016040528015611562578160200160208202803883390190505b50905060005b82518110156115b25761159385876000015485848151811061158657fe5b6020026020010151611c81565b82828151811061159f57fe5b6020908102919091010152600101611568565b50949350505050565b6115c361201f565b6001546040517f39477363000000000000000000000000000000000000000000000000000000008152600091600160a060020a03169063394773639061160d908690600401612a14565b60206040518083038186803b15801561162557600080fd5b505afa158015611639573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061165d919081019061222a565b9050600081600160a060020a03166357de26a46040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561169d57600080fd5b505afa1580156116b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116d591908101906123a6565b9050600084600160a060020a031663313ce5676040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561171557600080fd5b505afa158015611729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061174d91908101906123c4565b60ff169050604051806040016040528083815260200161176e600a84611e35565b905295945050505050565b60006103a182610beb85611889565b6000806118246117d785610beb670de0b6b3a76400006117cb8b6007016000815481106117b157fe5b90600052602060002001548b61135990919063ffffffff16565b9063ffffffff61135916565b61181885610beb611813670de0b6b3a76400008c6007016001815481106117fa57fe5b906000526020600020015461135990919063ffffffff16565b611889565b9063ffffffff61134716565b9050600061186f61184586610beb6118138b6006016000815481106117b157fe5b61181886610beb6118138c60060160018154811061185f57fe5b9060005260206000200154611889565b905061187e81610beb84611889565b979650505050505050565b60006103a482670de0b6b3a764000063ffffffff61135916565b6000806118b6848463ffffffff610da816565b116118d0576118cb838363ffffffff61119e16565b6103a1565b6103a16001611818858563ffffffff61119e16565b6000806118f486868686611788565b905061190a81876006016000815481106117fa57fe5b611926670de0b6b3a7640000886007016000815481106117fa57fe5b119695505050505050565b6060600083519050606081604051908082528060200260200182016040528015611965578160200160208202803883390190505b5090506000805b838110156119c857600087828151811061198257fe5b602002602001015190506119968782611e74565b6119bf5760018483815181106119a857fe5b911515602092830291909101909101526001909201915b5060010161196c565b506060816040519080825280602002602001820160405280156119f5578160200160208202803883390190505b5090506000805b85811015611a6457848181518110611a1057fe5b602002602001015115611a5c57888181518110611a2957fe5b6020026020010151838381518110611a3d57fe5b600160a060020a03909216602092830291909101909101526001909101905b6001016119fc565b5090979650505050505050565b6060600083519050606081604051908082528060200260200182016040528015611aa5578160200160208202803883390190505b5090506000805b83811015611b0357611ad186888381518110611ac457fe5b6020026020010151611e74565b15611afb576001838281518110611ae457fe5b911515602092830291909101909101526001909101905b600101611aac565b50606081604051908082528060200260200182016040528015611b30578160200160208202803883390190505b5090506000805b85811015611a6457848181518110611b4b57fe5b602002602001015115611b9757888181518110611b6457fe5b6020026020010151838381518110611b7857fe5b600160a060020a03909216602092830291909101909101526001909101905b600101611b37565b60606000835190506000835190506060818301604051908082528060200260200182016040528015611bdb578160200160208202803883390190505b50905060005b83811015611c2957868181518110611bf557fe5b6020026020010151828281518110611c0957fe5b600160a060020a0390921660209283029190910190910152600101611be1565b5060005b82811015611c7757858181518110611c4157fe5b60200260200101518282860181518110611c5757fe5b600160a060020a0390921660209283029190910190910152600101611c2d565b5095945050505050565b6000806000611d0e8487600160a060020a03166399d50d5d6040518163ffffffff1660e060020a02815260040160006040518083038186803b158015611cc657600080fd5b505afa158015611cda573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d029190810190612282565b9063ffffffff611e7d16565b915091508015611e2957611e2086600160a060020a031663027aa9f56040518163ffffffff1660e060020a02815260040160006040518083038186803b158015611d5757600080fd5b505afa158015611d6b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d9391908101906122b7565b8381518110611d9e57fe5b602002602001015187600160a060020a03166342a7cfd56040518163ffffffff1660e060020a02815260040160206040518083038186803b158015611de257600080fd5b505afa158015611df6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611e1a91908101906123a6565b87611ee1565b92505050610d91565b50600095945050505050565b6000808311611e4357600080fd5b600160005b83811015611e6c5781611e61818763ffffffff61135916565b925050600101611e48565b509392505050565b600080610ee384845b81516000908190815b81811015611ed05784600160a060020a0316868281518110611ea457fe5b6020026020010151600160a060020a03161415611ec857925060019150611eda9050565b600101611e86565b5060009250829150505b9250929050565b6000610800828585600061080082610beb868663ffffffff61135916565b60405180606001604052806060815260200160608152602001606081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b50805460008255906000526020600020908101906108c89190612039565b828054828255906000526020600020908101928215611fc8579160200282015b82811115611fc8578251825473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909116178255602090920191600190910190611f86565b50611fd4929150612056565b5090565b828054828255906000526020600020908101928215612013579160200282015b82811115612013578251825591602001919060010190611ff8565b50611fd4929150612039565b604051806040016040528060008152602001600081525090565b61205391905b80821115611fd4576000815560010161203f565b90565b61205391905b80821115611fd457805473ffffffffffffffffffffffffffffffffffffffff1916815560010161205c565b60006103a18235612ba3565b60006103a18251612ba3565b600082601f8301126120b057600080fd5b81516120c36120be82612b6f565b612b48565b915081818352602084019350602081019050838560208402820111156120e857600080fd5b60005b8381101561211457816120fe8882612093565b84525060209283019291909101906001016120eb565b5050505092915050565b600082601f83011261212f57600080fd5b815161213d6120be82612b6f565b9150818183526020840193506020810190508385602084028201111561216257600080fd5b60005b83811015612114578161217888826121f4565b8452506020928301929190910190600101612165565b60006103a18251612bae565b60008083601f8401126121ac57600080fd5b50813567ffffffffffffffff8111156121c457600080fd5b602083019150836001820283011115611eda57600080fd5b60006103a18235612bbf565b60006103a18235612053565b60006103a18251612053565b60006103a18251612bca565b60006020828403121561221e57600080fd5b60006108008484612087565b60006020828403121561223c57600080fd5b60006108008484612093565b6000806040838503121561225b57600080fd5b60006122678585612087565b9250506020612278858286016121e8565b9150509250929050565b60006020828403121561229457600080fd5b815167ffffffffffffffff8111156122ab57600080fd5b6108008482850161209f565b6000602082840312156122c957600080fd5b815167ffffffffffffffff8111156122e057600080fd5b6108008482850161211e565b6000602082840312156122fe57600080fd5b6000610800848461218e565b60008060008060006080868803121561232257600080fd5b600061232e88886121dc565b955050602061233f888289016121dc565b9450506040612350888289016121e8565b935050606086013567ffffffffffffffff81111561236d57600080fd5b6123798882890161219a565b92509250509295509295909350565b60006020828403121561239a57600080fd5b600061080084846121e8565b6000602082840312156123b857600080fd5b600061080084846121f4565b6000602082840312156123d657600080fd5b60006108008484612200565b60006123ee8383612402565b505060200190565b60006123ee8383612a0b565b61240b81612ba3565b82525050565b600061241c82612b96565b6124268185612b9a565b935061243183612b90565b60005b8281101561245c576124478683516123e2565b955061245282612b90565b9150600101612434565b5093949350505050565b600061247182612b96565b61247b8185612b9a565b935061248683612b90565b60005b8281101561245c5761249c8683516123e2565b95506124a782612b90565b9150600101612489565b60006124bc82612b96565b6124c68185612b9a565b93506124d183612b90565b60005b8281101561245c576124e78683516123f6565b95506124f282612b90565b91506001016124d4565b600061250782612b96565b6125118185612b9a565b935061251c83612b90565b60005b8281101561245c576125328683516123f6565b955061253d82612b90565b915060010161251f565b61240b81612bae565b61240b81612bbf565b600061256482612b96565b61256e8185612b9a565b935061257e818560208601612bd0565b61258781612bfc565b9093019392505050565b600061259e603f83612b9a565b7f41756374696f6e2e76616c69646174654269645175616e746974793a2042696481527f20657863656564732072656d61696e696e672063757272656e74207365747300602082015260400192915050565b60006125fd604383612b9a565b7f54776f41737365745072696365426f756e6465644c696e65617241756374696f81527f6e3a204f6e6c792074776f20636f6d706f6e656e74732061726520616c6c6f7760208201527f65642e0000000000000000000000000000000000000000000000000000000000604082015260600192915050565b6000612682604683612b9a565b7f4c696e65617241756374696f6e4c697175696461746f723a20496e76616c696481527f206f722064697361626c65642070726f706f73656420536574546f6b656e206160208201527f6464726573730000000000000000000000000000000000000000000000000000604082015260600192915050565b6000612707604e83612b9a565b7f54776f41737365745072696365426f756e6465644c696e65617241756374696f81527f6e3a2050617373656420746f6b656e20646f6573206e6f742068617665206d6160208201527f746368696e67206f7261636c652e000000000000000000000000000000000000604082015260600192915050565b600061278c603d83612b9a565b7f41756374696f6e2e76616c69646174654269645175616e746974793a204d757381527f7420626964206d756c7469706c65206f66206d696e696d756d20626964000000602082015260400192915050565b60006127eb605683612b9a565b7f41756374696f6e2e696e697469616c697a6541756374696f6e3a204d696e696d81527f756d20626964206d757374206265206c657373207468616e206f72206571756160208201527f6c20746f203125206f6620636f6c6c61746572616c2e00000000000000000000604082015260600192915050565b6000612870603083612b9a565b7f41756374696f6e2e736574746c65526562616c616e63653a20526562616c616e81527f6365206e6f7420636f6d706c6574656400000000000000000000000000000000602082015260400192915050565b805160808301906128d38482612a0b565b5060208201516128e66020850182612a0b565b5060408201516128f96040850182612a0b565b50606082015161290c6060850182612a0b565b50505050565b80516000906101008401906129278582612a0b565b50602083015161293a6020860182612a0b565b50604083015161294d6040860182612a0b565b5060608301516129606060860182612a0b565b5060808301516129736080860182612a0b565b5060a083015184820360a086015261298b8282612466565b91505060c083015184820360c08601526129a582826124fc565b91505060e083015184820360e0860152610ee382826124fc565b80516060808452600091908401906129d78282612466565b915050602083015184820360208601526129f182826124fc565b91505060408301518482036040860152610ee382826124fc565b61240b81612053565b602081016103a48284612402565b602080825281016103a18184612411565b602080825281016103a181846124b1565b602081016103a48284612547565b602081016103a48284612550565b602080825281016103a18184612559565b602080825281016103a481612591565b602080825281016103a4816125f0565b602080825281016103a481612675565b602080825281016103a4816126fa565b602080825281016103a48161277f565b602080825281016103a4816127de565b602080825281016103a481612863565b608081016103a482846128c2565b60808082528101612b008187612912565b9050612b0f6020830186612a0b565b612b1c6040830185612a0b565b610ee36060830184612a0b565b602080825281016103a181846129bf565b602081016103a48284612a0b565b60405181810167ffffffffffffffff81118282101715612b6757600080fd5b604052919050565b600067ffffffffffffffff821115612b8657600080fd5b5060209081020190565b60200190565b5190565b90815260200190565b60006103a482612bb3565b151590565b600160a060020a031690565b60006103a482612ba3565b60ff1690565b60005b83811015612beb578181015183820152602001612bd3565b8381111561290c5750506000910152565b601f01601f19169056fea265627a7a723058206d3467f1279a9b6072a74dcc80c2220e7a85372e3fe0138c772af4aa2aa143e86c6578706572696d656e74616cf50037000000000000000000000000f55186cc537e7067ea616f2aae007b4427a120c80000000000000000000000003e6cfdd0255bc69607cefefbc1029a328a982fb600000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000174c696e65617241756374696f6e4c697175696461746f72000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101305760003560e060020a9004806357dc13ec116100b15780639979ef45116100755780639979ef4514610291578063aa6f6082146102a4578063f2f4eb26146102b9578063fa2d8c90146102c1578063ffd9cc35146102c957610130565b806357dc13ec146102445780635c99ee011461025757806377b7a8d81461025f5780637920c1271461027f5780638a411b761461028757610130565b80631d59410a116100f85780631d59410a146101bb57806322c1107a146101de5780633b52de3b146101f15780634845443314610211578063558a7c061461022457610130565b8063060f02031461013557806306fdde031461015e5780630cccfc5814610173578063102d32c01461017b5780631273a6661461019b575b600080fd5b61014861014336600461220c565b6102dc565b6040516101559190612b3a565b60405180910390f35b6101666102f3565b6040516101559190612a60565b610148610381565b61018e610189366004612248565b610387565b6040516101559190612b29565b6101ae6101a936600461220c565b6103aa565b6040516101559190612a33565b6101ce6101c936600461220c565b61040e565b6040516101559493929190612aef565b6101ae6101ec36600461220c565b61057e565b6102046101ff36600461220c565b6105e0565b6040516101559190612a44565b61014861021f36600461220c565b6105f3565b61023761023236600461220c565b610608565b6040516101559190612ae1565b61014861025236600461220c565b61065c565b610148610671565b61027261026d36600461220c565b610677565b6040516101559190612a22565b6101486106e4565b61028f6106ea565b005b61018e61029f366004612388565b6106fe565b6102ac61073d565b6040516101559190612a52565b6102ac61074c565b61028f61075b565b61028f6102d736600461230a565b610775565b60006102e7826107a3565b6001015490505b919050565b6005805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103795780601f1061034e57610100808354040283529160200191610379565b820191906000526020600020905b81548152906001019060200180831161035c57829003601f168201915b505050505081565b60005481565b61038f611eff565b6103a161039b846107aa565b836107c4565b90505b92915050565b60606103b5826107a3565b60060180548060200260200160405190810160405280929190818152602001828054801561040257602002820191906000526020600020905b8154815260200190600101908083116103ee575b50505050509050919050565b60066020908152600091825260409182902082516101008101845281548152600182015481840152600282015481850152600382015460608201526004820154608082015260058201805485518186028101860190965280865292949193859360a086019392918301828280156104ae57602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610490575b505050505081526020016006820180548060200260200160405190810160405280929190818152602001828054801561050657602002820191906000526020600020905b8154815260200190600101908083116104f2575b505050505081526020016007820180548060200260200160405190810160405280929190818152602001828054801561055e57602002820191906000526020600020905b81548152602001906001019080831161054a575b5050505050815250509080600801549080600901549080600a0154905084565b6060610589826107a3565b60070180548060200260200160405190810160405280929190818152602001828054801561040257602002820191906000526020600020908154815260200190600101908083116103ee5750505050509050919050565b60006103a46105ee836107aa565b6107df565b60006105fe826107a3565b6004015492915050565b610610611f20565b6040518060800160405280610624846107a3565b600201548152602001600054815260200161063e846107aa565b600901548152602001610650846107aa565b600a0154905292915050565b6000610667826107a3565b6003015492915050565b60035481565b6060610682826107a3565b60050180548060200260200160405190810160405280929190818152602001828054801561040257602002820191906000526020600020905b8154600160a060020a031681526001909101906020018083116106bb5750505050509050919050565b60025481565b6106f333610808565b6106fc336108cb565b565b610706611eff565b61070f33610808565b61072161071b336107a3565b8361094d565b61073361072d336107a3565b836109ae565b6103a43383610387565b600154600160a060020a031681565b600454600160a060020a031681565b61076433610808565b6106f3610770336107a3565b6109cf565b61077e33610808565b61078885856109f8565b61079c610794336107aa565b868686610ae7565b5050505050565b60006103a4825b600160a060020a0316600090815260066020526040902090565b6107cc611eff565b6103a183836107da82610b7f565b610c19565b6008810154600090421015816107f484610d98565b90508180156108005750805b949350505050565b600480546040517ffef3ee73000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163fef3ee739161085091859101612a14565b60206040518083038186803b15801561086857600080fd5b505afa15801561087c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108a091908101906122ec565b6108c85760405160e560020a62461bcd0281526004016108bf90612a91565b60405180910390fd5b50565b600160a060020a0381166000908152600660205260408120818155600181018290556002810182905560038101829055600481018290559081816109126005830182611f48565b610920600683016000611f48565b61092e600783016000611f48565b505060088201600090556009820160009055600a820160009055505050565b600182015461096390829063ffffffff610da816565b156109835760405160e560020a62461bcd0281526004016108bf90612ab1565b81600401548111156109aa5760405160e560020a62461bcd0281526004016108bf90612a71565b5050565b60048201546109c3908263ffffffff610dc516565b82600401819055505050565b6109d881610d98565b156108c85760405160e560020a62461bcd0281526004016108bf90612ad1565b6060610a048383610dda565b90508051600214610a2a5760405160e560020a62461bcd0281526004016108bf90612a81565b6001546040517f32ed010e000000000000000000000000000000000000000000000000000000008152600160a060020a03909116906332ed010e90610a73908490600401612a22565b60206040518083038186803b158015610a8b57600080fd5b505afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ac391908101906122ec565b610ae25760405160e560020a62461bcd0281526004016108bf90612aa1565b505050565b610af384848484610eec565b6000610b00858585611054565b90506064610b14838363ffffffff61119e16565b1015610b355760405160e560020a62461bcd0281526004016108bf90612ac1565b60018501819055610b478585856111c0565b6009860155610b57858585611299565b600a860155600054610b7090429063ffffffff61134716565b85600801819055505050505050565b60028101546000908190610b9a90429063ffffffff610dc516565b90506000548110610bb1575050600a8101546102ee565b6000610bce846009015485600a0154610dc590919063ffffffff16565b90506000610bf7600054610beb848661135990919063ffffffff16565b9063ffffffff61119e16565b6009860154909150610c0f908263ffffffff61134716565b93505050506102ee565b610c21611eff565b8354600090610c3790859063ffffffff61119e16565b9050606085600501805480602002602001604051908101604052809291908181526020018280548015610c9357602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311610c75575b50505050509050600081519050606081604051908082528060200260200182016040528015610ccc578160200160208202803883390190505b509050606082604051908082528060200260200182016040528015610cfb578160200160208202803883390190505b50905060005b83811015610d7d57610d478a6006018281548110610d1b57fe5b90600052602060002001548b6007018381548110610d3557fe5b9060005260206000200154888b611380565b848381518110610d5357fe5b60200260200101848481518110610d6657fe5b602090810291909101019190915252600101610d01565b50610d8984838361144f565b955050505050505b9392505050565b6001810154600490910154101590565b600081610db457600080fd5b818381610dbd57fe5b069392505050565b600082821115610dd457600080fd5b50900390565b60608083600160a060020a03166399d50d5d6040518163ffffffff1660e060020a02815260040160006040518083038186803b158015610e1957600080fd5b505afa158015610e2d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610e559190810190612282565b9050606083600160a060020a03166399d50d5d6040518163ffffffff1660e060020a02815260040160006040518083038186803b158015610e9557600080fd5b505afa158015610ea9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ed19190810190612282565b9050610ee3828263ffffffff61147416565b95945050505050565b610fdc83600160a060020a03166342a7cfd56040518163ffffffff1660e060020a02815260040160206040518083038186803b158015610f2b57600080fd5b505afa158015610f3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f6391908101906123a6565b83600160a060020a03166342a7cfd56040518163ffffffff1660e060020a02815260040160206040518083038186803b158015610f9f57600080fd5b505afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610fd791908101906123a6565b6114bc565b84556003840181905560048401819055426002850155610ffc8383610dda565b8051611012916005870191602090910190611f66565b5061101d84846114d3565b8051611033916006870191602090910190611fd8565b5061103e84836114d3565b805161079c916007870191602090910190611fd8565b600061105e61201f565b61108b8560050160008154811061107157fe5b600091825260209091200154600160a060020a03166115bb565b905061109561201f565b6110a88660050160018154811061107157fe5b905060006110be83600001518360000151611779565b905060006110d6888386602001518660200151611788565b90506000805b60058a015460ff8216101561118b5760008061113b8c6006018460ff168154811061110357fe5b90600052602060002001548d6007018560ff168154811061112057fe5b90600052602060002001546111356001611889565b88611380565b91509150600061114b83836114bc565b90506000611168683635c9adc5dea000008363ffffffff6118a316565b90508581116111775785611179565b805b955050600190930192506110dc915050565b508854610d89908263ffffffff61135916565b60008082116111ac57600080fd5b60008284816111b757fe5b04949350505050565b60006111ca61201f565b6111dd8560050160008154811061107157fe5b90506111e761201f565b6111fa8660050160018154811061107157fe5b9050600061121083600001518360000151611779565b905060006112288883866020015186602001516118e5565b9050600081156112645761125d6064610beb6112506002546064610dc590919063ffffffff16565b869063ffffffff61135916565b9050611285565b6112826064610beb611250600254606461134790919063ffffffff16565b90505b610d89898287602001518760200151611788565b60006112a361201f565b6112b68560050160008154811061107157fe5b90506112c061201f565b6112d38660050160018154811061107157fe5b905060006112e983600001518360000151611779565b905060006113018883866020015186602001516118e5565b9050600081156113295761125d6064610beb611250600354606461134790919063ffffffff16565b6112826064610beb6112506003546064610dc590919063ffffffff16565b6000828201838110156103a157600080fd5b600082611368575060006103a4565b8282028284828161137557fe5b04146103a157600080fd5b6000808080611395888663ffffffff61135916565b6113ad88670de0b6b3a764000063ffffffff61135916565b1115611409576113fe85610beb6113f16113cd8c8463ffffffff61135916565b6113e58c670de0b6b3a764000063ffffffff61135916565b9063ffffffff610dc516565b899063ffffffff61135916565b915060009050611442565b61143b85610beb6113f161142b8b670de0b6b3a764000063ffffffff61135916565b6113e58d8b63ffffffff61135916565b9050600091505b9097909650945050505050565b611457611eff565b506040805160608101825293845260208401929092529082015290565b6060806114818484611931565b9050606061148f8486611931565b9050606061149d8686611a71565b90506114b2836114ad8385611b9f565b611b9f565b9695505050505050565b6000818310156114cc57816103a1565b5090919050565b6060808360050180548060200260200160405190810160405280929190818152602001828054801561152e57602002820191906000526020600020905b8154600160a060020a03168152600190910190602001808311611510575b5050505050905060608151604051908082528060200260200182016040528015611562578160200160208202803883390190505b50905060005b82518110156115b25761159385876000015485848151811061158657fe5b6020026020010151611c81565b82828151811061159f57fe5b6020908102919091010152600101611568565b50949350505050565b6115c361201f565b6001546040517f39477363000000000000000000000000000000000000000000000000000000008152600091600160a060020a03169063394773639061160d908690600401612a14565b60206040518083038186803b15801561162557600080fd5b505afa158015611639573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061165d919081019061222a565b9050600081600160a060020a03166357de26a46040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561169d57600080fd5b505afa1580156116b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116d591908101906123a6565b9050600084600160a060020a031663313ce5676040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561171557600080fd5b505afa158015611729573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061174d91908101906123c4565b60ff169050604051806040016040528083815260200161176e600a84611e35565b905295945050505050565b60006103a182610beb85611889565b6000806118246117d785610beb670de0b6b3a76400006117cb8b6007016000815481106117b157fe5b90600052602060002001548b61135990919063ffffffff16565b9063ffffffff61135916565b61181885610beb611813670de0b6b3a76400008c6007016001815481106117fa57fe5b906000526020600020015461135990919063ffffffff16565b611889565b9063ffffffff61134716565b9050600061186f61184586610beb6118138b6006016000815481106117b157fe5b61181886610beb6118138c60060160018154811061185f57fe5b9060005260206000200154611889565b905061187e81610beb84611889565b979650505050505050565b60006103a482670de0b6b3a764000063ffffffff61135916565b6000806118b6848463ffffffff610da816565b116118d0576118cb838363ffffffff61119e16565b6103a1565b6103a16001611818858563ffffffff61119e16565b6000806118f486868686611788565b905061190a81876006016000815481106117fa57fe5b611926670de0b6b3a7640000886007016000815481106117fa57fe5b119695505050505050565b6060600083519050606081604051908082528060200260200182016040528015611965578160200160208202803883390190505b5090506000805b838110156119c857600087828151811061198257fe5b602002602001015190506119968782611e74565b6119bf5760018483815181106119a857fe5b911515602092830291909101909101526001909201915b5060010161196c565b506060816040519080825280602002602001820160405280156119f5578160200160208202803883390190505b5090506000805b85811015611a6457848181518110611a1057fe5b602002602001015115611a5c57888181518110611a2957fe5b6020026020010151838381518110611a3d57fe5b600160a060020a03909216602092830291909101909101526001909101905b6001016119fc565b5090979650505050505050565b6060600083519050606081604051908082528060200260200182016040528015611aa5578160200160208202803883390190505b5090506000805b83811015611b0357611ad186888381518110611ac457fe5b6020026020010151611e74565b15611afb576001838281518110611ae457fe5b911515602092830291909101909101526001909101905b600101611aac565b50606081604051908082528060200260200182016040528015611b30578160200160208202803883390190505b5090506000805b85811015611a6457848181518110611b4b57fe5b602002602001015115611b9757888181518110611b6457fe5b6020026020010151838381518110611b7857fe5b600160a060020a03909216602092830291909101909101526001909101905b600101611b37565b60606000835190506000835190506060818301604051908082528060200260200182016040528015611bdb578160200160208202803883390190505b50905060005b83811015611c2957868181518110611bf557fe5b6020026020010151828281518110611c0957fe5b600160a060020a0390921660209283029190910190910152600101611be1565b5060005b82811015611c7757858181518110611c4157fe5b60200260200101518282860181518110611c5757fe5b600160a060020a0390921660209283029190910190910152600101611c2d565b5095945050505050565b6000806000611d0e8487600160a060020a03166399d50d5d6040518163ffffffff1660e060020a02815260040160006040518083038186803b158015611cc657600080fd5b505afa158015611cda573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d029190810190612282565b9063ffffffff611e7d16565b915091508015611e2957611e2086600160a060020a031663027aa9f56040518163ffffffff1660e060020a02815260040160006040518083038186803b158015611d5757600080fd5b505afa158015611d6b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d9391908101906122b7565b8381518110611d9e57fe5b602002602001015187600160a060020a03166342a7cfd56040518163ffffffff1660e060020a02815260040160206040518083038186803b158015611de257600080fd5b505afa158015611df6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611e1a91908101906123a6565b87611ee1565b92505050610d91565b50600095945050505050565b6000808311611e4357600080fd5b600160005b83811015611e6c5781611e61818763ffffffff61135916565b925050600101611e48565b509392505050565b600080610ee384845b81516000908190815b81811015611ed05784600160a060020a0316868281518110611ea457fe5b6020026020010151600160a060020a03161415611ec857925060019150611eda9050565b600101611e86565b5060009250829150505b9250929050565b6000610800828585600061080082610beb868663ffffffff61135916565b60405180606001604052806060815260200160608152602001606081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b50805460008255906000526020600020908101906108c89190612039565b828054828255906000526020600020908101928215611fc8579160200282015b82811115611fc8578251825473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909116178255602090920191600190910190611f86565b50611fd4929150612056565b5090565b828054828255906000526020600020908101928215612013579160200282015b82811115612013578251825591602001919060010190611ff8565b50611fd4929150612039565b604051806040016040528060008152602001600081525090565b61205391905b80821115611fd4576000815560010161203f565b90565b61205391905b80821115611fd457805473ffffffffffffffffffffffffffffffffffffffff1916815560010161205c565b60006103a18235612ba3565b60006103a18251612ba3565b600082601f8301126120b057600080fd5b81516120c36120be82612b6f565b612b48565b915081818352602084019350602081019050838560208402820111156120e857600080fd5b60005b8381101561211457816120fe8882612093565b84525060209283019291909101906001016120eb565b5050505092915050565b600082601f83011261212f57600080fd5b815161213d6120be82612b6f565b9150818183526020840193506020810190508385602084028201111561216257600080fd5b60005b83811015612114578161217888826121f4565b8452506020928301929190910190600101612165565b60006103a18251612bae565b60008083601f8401126121ac57600080fd5b50813567ffffffffffffffff8111156121c457600080fd5b602083019150836001820283011115611eda57600080fd5b60006103a18235612bbf565b60006103a18235612053565b60006103a18251612053565b60006103a18251612bca565b60006020828403121561221e57600080fd5b60006108008484612087565b60006020828403121561223c57600080fd5b60006108008484612093565b6000806040838503121561225b57600080fd5b60006122678585612087565b9250506020612278858286016121e8565b9150509250929050565b60006020828403121561229457600080fd5b815167ffffffffffffffff8111156122ab57600080fd5b6108008482850161209f565b6000602082840312156122c957600080fd5b815167ffffffffffffffff8111156122e057600080fd5b6108008482850161211e565b6000602082840312156122fe57600080fd5b6000610800848461218e565b60008060008060006080868803121561232257600080fd5b600061232e88886121dc565b955050602061233f888289016121dc565b9450506040612350888289016121e8565b935050606086013567ffffffffffffffff81111561236d57600080fd5b6123798882890161219a565b92509250509295509295909350565b60006020828403121561239a57600080fd5b600061080084846121e8565b6000602082840312156123b857600080fd5b600061080084846121f4565b6000602082840312156123d657600080fd5b60006108008484612200565b60006123ee8383612402565b505060200190565b60006123ee8383612a0b565b61240b81612ba3565b82525050565b600061241c82612b96565b6124268185612b9a565b935061243183612b90565b60005b8281101561245c576124478683516123e2565b955061245282612b90565b9150600101612434565b5093949350505050565b600061247182612b96565b61247b8185612b9a565b935061248683612b90565b60005b8281101561245c5761249c8683516123e2565b95506124a782612b90565b9150600101612489565b60006124bc82612b96565b6124c68185612b9a565b93506124d183612b90565b60005b8281101561245c576124e78683516123f6565b95506124f282612b90565b91506001016124d4565b600061250782612b96565b6125118185612b9a565b935061251c83612b90565b60005b8281101561245c576125328683516123f6565b955061253d82612b90565b915060010161251f565b61240b81612bae565b61240b81612bbf565b600061256482612b96565b61256e8185612b9a565b935061257e818560208601612bd0565b61258781612bfc565b9093019392505050565b600061259e603f83612b9a565b7f41756374696f6e2e76616c69646174654269645175616e746974793a2042696481527f20657863656564732072656d61696e696e672063757272656e74207365747300602082015260400192915050565b60006125fd604383612b9a565b7f54776f41737365745072696365426f756e6465644c696e65617241756374696f81527f6e3a204f6e6c792074776f20636f6d706f6e656e74732061726520616c6c6f7760208201527f65642e0000000000000000000000000000000000000000000000000000000000604082015260600192915050565b6000612682604683612b9a565b7f4c696e65617241756374696f6e4c697175696461746f723a20496e76616c696481527f206f722064697361626c65642070726f706f73656420536574546f6b656e206160208201527f6464726573730000000000000000000000000000000000000000000000000000604082015260600192915050565b6000612707604e83612b9a565b7f54776f41737365745072696365426f756e6465644c696e65617241756374696f81527f6e3a2050617373656420746f6b656e20646f6573206e6f742068617665206d6160208201527f746368696e67206f7261636c652e000000000000000000000000000000000000604082015260600192915050565b600061278c603d83612b9a565b7f41756374696f6e2e76616c69646174654269645175616e746974793a204d757381527f7420626964206d756c7469706c65206f66206d696e696d756d20626964000000602082015260400192915050565b60006127eb605683612b9a565b7f41756374696f6e2e696e697469616c697a6541756374696f6e3a204d696e696d81527f756d20626964206d757374206265206c657373207468616e206f72206571756160208201527f6c20746f203125206f6620636f6c6c61746572616c2e00000000000000000000604082015260600192915050565b6000612870603083612b9a565b7f41756374696f6e2e736574746c65526562616c616e63653a20526562616c616e81527f6365206e6f7420636f6d706c6574656400000000000000000000000000000000602082015260400192915050565b805160808301906128d38482612a0b565b5060208201516128e66020850182612a0b565b5060408201516128f96040850182612a0b565b50606082015161290c6060850182612a0b565b50505050565b80516000906101008401906129278582612a0b565b50602083015161293a6020860182612a0b565b50604083015161294d6040860182612a0b565b5060608301516129606060860182612a0b565b5060808301516129736080860182612a0b565b5060a083015184820360a086015261298b8282612466565b91505060c083015184820360c08601526129a582826124fc565b91505060e083015184820360e0860152610ee382826124fc565b80516060808452600091908401906129d78282612466565b915050602083015184820360208601526129f182826124fc565b91505060408301518482036040860152610ee382826124fc565b61240b81612053565b602081016103a48284612402565b602080825281016103a18184612411565b602080825281016103a181846124b1565b602081016103a48284612547565b602081016103a48284612550565b602080825281016103a18184612559565b602080825281016103a481612591565b602080825281016103a4816125f0565b602080825281016103a481612675565b602080825281016103a4816126fa565b602080825281016103a48161277f565b602080825281016103a4816127de565b602080825281016103a481612863565b608081016103a482846128c2565b60808082528101612b008187612912565b9050612b0f6020830186612a0b565b612b1c6040830185612a0b565b610ee36060830184612a0b565b602080825281016103a181846129bf565b602081016103a48284612a0b565b60405181810167ffffffffffffffff81118282101715612b6757600080fd5b604052919050565b600067ffffffffffffffff821115612b8657600080fd5b5060209081020190565b60200190565b5190565b90815260200190565b60006103a482612bb3565b151590565b600160a060020a031690565b60006103a482612ba3565b60ff1690565b60005b83811015612beb578181015183820152602001612bd3565b8381111561290c5750506000910152565b601f01601f19169056fea265627a7a723058206d3467f1279a9b6072a74dcc80c2220e7a85372e3fe0138c772af4aa2aa143e86c6578706572696d656e74616cf50037

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

000000000000000000000000f55186cc537e7067ea616f2aae007b4427a120c80000000000000000000000003e6cfdd0255bc69607cefefbc1029a328a982fb600000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000001500000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000174c696e65617241756374696f6e4c697175696461746f72000000000000000000

-----Decoded View---------------
Arg [0] : _core (address): 0xf55186CC537E7067EA616F2aaE007b4427a120C8
Arg [1] : _oracleWhiteList (address): 0x3e6cFdd0255bc69607ceFEfbc1029a328A982fB6
Arg [2] : _auctionPeriod (uint256): 14400
Arg [3] : _rangeStart (uint256): 3
Arg [4] : _rangeEnd (uint256): 21
Arg [5] : _name (string): LinearAuctionLiquidator

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000f55186cc537e7067ea616f2aae007b4427a120c8
Arg [1] : 0000000000000000000000003e6cfdd0255bc69607cefefbc1029a328a982fb6
Arg [2] : 0000000000000000000000000000000000000000000000000000000000003840
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000015
Arg [5] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000017
Arg [7] : 4c696e65617241756374696f6e4c697175696461746f72000000000000000000


Deployed Bytecode Sourcemap

90881:6288:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;90881:6288:0;;;;;;;;-1:-1:-1;;;90881:6288:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95181:116;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;91030:18;;;:::i;:::-;;;;;;;;61555:28;;;:::i;94307:244::-;;;;;;;;;:::i;:::-;;;;;;;;95743:154;;;;;;;;;:::i;:::-;;;;;;;;91055:55;;;;;;;;;:::i;:::-;;;;;;;;;;;95905:148;;;;;;;;;:::i;95025:::-;;;;;;;;;:::i;:::-;;;;;;;;95305:136;;;;;;;;;:::i;96061:461::-;;;;;;;;;:::i;:::-;;;;;;;;95449:134;;;;;;;;;:::i;75519:23::-;;;:::i;95591:144::-;;;;;;;;;:::i;:::-;;;;;;;;75437:25;;;:::i;94860:100::-;;;:::i;:::-;;93632:353;;;;;;;;;:::i;75391:39::-;;;:::i;:::-;;;;;;;;91006:17;;;:::i;94640:164::-;;;:::i;92674:606::-;;;;;;;;;:::i;95181:116::-;95238:7;95265:13;95273:4;95265:7;:13::i;:::-;:24;;;95258:31;;95181:116;;;;:::o;91030:18::-;;;;;;;;;;;;;;;-1:-1:-1;;91030:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;61555:28::-;;;;:::o;94307:244::-;94434:26;;:::i;:::-;94485:58;94512:19;94526:4;94512:13;:19::i;:::-;94533:9;94485:26;:58::i;:::-;94478:65;;94307:244;;;;;:::o;95743:154::-;95816:16;95852:13;95860:4;95852:7;:13::i;:::-;:37;;95845:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95743:154;;;:::o;91055:55::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;91055:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;95905:148::-;95975:16;96011:13;96019:4;96011:7;:13::i;:::-;:34;;96004:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95905:148;;;:::o;95025:::-;95090:4;95114:51;95145:19;95159:4;95145:13;:19::i;:::-;95114:30;:51::i;95305:136::-;95372:7;95399:13;95407:4;95399:7;:13::i;:::-;:34;;;;95305:136;-1:-1:-1;;95305:136:0:o;96061:461::-;96157:48;;:::i;:::-;96230:284;;;;;;;;96305:13;96313:4;96305:7;:13::i;:::-;:23;;;96230:284;;;;96363:13;;96230:284;;;;96410:19;96424:4;96410:13;:19::i;:::-;:30;;;96230:284;;;;96474:19;96488:4;96474:13;:19::i;:::-;:28;;;96230:284;;96223:291;96061:461;-1:-1:-1;;96061:461:0:o;95449:134::-;95515:7;95542:13;95550:4;95542:7;:13::i;:::-;:33;;;;95449:134;-1:-1:-1;;95449:134:0:o;75519:23::-;;;;:::o;95591:144::-;95659:16;95695:13;95703:4;95695:7;:13::i;:::-;:32;;95688:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;95688:39:0;;;;;;;;;;;;;;;;;;;;;;95591:144;;;:::o;75437:25::-;;;;:::o;94860:100::-;91198:27;91214:10;91198:15;:27::i;:::-;94923:29;94941:10;94923:17;:29::i;:::-;94860:100::o;93632:353::-;93741:26;;:::i;:::-;91198:27;91214:10;91198:15;:27::i;:::-;93785:59;93813:19;93821:10;93813:7;:19::i;:::-;93834:9;93785:27;:59::i;:::-;93857:66;93892:19;93900:10;93892:7;:19::i;:::-;93913:9;93857:34;:66::i;:::-;93943:34;93955:10;93967:9;93943:11;:34::i;75391:39::-;;;-1:-1:-1;;;;;75391:39:0;;:::o;91006:17::-;;;-1:-1:-1;;;;;91006:17:0;;:::o;94640:164::-;91198:27;91214:10;91198:15;:27::i;:::-;94700:54;94734:19;94742:10;94734:7;:19::i;:::-;94700:33;:54::i;92674:606::-;91198:27;91214:10;91198:15;:27::i;:::-;92951:129;93035:11;93061:8;92951:69;:129::i;:::-;93093:179;93145:25;93159:10;93145:13;:25::i;:::-;93185:11;93211:8;93234:27;93093:37;:179::i;:::-;92674:606;;;;;:::o;96684:128::-;96736:21;96777:19;96791:4;96820:127;-1:-1:-1;;;;;96925:14:0;96878:27;96925:14;;;:8;:14;;;;;;96820:127::o;63589:342::-;63735:26;;:::i;:::-;63786:137;63827:14;63864:9;63888:24;63827:14;63888:8;:24::i;:::-;63786:26;:137::i;64080:302::-;64217:22;;;;64158:4;;64198:15;:41;;64158:4;64274:43;64217:14;64274:19;:43::i;:::-;64250:67;;64338:15;:35;;;;;64357:16;64338:35;64330:44;64080:302;-1:-1:-1;;;;64080:302:0:o;96955:211::-;97040:4;;;:20;;;;;-1:-1:-1;;;;;97040:4:0;;;;:14;;:20;;97055:4;;97040:20;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;97040:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;97040:20:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;97040:20:0;;;;;;;;;97018:140;;;;-1:-1:-1;;;;;97018:140:0;;;;;;;;;;;;;;;;;96955:211;:::o;96587:89::-;-1:-1:-1;;;;;96654:14:0;;;;;;:8;:14;;;;;96647:21;;;;;;;;;;;;;;;;;;;;;;;;;;;96654:14;;;96647:21;;;;96654:14;96647:21;:::i;:::-;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;96587:89;:::o;50582:423::-;50715:19;;;;50701:34;;:9;;:34;:13;:34;:::i;:::-;:39;50679:150;;;;-1:-1:-1;;;;;50679:150:0;;;;;;;;;50877:8;:29;;;50864:9;:42;;50842:155;;;;-1:-1:-1;;;;;50842:155:0;;;;;;;;;50582:423;;:::o;50284:183::-;50415:29;;;;:44;;50449:9;50415:44;:33;:44;:::i;:::-;50383:8;:29;;:76;;;;50284:183;;:::o;51146:220::-;51253:29;51273:8;51253:19;:29::i;:::-;51252:30;51230:128;;;;-1:-1:-1;;;;;51230:128:0;;;;;;;;76418:611;76579:35;76617:52;76647:11;76660:8;76617:29;:52::i;:::-;76579:90;;76702:18;:25;76731:1;76702:30;76680:147;;;;-1:-1:-1;;;;;76680:147:0;;;;;;;;;76862:15;;:53;;;;;-1:-1:-1;;;;;76862:15:0;;;;:33;;:53;;76896:18;;76862:53;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;76862:53:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;76862:53:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;76862:53:0;;;;;;;;;76840:181;;;;-1:-1:-1;;;;;76840:181:0;;;;;;;;;76418:611;;;:::o;62325:1118::-;62545:156;62577:14;62614:11;62640:8;62663:27;62545:17;:156::i;:::-;62714:18;62735:66;62755:14;62779:11;62792:8;62735:19;:66::i;:::-;62714:87;-1:-1:-1;62979:3:0;62932:43;:27;62714:87;62932:43;:31;:43;:::i;:::-;:50;;62910:186;;;;-1:-1:-1;;;;;62910:186:0;;;;;;;;;63109:33;;;:46;;;63196:66;63109:14;63240:11;63253:8;63196:19;:66::i;:::-;63168:25;;;:94;63299:64;63168:14;63341:11;63354:8;63299:17;:64::i;:::-;63273:23;;;:90;63421:13;;63401:34;;:15;;:34;:19;:34;:::i;:::-;63376:14;:22;;:59;;;;62325:1118;;;;;:::o;64689:554::-;64818:32;;;;64760:7;;;;64798:53;;:15;;:53;:19;:53;:::i;:::-;64780:71;;64919:13;;64908:7;:24;64904:332;;-1:-1:-1;;64956:23:0;;;;64949:30;;64904:332;65012:13;65028:54;65056:14;:25;;;65028:14;:23;;;:27;;:54;;;;:::i;:::-;65012:70;;65097:20;65120:37;65143:13;;65120:18;65132:5;65120:7;:11;;:18;;;;:::i;:::-;:22;:37;:22;:37;:::i;:::-;65181:25;;;;65097:60;;-1:-1:-1;65181:43:0;;65097:60;65181:43;:29;:43;:::i;:::-;65174:50;;;;;;;52137:1245;52308:26;;:::i;:::-;52431:23;;52391;;52417:38;;:9;;:38;:13;:38;:::i;:::-;52391:64;;52468:38;52509:8;:27;;52468:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;52468:68:0;;;;;;;;;;;;;;;;;;;;;;;52549:26;52578:21;:28;52549:57;;52617:32;52666:18;52652:33;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;52652:33:0;;52617:68;;52696:33;52746:18;52732:33;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;52732:33:0;-1:-1:-1;52696:69:0;-1:-1:-1;52906:9:0;52901:370;52925:18;52921:1;:22;52901:370;;;53058:201;53099:8;:32;;53132:1;53099:35;;;;;;;;;;;;;;;;53153:8;:29;;53183:1;53153:32;;;;;;;;;;;;;;;;53204:15;53238:6;53058:22;:201::i;:::-;52984:15;53000:1;52984:18;;;;;;;;;;;;;53021:16;53038:1;53021:19;;;;;;;;;;;;;;;;;52965:294;;;;;52945:3;;52901:370;;;;53290:84;53317:21;53340:15;53357:16;53290:26;:84::i;:::-;53283:91;;;;;;;52137:1245;;;;;;:::o;51492:159::-;51624:19;;;;51591:29;;;;;:52;;;51492:159::o;1861:124::-;1919:7;1947:6;1939:15;;;;;;1976:1;1972;:5;;;;;;;1861:124;-1:-1:-1;;;1861:124:0:o;1312:150::-;1370:7;1403:1;1398;:6;;1390:15;;;;;;-1:-1:-1;1428:5:0;;;1312:150::o;53685:392::-;53833:16;53867:37;53907:11;-1:-1:-1;;;;;53907:25:0;;:27;;;;;-1:-1:-1;;;53907:27:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;53907:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;53907:27:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;53907:27:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;53907:27:0;;;;;;;;;53867:67;;53945:34;53982:8;-1:-1:-1;;;;;53982:22:0;;:24;;;;;-1:-1:-1;;;53982:24:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;53982:24:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;53982:24:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;53982:24:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;53982:24:0;;;;;;;;;53945:61;-1:-1:-1;54024:45:0;:20;53945:61;54024:45;:26;:45;:::i;:::-;54017:52;53685:392;-1:-1:-1;;;;;53685:392:0:o;49481:795::-;49715:96;49738:11;-1:-1:-1;;;;;49738:23:0;;:25;;;;;-1:-1:-1;;;49738:25:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;49738:25:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;49738:25:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;49738:25:0;;;;;;;;;49778:8;-1:-1:-1;;;;;49778:20:0;;:22;;;;;-1:-1:-1;;;49778:22:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;49778:22:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;49778:22:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;49778:22:0;;;;;;;;;49715:8;:96::i;:::-;49689:122;;49824:28;;;:58;;;49893:29;;;:59;;;49984:15;49963:18;;;:36;50040:44;50062:11;50075:8;50040:21;:44::i;:::-;50010:74;;;;:27;;;;:74;;;;;;:::i;:::-;;50130:49;50157:8;50167:11;50130:26;:49::i;:::-;50095:84;;;;:32;;;;:84;;;;;;:::i;:::-;;50222:46;50249:8;50259;50222:26;:46::i;:::-;50190:78;;;;:29;;;;:78;;;;;;:::i;77758:2214::-;77946:7;78029:25;;:::i;:::-;78057:44;78070:8;:27;;78098:1;78070:30;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;78070:30:0;78057:12;:44::i;:::-;78029:72;;78112:25;;:::i;:::-;78140:44;78153:8;:27;;78181:1;78153:30;;;;;;;78140:44;78112:72;;78259:17;78279:50;78298:8;:14;;;78314:8;:14;;;78279:18;:50::i;:::-;78259:70;;78411:24;78438:157;78488:8;78511:9;78535:8;:17;;;78567:8;:17;;;78438:35;:157::i;:::-;78411:184;-1:-1:-1;78608:28:0;;78651:1163;78673:27;;;:34;78669:38;;;;78651:1163;;;78888:25;78932:26;78976:215;79025:8;:32;;79058:1;79025:35;;;;;;;;;;;;;;;;;;79079:8;:29;;79109:1;79079:32;;;;;;;;;;;;;;;;;;79130:11;75150:1;79130:9;:11::i;:::-;79160:16;78976:30;:215::i;:::-;78869:322;;;;79308:23;79334:47;79343:17;79362:18;79334:8;:47::i;:::-;79308:73;-1:-1:-1;79550:31:0;79584:51;75272:8;79308:73;79584:51;:34;:51;:::i;:::-;79550:85;;79699:20;79673:23;:46;:129;;79782:20;79673:129;;;79739:23;79673:129;79650:152;-1:-1:-1;;78709:3:0;;;;;-1:-1:-1;78651:1163:0;;-1:-1:-1;;78651:1163:0;;-1:-1:-1;79915:23:0;;:49;;79943:20;79915:49;:27;:49;:::i;871:303::-;929:7;1028:1;1024;:5;1016:14;;;;;;1041:9;1057:1;1053;:5;;;;;;;871:303;-1:-1:-1;;;;871:303:0:o;80422:1598::-;80609:7;80692:25;;:::i;:::-;80720:44;80733:8;:27;;80761:1;80733:30;;;;;;;80720:44;80692:72;;80775:25;;:::i;:::-;80803:44;80816:8;:27;;80844:1;80816:30;;;;;;;80803:44;80775:72;;80933:17;80953:50;80972:8;:14;;;80988:8;:14;;;80953:18;:50::i;:::-;80933:70;;81104:26;81133:143;81169:8;81192:9;81216:8;:17;;;81248:8;:17;;;81133:21;:143::i;:::-;81104:172;;81488:22;81525:21;81521:239;;;81580:59;75326:3;81580:42;81594:27;81610:10;;75326:3;81594:15;;:27;;;;:::i;:::-;81580:9;;:42;:13;:42;:::i;:59::-;81563:76;;81521:239;;;81689:59;75326:3;81689:42;81703:27;81719:10;;75326:3;81703:15;;:27;;;;:::i;81689:59::-;81672:76;;81521:239;81850:162;81900:8;81923:14;81952:8;:17;;;81984:8;:17;;;81850:35;:162::i;82466:1571::-;82651:7;82734:25;;:::i;:::-;82762:44;82775:8;:27;;82803:1;82775:30;;;;;;;82762:44;82734:72;;82817:25;;:::i;:::-;82845:44;82858:8;:27;;82886:1;82858:30;;;;;;;82845:44;82817:72;;82964:17;82984:50;83003:8;:14;;;83019:8;:14;;;82984:18;:50::i;:::-;82964:70;;83135:26;83164:143;83200:8;83223:9;83247:8;:17;;;83279:8;:17;;;83164:21;:143::i;:::-;83135:172;;83519:20;83554:21;83550:231;;;83607:57;75326:3;83607:40;83621:25;83637:8;;75326:3;83621:15;;:25;;;;:::i;83550:231::-;83712:57;75326:3;83712:40;83726:25;83742:8;;75326:3;83726:15;;:25;;;;:::i;1550:150::-;1608:7;1640:5;;;1664:6;;;;1656:15;;;;;303:433;361:7;605:6;601:47;;-1:-1:-1;635:1:0;628:8;;601:47;672:5;;;676:1;672;:5;:1;696:5;;;;;:10;688:19;;;;;54720:2693;54931:7;;;;56637:24;:12;56654:6;56637:24;:16;:24;:::i;:::-;56599:35;:12;49041:8;56599:35;:16;:35;:::i;:::-;:62;56595:766;;;56731:131;56855:6;56731:119;56770:65;56810:24;:12;56855:6;56810:24;:16;:24;:::i;:::-;56770:35;:12;49041:8;56770:35;:16;:35;:::i;:::-;:39;:65;:39;:65;:::i;:::-;56731:16;;:119;:20;:119;:::i;:131::-;56718:144;;56996:1;56982:15;;56595:766;;;57085:131;57209:6;57085:119;57124:65;57153:35;:12;49041:8;57153:35;:16;:35;:::i;:::-;57124:24;:12;57141:6;57124:24;:16;:24;:::i;57085:131::-;57071:145;;57348:1;57335:14;;56595:766;57381:10;;;;-1:-1:-1;54720:2693:0;-1:-1:-1;;;;;54720:2693:0:o;29938:311::-;30129:16;;:::i;:::-;-1:-1:-1;30170:71:0;;;;;;;;;;;;;;;;;;;;;;;29938:311::o;42418:364::-;42496:16;42525:31;42559:16;42570:1;42573;42559:10;:16::i;:::-;42525:50;;42586:32;42621:16;42632:1;42635;42621:10;:16::i;:::-;42586:51;;42648:29;42680:15;42690:1;42693;42680:9;:15::i;:::-;42648:47;;42713:61;42720:14;42736:37;42743:12;42757:15;42736:6;:37::i;:::-;42713:6;:61::i;:::-;42706:68;42418:364;-1:-1:-1;;;;;;42418:364:0:o;36901:107::-;36959:7;36991:1;36986;:6;;:14;;36999:1;36986:14;;;-1:-1:-1;36995:1:0;;36901:107;-1:-1:-1;36901:107:0:o;57867:628::-;58018:16;58052:35;58090:8;:27;;58052:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;58052:65:0;;;;;;;;;;;;;;;;;;;;;;;58128:30;58175:18;:25;58161:40;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;58161:40:0;-1:-1:-1;58128:73:0;-1:-1:-1;58217:9:0;58212:243;58236:18;:25;58232:1;:29;58212:243;;;58302:141;58342:4;58365:8;:23;;;58407:18;58426:1;58407:21;;;;;;;;;;;;;;58302;:141::i;:::-;58283:13;58297:1;58283:16;;;;;;;;;;;;;;;;;:160;58263:3;;58212:243;;;-1:-1:-1;58474:13:0;57867:628;-1:-1:-1;;;;57867:628:0:o;89189:421::-;89248:16;;:::i;:::-;89299:15;;:47;;;;;89277:19;;-1:-1:-1;;;;;89299:15:0;;:39;;:47;;89339:6;;89299:47;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;89299:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;89299:47:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;89299:47:0;;;;;;;;;89277:69;;89357:18;89386:11;-1:-1:-1;;;;;89378:25:0;;:27;;;;;-1:-1:-1;;;89378:27:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;89378:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;89378:27:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;89378:27:0;;;;;;;;;89357:48;;89418:16;89451:6;-1:-1:-1;;;;;89437:30:0;;:32;;;;;-1:-1:-1;;;89437:32:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;89437:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;89437:32:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;89437:32:0;;;;;;;;;89418:51;;;;89489:113;;;;;;;;89521:10;89489:113;;;;89556:34;89577:2;89581:8;89556:20;:34::i;:::-;89489:113;;89482:120;89189:421;-1:-1:-1;;;;;89189:421:0:o;89689:174::-;89786:7;89813:42;89840:14;89813:22;:14;:20;:22::i;87194:1831::-;87439:7;87774:21;87798:212;87903:96;87981:17;87903:73;75104:8;87903:50;87920:8;:29;;87950:1;87920:32;;;;;;;;;;;;;;;;87903:12;:16;;:50;;;;:::i;:::-;:54;:73;:54;:73;:::i;:96::-;87798:86;87866:17;87798:63;:55;75104:8;87798;:29;;87828:1;87798:32;;;;;;;;;;;;;;;;:36;;:55;;;;:::i;:::-;:61;:63::i;:86::-;:90;:212;:90;:212;:::i;:::-;87774:236;;88374:23;88400:187;88492:84;88558:17;88492:61;:53;88509:8;:32;;88542:1;88509:35;;;;;;;88492:84;88400:74;88456:17;88400:51;:43;:8;:32;;88433:1;88400:35;;;;;;;;;;;;;;;;:41;:43::i;:187::-;88374:213;;88975:42;89001:15;88975:21;:13;:19;:21::i;:42::-;88968:49;87194:1831;-1:-1:-1;;;;;;;87194:1831:0:o;69907:151::-;69999:7;70031:19;:1;69195:8;70031:19;:5;:19;:::i;70994:169::-;71082:7;;71114:8;:1;71120;71114:8;:5;:8;:::i;:::-;:12;:41;;71147:8;:1;71153;71147:8;:5;:8;:::i;:::-;71114:41;;;71129:15;71142:1;71129:8;:1;71135;71129:8;:5;:8;:::i;85387:815::-;85616:4;85707:24;85734:158;85784:8;85807:10;85832:17;85864;85734:35;:158::i;:::-;85707:185;;86137:57;86177:16;86137:8;:32;;86170:1;86137:35;;;;;;;:57;86066:55;75104:8;86066;:29;;86096:1;86066:32;;;;;;;:55;:128;;85387:815;-1:-1:-1;;;;;;85387:815:0:o;43004:802::-;43087:16;43116:14;43133:1;:8;43116:25;;43152:24;43190:6;43179:18;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;43179:18:0;-1:-1:-1;43152:45:0;-1:-1:-1;43208:13:0;;43315:196;43339:6;43335:1;:10;43315:196;;;43367:9;43379:1;43381;43379:4;;;;;;;;;;;;;;43367:16;;43403:14;43412:1;43415;43403:8;:14::i;:::-;43398:102;;43454:4;43438:10;43449:1;43438:13;;;;;;;;:20;;;:13;;;;;;;;;;;:20;43477:7;;;;;43398:102;-1:-1:-1;43347:3:0;;43315:196;;;;43521:29;43567:5;43553:20;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;43553:20:0;-1:-1:-1;43521:52:0;-1:-1:-1;43584:9:0;;43608:161;43632:6;43628:1;:10;43608:161;;;43664:10;43675:1;43664:13;;;;;;;;;;;;;;43660:98;;;43716:1;43718;43716:4;;;;;;;;;;;;;;43698:12;43711:1;43698:15;;;;;;;;-1:-1:-1;;;;;43698:22:0;;;:15;;;;;;;;;;;:22;43739:3;;;;;43660:98;43640:3;;43608:161;;;-1:-1:-1;43786:12:0;;43004:802;-1:-1:-1;;;;;;;43004:802:0:o;41506:705::-;41588:16;41617:14;41634:1;:8;41617:25;;41653:24;41691:6;41680:18;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;41680:18:0;-1:-1:-1;41653:45:0;-1:-1:-1;41709:17:0;;41741:171;41765:6;41761:1;:10;41741:171;;;41797:17;41806:1;41809;41811;41809:4;;;;;;;;;;;;;;41797:8;:17::i;:::-;41793:108;;;41851:4;41835:10;41846:1;41835:13;;;;;;;;:20;;;:13;;;;;;;;;;;:20;41874:11;;;;;41793:108;41773:3;;41741:171;;;;41922:29;41968:9;41954:24;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;41954:24:0;-1:-1:-1;41922:56:0;-1:-1:-1;41989:9:0;;42013:161;42037:6;42033:1;:10;42013:161;;;42069:10;42080:1;42069:13;;;;;;;;;;;;;;42065:98;;;42121:1;42123;42121:4;;;;;;;;;;;;;;42103:12;42116:1;42103:15;;;;;;;;-1:-1:-1;;;;;42103:22:0;;;:15;;;;;;;;;;;:22;42144:3;;;;;42065:98;42045:3;;42013:161;;40252:488;40331:16;40360:15;40378:1;:8;40360:26;;40397:15;40415:1;:8;40397:26;;40434:29;40490:7;40480;:17;40466:32;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;40466:32:0;-1:-1:-1;40434:64:0;-1:-1:-1;40514:9:0;40509:87;40533:7;40529:1;:11;40509:87;;;40580:1;40582;40580:4;;;;;;;;;;;;;;40562:12;40575:1;40562:15;;;;;;;;-1:-1:-1;;;;;40562:22:0;;;:15;;;;;;;;;;;:22;40542:3;;40509:87;;;-1:-1:-1;40611:9:0;40606:97;40630:7;40626:1;:11;40606:97;;;40687:1;40689;40687:4;;;;;;;;;;;;;;40659:12;40682:1;40672:7;:11;40659:25;;;;;;;;-1:-1:-1;;;;;40659:32:0;;;:25;;;;;;;;;;;:32;40639:3;;40606:97;;;-1:-1:-1;40720:12:0;40252:488;-1:-1:-1;;;;;40252:488:0:o;58902:701::-;59082:7;59186:20;59221:16;59251:45;59285:10;59251:9;-1:-1:-1;;;;;59251:23:0;;:25;;;;;-1:-1:-1;;;59251:25:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59251:25:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;59251:25:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;59251:25:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;59251:25:0;;;;;;;;;:33;:45;:33;:45;:::i;:::-;59171:125;;;;59362:11;59358:217;;;59397:166;59438:9;-1:-1:-1;;;;;59438:18:0;;:20;;;;;-1:-1:-1;;;59438:20:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59438:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;59438:20:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;59438:20:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;59438::0;;;;;;;;;59459:12;59438:34;;;;;;;;;;;;;;59491:9;-1:-1:-1;;;;;59491:21:0;;:23;;;;;-1:-1:-1;;;59491:23:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59491:23:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;59491:23:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;59491:23:0;;;;;;;;;59533:15;59397:22;:166::i;:::-;59390:173;;;;;;59358:217;-1:-1:-1;59594:1:0;;58902:701;-1:-1:-1;;;;;58902:701:0:o;70452:435::-;70570:7;70607:1;70603;:5;70595:14;;;;;;70639:1;70622:14;70651:203;70675:3;70671:1;:7;70651:203;;;70724:6;70821:21;70724:6;70840:1;70821:21;:18;:21;:::i;:::-;70812:30;-1:-1:-1;;70680:3:0;;70651:203;;;-1:-1:-1;70873:6:0;70452:435;-1:-1:-1;;;70452:435:0:o;39906:163::-;39978:4;39995:9;40026:13;40034:1;40037;39351:297;39465:8;;39422:7;;;;;39484:129;39508:6;39504:1;:10;39484:129;;;39548:1;-1:-1:-1;;;;;39540:9:0;:1;39542;39540:4;;;;;;;;;;;;;;-1:-1:-1;;;;;39540:9:0;;39536:66;;;39578:1;-1:-1:-1;39581:4:0;;-1:-1:-1;39570:16:0;;-1:-1:-1;39570:16:0;39536:66;39516:3;;39484:129;;;-1:-1:-1;39631:1:0;;-1:-1:-1;39631:1:0;;-1:-1:-1;;39351:297:0;;;;;;:::o;60082:277::-;60259:7;60291:60;60314:15;60331:5;60338:12;47034:7;47066:50;47103:12;47066:32;:12;47083:14;47066:32;:16;:32;:::i;90881:6288::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;90881:6288:0;-1:-1:-1;;;;;90881:6288:0;;;;;;;;;;;-1:-1:-1;90881:6288:0;;;;;;;-1:-1:-1;90881:6288:0;;;-1:-1:-1;90881:6288:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;90881:6288:0;;;-1:-1:-1;90881:6288:0;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;90881:6288:0;;;;;;;5:118:-1;;72:46;110:6;97:20;72:46;;130:122;;208:39;239:6;233:13;208:39;;277:722;;405:3;398:4;390:6;386:17;382:27;372:2;;423:1;420;413:12;372:2;453:6;447:13;475:80;490:64;547:6;490:64;;;475:80;;;466:89;;572:5;597:6;590:5;583:21;627:4;619:6;615:17;605:27;;649:4;644:3;640:14;633:21;;702:6;749:3;741:4;733:6;729:17;724:3;720:27;717:36;714:2;;;766:1;763;756:12;714:2;791:1;776:217;801:6;798:1;795:13;776:217;;;859:3;881:48;925:3;913:10;881:48;;;869:61;;-1:-1;953:4;944:14;;;;972;;;;;823:1;816:9;776:217;;;780:14;365:634;;;;;;;;1025:722;;1153:3;1146:4;1138:6;1134:17;1130:27;1120:2;;1171:1;1168;1161:12;1120:2;1201:6;1195:13;1223:80;1238:64;1295:6;1238:64;;1223:80;1214:89;;1320:5;1345:6;1338:5;1331:21;1375:4;1367:6;1363:17;1353:27;;1397:4;1392:3;1388:14;1381:21;;1450:6;1497:3;1489:4;1481:6;1477:17;1472:3;1468:27;1465:36;1462:2;;;1514:1;1511;1504:12;1462:2;1539:1;1524:217;1549:6;1546:1;1543:13;1524:217;;;1607:3;1629:48;1673:3;1661:10;1629:48;;;1617:61;;-1:-1;1701:4;1692:14;;;;1720;;;;;1571:1;1564:9;1524:217;;1755:116;;1830:36;1858:6;1852:13;1830:36;;1892:335;;;2006:3;1999:4;1991:6;1987:17;1983:27;1973:2;;2024:1;2021;2014:12;1973:2;-1:-1;2044:20;;2084:18;2073:30;;2070:2;;;2116:1;2113;2106:12;2070:2;2150:4;2142:6;2138:17;2126:29;;2200:3;2193;2185:6;2181:16;2171:8;2167:31;2164:40;2161:2;;;2217:1;2214;2207:12;2235:152;;2319:63;2374:6;2361:20;2319:63;;2394:118;;2461:46;2499:6;2486:20;2461:46;;2519:122;;2597:39;2628:6;2622:13;2597:39;;2648:118;;2724:37;2753:6;2747:13;2724:37;;2773:241;;2877:2;2865:9;2856:7;2852:23;2848:32;2845:2;;;2893:1;2890;2883:12;2845:2;2928:1;2945:53;2990:7;2970:9;2945:53;;3021:263;;3136:2;3124:9;3115:7;3111:23;3107:32;3104:2;;;3152:1;3149;3142:12;3104:2;3187:1;3204:64;3260:7;3240:9;3204:64;;3291:366;;;3412:2;3400:9;3391:7;3387:23;3383:32;3380:2;;;3428:1;3425;3418:12;3380:2;3463:1;3480:53;3525:7;3505:9;3480:53;;;3470:63;;3442:97;3570:2;3588:53;3633:7;3624:6;3613:9;3609:22;3588:53;;;3578:63;;3549:98;3374:283;;;;;;3664:392;;3804:2;3792:9;3783:7;3779:23;3775:32;3772:2;;;3820:1;3817;3810:12;3772:2;3855:24;;3899:18;3888:30;;3885:2;;;3931:1;3928;3921:12;3885:2;3951:89;4032:7;4023:6;4012:9;4008:22;3951:89;;4063:392;;4203:2;4191:9;4182:7;4178:23;4174:32;4171:2;;;4219:1;4216;4209:12;4171:2;4254:24;;4298:18;4287:30;;4284:2;;;4330:1;4327;4320:12;4284:2;4350:89;4431:7;4422:6;4411:9;4407:22;4350:89;;4462:257;;4574:2;4562:9;4553:7;4549:23;4545:32;4542:2;;;4590:1;4587;4580:12;4542:2;4625:1;4642:61;4695:7;4675:9;4642:61;;4726:809;;;;;;4934:3;4922:9;4913:7;4909:23;4905:33;4902:2;;;4951:1;4948;4941:12;4902:2;4986:1;5003:70;5065:7;5045:9;5003:70;;;4993:80;;4965:114;5110:2;5128:70;5190:7;5181:6;5170:9;5166:22;5128:70;;;5118:80;;5089:115;5235:2;5253:53;5298:7;5289:6;5278:9;5274:22;5253:53;;;5243:63;;5214:98;5371:2;5360:9;5356:18;5343:32;5395:18;5387:6;5384:30;5381:2;;;5427:1;5424;5417:12;5381:2;5455:64;5511:7;5502:6;5491:9;5487:22;5455:64;;;5445:74;;;;5322:203;4896:639;;;;;;;;;5542:241;;5646:2;5634:9;5625:7;5621:23;5617:32;5614:2;;;5662:1;5659;5652:12;5614:2;5697:1;5714:53;5759:7;5739:9;5714:53;;5790:263;;5905:2;5893:9;5884:7;5880:23;5876:32;5873:2;;;5921:1;5918;5911:12;5873:2;5956:1;5973:64;6029:7;6009:9;5973:64;;6060:259;;6173:2;6161:9;6152:7;6148:23;6144:32;6141:2;;;6189:1;6186;6179:12;6141:2;6224:1;6241:62;6295:7;6275:9;6241:62;;6327:173;;6414:46;6456:3;6448:6;6414:46;;;-1:-1;;6489:4;6480:14;;6407:93;6509:173;;6596:46;6638:3;6630:6;6596:46;;6690:110;6763:31;6788:5;6763:31;;;6758:3;6751:44;6745:55;;;6965:621;;7110:54;7158:5;7110:54;;;7177:86;7256:6;7251:3;7177:86;;;7170:93;;7283:56;7333:5;7283:56;;;7360:1;7345:219;7370:6;7367:1;7364:13;7345:219;;;7417:63;7476:3;7467:6;7461:13;7417:63;;;7410:70;;7497:60;7550:6;7497:60;;;7487:70;-1:-1;7392:1;7385:9;7345:219;;;-1:-1;7577:3;;7089:497;-1:-1;;;;7089:497;7625:585;;7756:50;7800:5;7756:50;;;7819:76;7888:6;7883:3;7819:76;;;7812:83;;7915:52;7961:5;7915:52;;;7988:1;7973:215;7998:6;7995:1;7992:13;7973:215;;;8045:63;8104:3;8095:6;8089:13;8045:63;;;8038:70;;8125:56;8174:6;8125:56;;;8115:66;-1:-1;8020:1;8013:9;7973:215;;8249:621;;8394:54;8442:5;8394:54;;;8461:86;8540:6;8535:3;8461:86;;;8454:93;;8567:56;8617:5;8567:56;;;8644:1;8629:219;8654:6;8651:1;8648:13;8629:219;;;8701:63;8760:3;8751:6;8745:13;8701:63;;;8694:70;;8781:60;8834:6;8781:60;;;8771:70;-1:-1;8676:1;8669:9;8629:219;;8909:585;;9040:50;9084:5;9040:50;;;9103:76;9172:6;9167:3;9103:76;;;9096:83;;9199:52;9245:5;9199:52;;;9272:1;9257:215;9282:6;9279:1;9276:13;9257:215;;;9329:63;9388:3;9379:6;9373:13;9329:63;;;9322:70;;9409:56;9458:6;9409:56;;;9399:66;-1:-1;9304:1;9297:9;9257:215;;9502:111;9579:28;9601:5;9579:28;;9620:152;9716:50;9760:5;9716:50;;9960:339;;10068:35;10097:5;10068:35;;;10115:71;10179:6;10174:3;10115:71;;;10108:78;;10191:52;10236:6;10231:3;10224:4;10217:5;10213:16;10191:52;;;10264:29;10286:6;10264:29;;;10255:39;;;;10048:251;-1:-1;;;10048:251;10307:465;;10467:67;10531:2;10526:3;10467:67;;;10567:66;10547:87;;10668:66;10663:2;10654:12;;10647:88;10763:2;10754:12;;10453:319;-1:-1;;10453:319;10781:566;;10941:67;11005:2;11000:3;10941:67;;;11041:66;11021:87;;11142:66;11137:2;11128:12;;11121:88;11243:66;11238:2;11229:12;;11222:88;11338:2;11329:12;;10927:420;-1:-1;;10927:420;11356:566;;11516:67;11580:2;11575:3;11516:67;;;11616:66;11596:87;;11717:66;11712:2;11703:12;;11696:88;11818:66;11813:2;11804:12;;11797:88;11913:2;11904:12;;11502:420;-1:-1;;11502:420;11931:566;;12091:67;12155:2;12150:3;12091:67;;;12191:66;12171:87;;12292:66;12287:2;12278:12;;12271:88;12393:66;12388:2;12379:12;;12372:88;12488:2;12479:12;;12077:420;-1:-1;;12077:420;12506:465;;12666:67;12730:2;12725:3;12666:67;;;12766:66;12746:87;;12867:66;12862:2;12853:12;;12846:88;12962:2;12953:12;;12652:319;-1:-1;;12652:319;12980:566;;13140:67;13204:2;13199:3;13140:67;;;13240:66;13220:87;;13341:66;13336:2;13327:12;;13320:88;13442:66;13437:2;13428:12;;13421:88;13537:2;13528:12;;13126:420;-1:-1;;13126:420;13555:465;;13715:67;13779:2;13774:3;13715:67;;;13815:66;13795:87;;13916:66;13911:2;13902:12;;13895:88;14011:2;14002:12;;13701:319;-1:-1;;13701:319;14135:854;14383:22;;14306:4;14297:14;;;14411:61;14301:3;14383:22;14411:61;;;14326:152;14564:4;14557:5;14553:16;14547:23;14576:62;14632:4;14627:3;14623:14;14610:11;14576:62;;;14488:156;14729:4;14722:5;14718:16;14712:23;14741:62;14797:4;14792:3;14788:14;14775:11;14741:62;;;14654:155;14894:4;14887:5;14883:16;14877:23;14906:62;14962:4;14957:3;14953:14;14940:11;14906:62;;;14819:155;14279:710;;;;15047:1801;15266:22;;15047:1801;;15190:5;15181:15;;;15294:61;15185:3;15266:22;15294:61;;;15211:150;15439:4;15432:5;15428:16;15422:23;15451:62;15507:4;15502:3;15498:14;15485:11;15451:62;;;15371:148;15596:4;15589:5;15585:16;15579:23;15608:62;15664:4;15659:3;15655:14;15642:11;15608:62;;;15529:147;15763:4;15756:5;15752:16;15746:23;15775:62;15831:4;15826:3;15822:14;15809:11;15775:62;;;15686:157;15931:4;15924:5;15920:16;15914:23;15943:62;15999:4;15994:3;15990:14;15977:11;15943:62;;;15853:158;16097:4;16090:5;16086:16;16080:23;16149:3;16143:4;16139:14;16132:4;16127:3;16123:14;16116:38;16169:98;16262:4;16249:11;16169:98;;;16161:106;;16021:258;16370:4;16363:5;16359:16;16353:23;16422:3;16416:4;16412:14;16405:4;16400:3;16396:14;16389:38;16442:98;16535:4;16522:11;16442:98;;;16434:106;;16289:263;16640:4;16633:5;16629:16;16623:23;16692:3;16686:4;16682:14;16675:4;16670:3;16666:14;16659:38;16712:98;16805:4;16792:11;16712:98;;16918:959;17141:22;;17071:4;17176:37;;;16918:959;;17062:14;;;;17228:98;17062:14;17141:22;17228:98;;;17220:106;;17091:247;17412:4;17405:5;17401:16;17395:23;17464:3;17458:4;17454:14;17447:4;17442:3;17438:14;17431:38;17484:98;17577:4;17564:11;17484:98;;;17476:106;;17348:246;17669:4;17662:5;17658:16;17652:23;17721:3;17715:4;17711:14;17704:4;17699:3;17695:14;17688:38;17741:98;17834:4;17821:11;17741:98;;17884:110;17957:31;17982:5;17957:31;;18128:213;18246:2;18231:18;;18260:71;18235:9;18304:6;18260:71;;18348:361;18516:2;18530:47;;;18501:18;;18591:108;18501:18;18685:6;18591:108;;18716:361;18884:2;18898:47;;;18869:18;;18959:108;18869:18;19053:6;18959:108;;19084:201;19196:2;19181:18;;19210:65;19185:9;19248:6;19210:65;;19292:239;19423:2;19408:18;;19437:84;19412:9;19494:6;19437:84;;19806:293;19940:2;19954:47;;;19925:18;;20015:74;19925:18;20075:6;20015:74;;20106:407;20297:2;20311:47;;;20282:18;;20372:131;20282:18;20372:131;;20520:407;20711:2;20725:47;;;20696:18;;20786:131;20696:18;20786:131;;20934:407;21125:2;21139:47;;;21110:18;;21200:131;21110:18;21200:131;;21348:407;21539:2;21553:47;;;21524:18;;21614:131;21524:18;21614:131;;21762:407;21953:2;21967:47;;;21938:18;;22028:131;21938:18;22028:131;;22176:407;22367:2;22381:47;;;22352:18;;22442:131;22352:18;22442:131;;22590:407;22781:2;22795:47;;;22766:18;;22856:131;22766:18;22856:131;;23004:370;23200:3;23185:19;;23215:149;23189:9;23337:6;23215:149;;23381:679;23625:3;23640:47;;;23610:19;;23701:100;23610:19;23787:6;23701:100;;;23693:108;;23812:72;23880:2;23869:9;23865:18;23856:6;23812:72;;;23895;23963:2;23952:9;23948:18;23939:6;23895:72;;;23978;24046:2;24035:9;24031:18;24022:6;23978:72;;24067:365;24237:2;24251:47;;;24222:18;;24312:110;24222:18;24408:6;24312:110;;24439:213;24557:2;24542:18;;24571:71;24546:9;24615:6;24571:71;;24659:256;24721:2;24715:9;24747:17;;;24822:18;24807:34;;24843:22;;;24804:62;24801:2;;;24879:1;24876;24869:12;24801:2;24895;24888:22;24699:216;;-1:-1;24699:216;24922:258;;25081:18;25073:6;25070:30;25067:2;;;25113:1;25110;25103:12;25067:2;-1:-1;25142:4;25130:17;;;25160:15;;25004:176;25454:117;25559:4;25547:17;;25528:43;25972:103;26058:12;;26042:33;27032:168;27140:19;;;27189:4;27180:14;;27133:67;27931:105;;28000:31;28025:5;28000:31;;28043:92;28116:13;28109:21;;28092:43;28142:128;-1:-1;;;;;28211:54;;28194:76;28574:122;;28660:31;28685:5;28660:31;;28924:88;29002:4;28991:16;;28974:38;29631:268;29696:1;29703:101;29717:6;29714:1;29711:13;29703:101;;;29784:11;;;29778:18;29765:11;;;29758:39;29739:2;29732:10;29703:101;;;29819:6;29816:1;29813:13;29810:2;;;-1:-1;;29884:1;29866:16;;29859:27;29680:219;29907:97;29995:2;29975:14;-1:-1;;29971:28;;29955:49

Swarm Source

bzzr://6d3467f1279a9b6072a74dcc80c2220e7a85372e3fe0138c772af4aa2aa143e8

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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