Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 11264890 | 1329 days ago | IN | Create: LoanMaintenance | 0 ETH | 0.10647491 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
LoanMaintenance
Compiler Version
v0.5.17+commit.d19bba13
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-11-15 */ /** * Copyright 2017-2020, bZeroX, LLC <https://bzx.network/>. All Rights Reserved. * Licensed under the Apache License, Version 2.0. */ pragma solidity 0.5.17; pragma experimental ABIEncoderV2; interface IWeth { function deposit() external payable; function withdraw(uint256 wad) external; } contract IERC20 { string public name; uint8 public decimals; string public symbol; function totalSupply() public view returns (uint256); function balanceOf(address _who) public view returns (uint256); function allowance(address _owner, address _spender) public view returns (uint256); function approve(address _spender, uint256 _value) public returns (bool); function transfer(address _to, uint256 _value) public returns (bool); function transferFrom(address _from, address _to, uint256 _value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } contract IWethERC20 is IWeth, IERC20 {} contract Constants { uint256 internal constant WEI_PRECISION = 10**18; uint256 internal constant WEI_PERCENT_PRECISION = 10**20; uint256 internal constant DAYS_IN_A_YEAR = 365; uint256 internal constant ONE_MONTH = 2628000; // approx. seconds in a month string internal constant UserRewardsID = "UserRewards"; string internal constant LoanDepositValueID = "LoanDepositValue"; IWethERC20 public constant wethToken = IWethERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); address public constant bzrxTokenAddress = 0x56d811088235F11C8920698a204A5010a788f4b3; address public constant vbzrxTokenAddress = 0xB72B31907C1C95F3650b64b2469e08EdACeE5e8F; } /** * @dev Library for managing loan sets * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * Include with `using EnumerableBytes32Set for EnumerableBytes32Set.Bytes32Set;`. * */ library EnumerableBytes32Set { struct Bytes32Set { // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (bytes32 => uint256) index; bytes32[] values; } /** * @dev Add an address value to a set. O(1). * Returns false if the value was already in the set. */ function addAddress(Bytes32Set storage set, address addrvalue) internal returns (bool) { bytes32 value; assembly { value := addrvalue } return addBytes32(set, value); } /** * @dev Add a value to a set. O(1). * Returns false if the value was already in the set. */ function addBytes32(Bytes32Set storage set, bytes32 value) internal returns (bool) { if (!contains(set, value)){ set.index[value] = set.values.push(value); return true; } else { return false; } } /** * @dev Removes an address value from a set. O(1). * Returns false if the value was not present in the set. */ function removeAddress(Bytes32Set storage set, address addrvalue) internal returns (bool) { bytes32 value; assembly { value := addrvalue } return removeBytes32(set, value); } /** * @dev Removes a value from a set. O(1). * Returns false if the value was not present in the set. */ function removeBytes32(Bytes32Set storage set, bytes32 value) internal returns (bool) { if (contains(set, value)){ uint256 toDeleteIndex = set.index[value] - 1; uint256 lastIndex = set.values.length - 1; // If the element we're deleting is the last one, we can just remove it without doing a swap if (lastIndex != toDeleteIndex) { bytes32 lastValue = set.values[lastIndex]; // Move the last value to the index where the deleted value is set.values[toDeleteIndex] = lastValue; // Update the index for the moved value set.index[lastValue] = toDeleteIndex + 1; // All indexes are 1-based } // Delete the index entry for the deleted value delete set.index[value]; // Delete the old entry for the moved value set.values.pop(); return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return set.index[value] != 0; } /** * @dev Returns true if the value is in the set. O(1). */ function containsAddress(Bytes32Set storage set, address addrvalue) internal view returns (bool) { bytes32 value; assembly { value := addrvalue } return set.index[value] != 0; } /** * @dev Returns an array with all values in the set. O(N). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * WARNING: This function may run out of gas on large sets: use {length} and * {get} instead in these cases. */ function enumerate(Bytes32Set storage set, uint256 start, uint256 count) internal view returns (bytes32[] memory output) { uint256 end = start + count; require(end >= start, "addition overflow"); end = set.values.length < end ? set.values.length : end; if (end == 0 || start >= end) { return output; } output = new bytes32[](end-start); for (uint256 i = start; i < end; i++) { output[i-start] = set.values[i]; } return output; } /** * @dev Returns the number of elements on the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return set.values.length; } /** @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function get(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return set.values[index]; } /** @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function getAddress(Bytes32Set storage set, uint256 index) internal view returns (address) { bytes32 value = set.values[index]; address addrvalue; assembly { addrvalue := value } return addrvalue; } } /** * @title Helps contracts guard against reentrancy attacks. * @author Remco Bloemen <remco@2π.com>, Eenae <[email protected]> * @dev If you mark a function `nonReentrant`, you should also * mark it `external`. */ contract ReentrancyGuard { /// @dev Constant for unlocked guard state - non-zero to prevent extra gas costs. /// See: https://github.com/OpenZeppelin/openzeppelin-solidity/issues/1056 uint256 internal constant REENTRANCY_GUARD_FREE = 1; /// @dev Constant for locked guard state uint256 internal constant REENTRANCY_GUARD_LOCKED = 2; /** * @dev We use a single lock for the whole contract. */ uint256 internal reentrancyLock = REENTRANCY_GUARD_FREE; /** * @dev Prevents a contract from calling itself, directly or indirectly. * If you mark a function `nonReentrant`, you should also * mark it `external`. Calling one `nonReentrant` function from * another is not supported. Instead, you can implement a * `private` function doing the actual work, and an `external` * wrapper marked as `nonReentrant`. */ modifier nonReentrant() { require(reentrancyLock == REENTRANCY_GUARD_FREE, "nonReentrant"); reentrancyLock = REENTRANCY_GUARD_LOCKED; _; reentrancyLock = REENTRANCY_GUARD_FREE; } } /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "unauthorized"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot 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-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b != 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Integer division of two numbers, rounding up and truncating the quotient */ function divCeil(uint256 a, uint256 b) internal pure returns (uint256) { return divCeil(a, b, "SafeMath: division by zero"); } /** * @dev Integer division of two numbers, rounding up and truncating the quotient */ function divCeil(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b != 0, errorMessage); if (a == 0) { return 0; } uint256 c = ((a - 1) / b) + 1; return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } function min256(uint256 _a, uint256 _b) internal pure returns (uint256) { return _a < _b ? _a : _b; } } /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * _Available since v2.4.0._ */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. * * _Available since v2.4.0._ */ function sendValue(address recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call.value(amount)(""); require(success, "Address: unable to send value, recipient may have reverted"); } } /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } contract LoanStruct { struct Loan { bytes32 id; // id of the loan bytes32 loanParamsId; // the linked loan params id bytes32 pendingTradesId; // the linked pending trades id uint256 principal; // total borrowed amount outstanding uint256 collateral; // total collateral escrowed for the loan uint256 startTimestamp; // loan start time uint256 endTimestamp; // for active loans, this is the expected loan end time, for in-active loans, is the actual (past) end time uint256 startMargin; // initial margin when the loan opened uint256 startRate; // reference rate when the loan opened for converting collateralToken to loanToken address borrower; // borrower of this loan address lender; // lender of this loan bool active; // if false, the loan has been fully closed } } contract LoanParamsStruct { struct LoanParams { bytes32 id; // id of loan params object bool active; // if false, this object has been disabled by the owner and can't be used for future loans address owner; // owner of this object address loanToken; // the token being loaned address collateralToken; // the required collateral token uint256 minInitialMargin; // the minimum allowed initial margin uint256 maintenanceMargin; // an unhealthy loan when current margin is at or below this value uint256 maxLoanTerm; // the maximum term for new loans (0 means there's no max term) } } contract OrderStruct { struct Order { uint256 lockedAmount; // escrowed amount waiting for a counterparty uint256 interestRate; // interest rate defined by the creator of this order uint256 minLoanTerm; // minimum loan term allowed uint256 maxLoanTerm; // maximum loan term allowed uint256 createdTimestamp; // timestamp when this order was created uint256 expirationTimestamp; // timestamp when this order expires } } contract LenderInterestStruct { struct LenderInterest { uint256 principalTotal; // total borrowed amount outstanding of asset uint256 owedPerDay; // interest owed per day for all loans of asset uint256 owedTotal; // total interest owed for all loans of asset (assuming they go to full term) uint256 paidTotal; // total interest paid so far for asset uint256 updatedTimestamp; // last update } } contract LoanInterestStruct { struct LoanInterest { uint256 owedPerDay; // interest owed per day for loan uint256 depositTotal; // total escrowed interest for loan uint256 updatedTimestamp; // last update } } contract Objects is LoanStruct, LoanParamsStruct, OrderStruct, LenderInterestStruct, LoanInterestStruct {} contract State is Constants, Objects, ReentrancyGuard, Ownable { using SafeMath for uint256; using EnumerableBytes32Set for EnumerableBytes32Set.Bytes32Set; address public priceFeeds; // handles asset reference price lookups address public swapsImpl; // handles asset swaps using dex liquidity mapping (bytes4 => address) public logicTargets; // implementations of protocol functions mapping (bytes32 => Loan) public loans; // loanId => Loan mapping (bytes32 => LoanParams) public loanParams; // loanParamsId => LoanParams mapping (address => mapping (bytes32 => Order)) public lenderOrders; // lender => orderParamsId => Order mapping (address => mapping (bytes32 => Order)) public borrowerOrders; // borrower => orderParamsId => Order mapping (bytes32 => mapping (address => bool)) public delegatedManagers; // loanId => delegated => approved // Interest mapping (address => mapping (address => LenderInterest)) public lenderInterest; // lender => loanToken => LenderInterest object mapping (bytes32 => LoanInterest) public loanInterest; // loanId => LoanInterest object // Internals EnumerableBytes32Set.Bytes32Set internal logicTargetsSet; // implementations set EnumerableBytes32Set.Bytes32Set internal activeLoansSet; // active loans set mapping (address => EnumerableBytes32Set.Bytes32Set) internal lenderLoanSets; // lender loans set mapping (address => EnumerableBytes32Set.Bytes32Set) internal borrowerLoanSets; // borrow loans set mapping (address => EnumerableBytes32Set.Bytes32Set) internal userLoanParamSets; // user loan params set address public feesController; // address controlling fee withdrawals uint256 public lendingFeePercent = 10 ether; // 10% fee // fee taken from lender interest payments mapping (address => uint256) public lendingFeeTokensHeld; // total interest fees received and not withdrawn per asset mapping (address => uint256) public lendingFeeTokensPaid; // total interest fees withdraw per asset (lifetime fees = lendingFeeTokensHeld + lendingFeeTokensPaid) uint256 public tradingFeePercent = 0.15 ether; // 0.15% fee // fee paid for each trade mapping (address => uint256) public tradingFeeTokensHeld; // total trading fees received and not withdrawn per asset mapping (address => uint256) public tradingFeeTokensPaid; // total trading fees withdraw per asset (lifetime fees = tradingFeeTokensHeld + tradingFeeTokensPaid) uint256 public borrowingFeePercent = 0.09 ether; // 0.09% fee // origination fee paid for each loan mapping (address => uint256) public borrowingFeeTokensHeld; // total borrowing fees received and not withdrawn per asset mapping (address => uint256) public borrowingFeeTokensPaid; // total borrowing fees withdraw per asset (lifetime fees = borrowingFeeTokensHeld + borrowingFeeTokensPaid) uint256 public protocolTokenHeld; // current protocol token deposit balance uint256 public protocolTokenPaid; // lifetime total payout of protocol token uint256 public affiliateFeePercent = 30 ether; // 30% fee share // fee share for affiliate program mapping (address => mapping (address => uint256)) public liquidationIncentivePercent; // percent discount on collateral for liquidators per loanToken and collateralToken mapping (address => address) public loanPoolToUnderlying; // loanPool => underlying mapping (address => address) public underlyingToLoanPool; // underlying => loanPool EnumerableBytes32Set.Bytes32Set internal loanPoolsSet; // loan pools set mapping (address => bool) public supportedTokens; // supported tokens for swaps uint256 public maxDisagreement = 5 ether; // % disagreement between swap rate and reference rate uint256 public sourceBufferPercent = 5 ether; // used to estimate kyber swap source amount uint256 public maxSwapSize = 1500 ether; // maximum supported swap size in ETH function _setTarget( bytes4 sig, address target) internal { logicTargets[sig] = target; if (target != address(0)) { logicTargetsSet.addBytes32(bytes32(sig)); } else { logicTargetsSet.removeBytes32(bytes32(sig)); } } } interface IPriceFeeds { function queryRate( address sourceToken, address destToken) external view returns (uint256 rate, uint256 precision); function queryPrecision( address sourceToken, address destToken) external view returns (uint256 precision); function queryReturn( address sourceToken, address destToken, uint256 sourceAmount) external view returns (uint256 destAmount); function checkPriceDisagreement( address sourceToken, address destToken, uint256 sourceAmount, uint256 destAmount, uint256 maxSlippage) external view returns (uint256 sourceToDestSwapRate); function amountInEth( address Token, uint256 amount) external view returns (uint256 ethAmount); function getMaxDrawdown( address loanToken, address collateralToken, uint256 loanAmount, uint256 collateralAmount, uint256 maintenanceMargin) external view returns (uint256); function getCurrentMarginAndCollateralSize( address loanToken, address collateralToken, uint256 loanAmount, uint256 collateralAmount) external view returns (uint256 currentMargin, uint256 collateralInEthAmount); function getCurrentMargin( address loanToken, address collateralToken, uint256 loanAmount, uint256 collateralAmount) external view returns (uint256 currentMargin, uint256 collateralToLoanRate); function shouldLiquidate( address loanToken, address collateralToken, uint256 loanAmount, uint256 collateralAmount, uint256 maintenanceMargin) external view returns (bool); function getFastGasPrice( address payToken) external view returns (uint256); } contract FeesEvents { enum FeeType { Lending, Trading, Borrowing, SettleInterest } event PayLendingFee( address indexed payer, address indexed token, uint256 amount ); event SettleFeeRewardForInterestExpense( address indexed payer, address indexed token, bytes32 indexed loanId, uint256 amount ); event PayTradingFee( address indexed payer, address indexed token, bytes32 indexed loanId, uint256 amount ); event PayBorrowingFee( address indexed payer, address indexed token, bytes32 indexed loanId, uint256 amount ); event EarnReward( address indexed receiver, bytes32 indexed loanId, FeeType indexed feeType, address token, uint256 amount ); } contract FeesHelper is State, FeesEvents { using SafeERC20 for IERC20; // calculate trading fee function _getTradingFee( uint256 feeTokenAmount) internal view returns (uint256) { return feeTokenAmount .mul(tradingFeePercent) .divCeil(WEI_PERCENT_PRECISION); } // calculate loan origination fee function _getBorrowingFee( uint256 feeTokenAmount) internal view returns (uint256) { return feeTokenAmount .mul(borrowingFeePercent) .divCeil(WEI_PERCENT_PRECISION); } // settle trading fee function _payTradingFee( address user, bytes32 loanId, address feeToken, uint256 tradingFee) internal { if (tradingFee != 0) { tradingFeeTokensHeld[feeToken] = tradingFeeTokensHeld[feeToken] .add(tradingFee); emit PayTradingFee( user, feeToken, loanId, tradingFee ); _payFeeReward( user, loanId, feeToken, tradingFee, FeeType.Trading ); } } // settle loan origination fee function _payBorrowingFee( address user, bytes32 loanId, address feeToken, uint256 borrowingFee) internal { if (borrowingFee != 0) { borrowingFeeTokensHeld[feeToken] = borrowingFeeTokensHeld[feeToken] .add(borrowingFee); emit PayBorrowingFee( user, feeToken, loanId, borrowingFee ); _payFeeReward( user, loanId, feeToken, borrowingFee, FeeType.Borrowing ); } } // settle lender (interest) fee function _payLendingFee( address user, address feeToken, uint256 lendingFee) internal { if (lendingFee != 0) { lendingFeeTokensHeld[feeToken] = lendingFeeTokensHeld[feeToken] .add(lendingFee); emit PayLendingFee( user, feeToken, lendingFee ); //// NOTE: Lenders do not receive a fee reward //// } } // settles and pays borrowers based on the fees generated by their interest payments function _settleFeeRewardForInterestExpense( LoanInterest storage loanInterestLocal, bytes32 loanId, address feeToken, address user, uint256 interestTime) internal { uint256 updatedTimestamp = loanInterestLocal.updatedTimestamp; uint256 interestExpenseFee; if (updatedTimestamp != 0) { // this represents the fee generated by a borrower's interest payment interestExpenseFee = interestTime .sub(updatedTimestamp) .mul(loanInterestLocal.owedPerDay) .mul(lendingFeePercent) .div(1 days * WEI_PERCENT_PRECISION); } loanInterestLocal.updatedTimestamp = interestTime; if (interestExpenseFee != 0) { emit SettleFeeRewardForInterestExpense( user, feeToken, loanId, interestExpenseFee ); _payFeeReward( user, loanId, feeToken, interestExpenseFee, FeeType.SettleInterest ); } } // pay protocolToken reward to user function _payFeeReward( address user, bytes32 loanId, address feeToken, uint256 feeAmount, FeeType feeType) internal { // The protocol is designed to allow positions and loans to be closed, if for whatever reason // the price lookup is failing, returning 0, or is otherwise paused. Therefore, we allow this // call to fail silently, rather than revert, to allow the transaction to continue without a // BZRX token reward. uint256 rewardAmount; address _priceFeeds = priceFeeds; (bool success, bytes memory data) = _priceFeeds.staticcall( abi.encodeWithSelector( IPriceFeeds(_priceFeeds).queryReturn.selector, feeToken, bzrxTokenAddress, // price rewards using BZRX price rather than vesting token price feeAmount / 2 // 50% of fee value ) ); assembly { if eq(success, 1) { rewardAmount := mload(add(data, 32)) } } if (rewardAmount != 0) { uint256 tokenBalance = protocolTokenHeld; if (rewardAmount > tokenBalance) { rewardAmount = tokenBalance; } if (rewardAmount != 0) { protocolTokenHeld = tokenBalance .sub(rewardAmount); bytes32 slot = keccak256(abi.encodePacked(user, UserRewardsID)); assembly { sstore(slot, add(sload(slot), rewardAmount)) } emit EarnReward( user, loanId, feeType, vbzrxTokenAddress, // rewardToken rewardAmount ); } } } } contract VaultController is Constants { using SafeERC20 for IERC20; event VaultDeposit( address indexed asset, address indexed from, uint256 amount ); event VaultWithdraw( address indexed asset, address indexed to, uint256 amount ); function vaultEtherDeposit( address from, uint256 value) internal { IWethERC20 _wethToken = wethToken; _wethToken.deposit.value(value)(); emit VaultDeposit( address(_wethToken), from, value ); } function vaultEtherWithdraw( address to, uint256 value) internal { if (value != 0) { IWethERC20 _wethToken = wethToken; uint256 balance = address(this).balance; if (value > balance) { _wethToken.withdraw(value - balance); } Address.sendValue(to, value); emit VaultWithdraw( address(_wethToken), to, value ); } } function vaultDeposit( address token, address from, uint256 value) internal { if (value != 0) { IERC20(token).safeTransferFrom( from, address(this), value ); emit VaultDeposit( token, from, value ); } } function vaultWithdraw( address token, address to, uint256 value) internal { if (value != 0) { IERC20(token).safeTransfer( to, value ); emit VaultWithdraw( token, to, value ); } } function vaultTransfer( address token, address from, address to, uint256 value) internal { if (value != 0) { if (from == address(this)) { IERC20(token).safeTransfer( to, value ); } else { IERC20(token).safeTransferFrom( from, to, value ); } } } function vaultApprove( address token, address to, uint256 value) internal { if (value != 0 && IERC20(token).allowance(address(this), to) != 0) { IERC20(token).safeApprove(to, 0); } IERC20(token).safeApprove(to, value); } } contract InterestUser is State, VaultController, FeesHelper { using SafeERC20 for IERC20; function _payInterest( address lender, address interestToken) internal { LenderInterest storage lenderInterestLocal = lenderInterest[lender][interestToken]; uint256 interestOwedNow = 0; if (lenderInterestLocal.owedPerDay != 0 && lenderInterestLocal.updatedTimestamp != 0) { interestOwedNow = block.timestamp .sub(lenderInterestLocal.updatedTimestamp) .mul(lenderInterestLocal.owedPerDay) .div(1 days); lenderInterestLocal.updatedTimestamp = block.timestamp; if (interestOwedNow > lenderInterestLocal.owedTotal) interestOwedNow = lenderInterestLocal.owedTotal; if (interestOwedNow != 0) { lenderInterestLocal.paidTotal = lenderInterestLocal.paidTotal .add(interestOwedNow); lenderInterestLocal.owedTotal = lenderInterestLocal.owedTotal .sub(interestOwedNow); _payInterestTransfer( lender, interestToken, interestOwedNow ); } } else { lenderInterestLocal.updatedTimestamp = block.timestamp; } } function _payInterestTransfer( address lender, address interestToken, uint256 interestOwedNow) internal { uint256 lendingFee = interestOwedNow .mul(lendingFeePercent) .divCeil(WEI_PERCENT_PRECISION); _payLendingFee( lender, interestToken, lendingFee ); // transfers the interest to the lender, less the interest fee vaultWithdraw( interestToken, lender, interestOwedNow .sub(lendingFee) ); } } contract LiquidationHelper is State { function _getLiquidationAmounts( uint256 principal, uint256 collateral, uint256 currentMargin, uint256 maintenanceMargin, uint256 collateralToLoanRate, uint256 incentivePercent) internal view returns (uint256 maxLiquidatable, uint256 maxSeizable) { if (currentMargin > maintenanceMargin || collateralToLoanRate == 0) { return (maxLiquidatable, maxSeizable); } else if (currentMargin <= incentivePercent) { return (principal, collateral); } uint256 desiredMargin = maintenanceMargin .add(5 ether); // 5 percentage points above maintenance // maxLiquidatable = ((1 + desiredMargin)*principal - collateralToLoanRate*collateral) / (desiredMargin - incentivePercent) maxLiquidatable = desiredMargin .add(WEI_PERCENT_PRECISION) .mul(principal) .div(WEI_PERCENT_PRECISION); maxLiquidatable = maxLiquidatable .sub( collateral .mul(collateralToLoanRate) .div(WEI_PRECISION) ); maxLiquidatable = maxLiquidatable .mul(WEI_PERCENT_PRECISION) .div( desiredMargin .sub(incentivePercent) ); if (maxLiquidatable > principal) { maxLiquidatable = principal; } // maxSeizable = maxLiquidatable * (1 + incentivePercent) / collateralToLoanRate maxSeizable = maxLiquidatable .mul( incentivePercent .add(WEI_PERCENT_PRECISION) ); maxSeizable = maxSeizable .div(collateralToLoanRate) .div(100); if (maxSeizable > collateral) { maxSeizable = collateral; } return (maxLiquidatable, maxSeizable); } } contract SwapsEvents { event LoanSwap( bytes32 indexed loanId, address indexed sourceToken, address indexed destToken, address borrower, uint256 sourceAmount, uint256 destAmount ); event ExternalSwap( address indexed user, address indexed sourceToken, address indexed destToken, uint256 sourceAmount, uint256 destAmount ); } interface ISwapsImpl { function dexSwap( address sourceTokenAddress, address destTokenAddress, address receiverAddress, address returnToSenderAddress, uint256 minSourceTokenAmount, uint256 maxSourceTokenAmount, uint256 requiredDestTokenAmount) external returns (uint256 destTokenAmountReceived, uint256 sourceTokenAmountUsed); function dexExpectedRate( address sourceTokenAddress, address destTokenAddress, uint256 sourceTokenAmount) external view returns (uint256); } contract SwapsUser is State, SwapsEvents, FeesHelper { function _loanSwap( bytes32 loanId, address sourceToken, address destToken, address user, uint256 minSourceTokenAmount, uint256 maxSourceTokenAmount, uint256 requiredDestTokenAmount, bool bypassFee, bytes memory loanDataBytes) internal returns (uint256 destTokenAmountReceived, uint256 sourceTokenAmountUsed, uint256 sourceToDestSwapRate) { (destTokenAmountReceived, sourceTokenAmountUsed) = _swapsCall( [ sourceToken, destToken, address(this), // receiver address(this), // returnToSender user ], [ minSourceTokenAmount, maxSourceTokenAmount, requiredDestTokenAmount ], loanId, bypassFee, loanDataBytes ); // will revert if swap size too large _checkSwapSize(sourceToken, sourceTokenAmountUsed); // will revert if disagreement found sourceToDestSwapRate = IPriceFeeds(priceFeeds).checkPriceDisagreement( sourceToken, destToken, sourceTokenAmountUsed, destTokenAmountReceived, maxDisagreement ); emit LoanSwap( loanId, sourceToken, destToken, user, sourceTokenAmountUsed, destTokenAmountReceived ); } function _swapsCall( address[5] memory addrs, uint256[3] memory vals, bytes32 loanId, bool miscBool, // bypassFee bytes memory loanDataBytes) internal returns (uint256, uint256) { //addrs[0]: sourceToken //addrs[1]: destToken //addrs[2]: receiver //addrs[3]: returnToSender //addrs[4]: user //vals[0]: minSourceTokenAmount //vals[1]: maxSourceTokenAmount //vals[2]: requiredDestTokenAmount require(vals[0] != 0, "sourceAmount == 0"); uint256 destTokenAmountReceived; uint256 sourceTokenAmountUsed; uint256 tradingFee; if (!miscBool) { // bypassFee if (vals[2] == 0) { // condition: vals[0] will always be used as sourceAmount tradingFee = _getTradingFee(vals[0]); if (tradingFee != 0) { _payTradingFee( addrs[4], // user loanId, addrs[0], // sourceToken tradingFee ); vals[0] = vals[0] .sub(tradingFee); } } else { // condition: unknown sourceAmount will be used tradingFee = _getTradingFee(vals[2]); if (tradingFee != 0) { vals[2] = vals[2] .add(tradingFee); } } } if (vals[1] == 0) { vals[1] = vals[0]; } else { require(vals[0] <= vals[1], "min greater than max"); } require(loanDataBytes.length == 0, "invalid state"); (destTokenAmountReceived, sourceTokenAmountUsed) = _swapsCall_internal( addrs, vals ); if (vals[2] == 0) { // there's no minimum destTokenAmount, but all of vals[0] (minSourceTokenAmount) must be spent, and amount spent can't exceed vals[0] require(sourceTokenAmountUsed == vals[0], "swap too large to fill"); if (tradingFee != 0) { sourceTokenAmountUsed = sourceTokenAmountUsed + tradingFee; // will never overflow } } else { // there's a minimum destTokenAmount required, but sourceTokenAmountUsed won't be greater than vals[1] (maxSourceTokenAmount) require(sourceTokenAmountUsed <= vals[1], "swap fill too large"); require(destTokenAmountReceived >= vals[2], "insufficient swap liquidity"); if (tradingFee != 0) { _payTradingFee( addrs[4], // user loanId, // loanId, addrs[1], // destToken tradingFee ); destTokenAmountReceived = destTokenAmountReceived - tradingFee; // will never overflow } } return (destTokenAmountReceived, sourceTokenAmountUsed); } function _swapsCall_internal( address[5] memory addrs, uint256[3] memory vals) internal returns (uint256 destTokenAmountReceived, uint256 sourceTokenAmountUsed) { bytes memory data = abi.encodeWithSelector( ISwapsImpl(swapsImpl).dexSwap.selector, addrs[0], // sourceToken addrs[1], // destToken addrs[2], // receiverAddress addrs[3], // returnToSenderAddress vals[0], // minSourceTokenAmount vals[1], // maxSourceTokenAmount vals[2] // requiredDestTokenAmount ); bool success; (success, data) = swapsImpl.delegatecall(data); require(success, "swap failed"); (destTokenAmountReceived, sourceTokenAmountUsed) = abi.decode(data, (uint256, uint256)); } function _swapsExpectedReturn( address sourceToken, address destToken, uint256 sourceTokenAmount) internal view returns (uint256) { uint256 tradingFee = _getTradingFee(sourceTokenAmount); if (tradingFee != 0) { sourceTokenAmount = sourceTokenAmount .sub(tradingFee); } uint256 sourceToDestRate = ISwapsImpl(swapsImpl).dexExpectedRate( sourceToken, destToken, sourceTokenAmount ); uint256 sourceToDestPrecision = IPriceFeeds(priceFeeds).queryPrecision( sourceToken, destToken ); return sourceTokenAmount .mul(sourceToDestRate) .div(sourceToDestPrecision); } function _checkSwapSize( address tokenAddress, uint256 amount) internal view { uint256 _maxSwapSize = maxSwapSize; if (_maxSwapSize != 0) { uint256 amountInEth; if (tokenAddress == address(wethToken)) { amountInEth = amount; } else { amountInEth = IPriceFeeds(priceFeeds).amountInEth(tokenAddress, amount); } require(amountInEth <= _maxSwapSize, "swap too large"); } } } contract LoanMaintenanceEvents { event DepositCollateral( address indexed user, address indexed depositToken, bytes32 indexed loanId, uint256 depositAmount ); event WithdrawCollateral( address indexed user, address indexed withdrawToken, bytes32 indexed loanId, uint256 withdrawAmount ); event ExtendLoanDuration( address indexed user, address indexed depositToken, bytes32 indexed loanId, uint256 depositAmount, uint256 collateralUsedAmount, uint256 newEndTimestamp ); event ReduceLoanDuration( address indexed user, address indexed withdrawToken, bytes32 indexed loanId, uint256 withdrawAmount, uint256 newEndTimestamp ); event LoanDeposit( bytes32 indexed loanId, uint256 depositValueAsLoanToken, uint256 depositValueAsCollateralToken ); event ClaimReward( address indexed user, address indexed receiver, address indexed token, uint256 amount ); enum LoanType { All, Margin, NonMargin } struct LoanReturnData { bytes32 loanId; // id of the loan uint96 endTimestamp; // loan end timestamp address loanToken; // loan token address address collateralToken; // collateral token address uint256 principal; // principal amount of the loan uint256 collateral; // collateral amount of the loan uint256 interestOwedPerDay; // interest owned per day uint256 interestDepositRemaining; // remaining unspent interest uint256 startRate; // collateralToLoanRate uint256 startMargin; // margin with which loan was open uint256 maintenanceMargin; // maintenance margin uint256 currentMargin; /// current margin uint256 maxLoanTerm; // maximum term of the loan uint256 maxLiquidatable; // current max liquidatable uint256 maxSeizable; // current max seizable uint256 depositValueAsLoanToken; // net value of deposit denominated as loanToken uint256 depositValueAsCollateralToken; // net value of deposit denominated as collateralToken } } contract LoanMaintenance is State, LoanMaintenanceEvents, VaultController, InterestUser, SwapsUser, LiquidationHelper { function initialize( address target) external onlyOwner { _setTarget(this.depositCollateral.selector, target); _setTarget(this.withdrawCollateral.selector, target); _setTarget(this.withdrawAccruedInterest.selector, target); _setTarget(this.extendLoanDuration.selector, target); _setTarget(this.reduceLoanDuration.selector, target); _setTarget(this.setDepositAmount.selector, target); _setTarget(this.claimRewards.selector, target); _setTarget(this.rewardsBalanceOf.selector, target); _setTarget(this.getLenderInterestData.selector, target); _setTarget(this.getLoanInterestData.selector, target); _setTarget(this.getUserLoans.selector, target); _setTarget(this.getUserLoansCount.selector, target); _setTarget(this.getLoan.selector, target); _setTarget(this.getActiveLoans.selector, target); _setTarget(this.getActiveLoansCount.selector, target); } function depositCollateral( bytes32 loanId, uint256 depositAmount) // must match msg.value if ether is sent external payable nonReentrant { require(depositAmount != 0, "depositAmount is 0"); Loan storage loanLocal = loans[loanId]; require(loanLocal.active, "loan is closed"); LoanParams storage loanParamsLocal = loanParams[loanLocal.loanParamsId]; address collateralToken = loanParamsLocal.collateralToken; uint256 collateral = loanLocal.collateral; require(msg.value == 0 || collateralToken == address(wethToken), "wrong asset sent"); collateral = collateral .add(depositAmount); loanLocal.collateral = collateral; if (msg.value == 0) { vaultDeposit( collateralToken, msg.sender, depositAmount ); } else { require(msg.value == depositAmount, "ether deposit mismatch"); vaultEtherDeposit( msg.sender, msg.value ); } // update deposit amount (uint256 collateralToLoanRate, uint256 collateralToLoanPrecision) = IPriceFeeds(priceFeeds).queryRate( collateralToken, loanParamsLocal.loanToken ); if (collateralToLoanRate != 0) { _setDepositAmount( loanId, depositAmount .mul(collateralToLoanRate) .div(collateralToLoanPrecision), depositAmount, false // isSubtraction ); } emit DepositCollateral( loanLocal.borrower, collateralToken, loanId, depositAmount ); } function withdrawCollateral( bytes32 loanId, address receiver, uint256 withdrawAmount) external nonReentrant returns (uint256 actualWithdrawAmount) { require(withdrawAmount != 0, "withdrawAmount is 0"); Loan storage loanLocal = loans[loanId]; LoanParams storage loanParamsLocal = loanParams[loanLocal.loanParamsId]; require(loanLocal.active, "loan is closed"); require( msg.sender == loanLocal.borrower || delegatedManagers[loanLocal.id][msg.sender], "unauthorized" ); address collateralToken = loanParamsLocal.collateralToken; uint256 collateral = loanLocal.collateral; uint256 maxDrawdown = IPriceFeeds(priceFeeds).getMaxDrawdown( loanParamsLocal.loanToken, collateralToken, loanLocal.principal, collateral, loanParamsLocal.maintenanceMargin ); if (withdrawAmount > maxDrawdown) { actualWithdrawAmount = maxDrawdown; } else { actualWithdrawAmount = withdrawAmount; } collateral = collateral .sub(actualWithdrawAmount, "withdrawAmount too high"); loanLocal.collateral = collateral; if (collateralToken == address(wethToken)) { vaultEtherWithdraw( receiver, actualWithdrawAmount ); } else { vaultWithdraw( collateralToken, receiver, actualWithdrawAmount ); } // update deposit amount (uint256 collateralToLoanRate, uint256 collateralToLoanPrecision) = IPriceFeeds(priceFeeds).queryRate( collateralToken, loanParamsLocal.loanToken ); if (collateralToLoanRate != 0) { _setDepositAmount( loanId, actualWithdrawAmount .mul(collateralToLoanRate) .div(collateralToLoanPrecision), actualWithdrawAmount, true // isSubtraction ); } emit WithdrawCollateral( loanLocal.borrower, collateralToken, loanId, actualWithdrawAmount ); } function withdrawAccruedInterest( address loanToken) external { // pay outstanding interest to lender _payInterest( msg.sender, // lender loanToken ); } function extendLoanDuration( bytes32 loanId, uint256 depositAmount, bool useCollateral, bytes calldata /*loanDataBytes*/) // for future use external payable nonReentrant returns (uint256 secondsExtended) { require(depositAmount != 0, "depositAmount is 0"); Loan storage loanLocal = loans[loanId]; LoanParams storage loanParamsLocal = loanParams[loanLocal.loanParamsId]; require(loanLocal.active, "loan is closed"); require( !useCollateral || msg.sender == loanLocal.borrower || delegatedManagers[loanLocal.id][msg.sender], "unauthorized" ); require(loanParamsLocal.maxLoanTerm == 0, "indefinite-term only"); require(msg.value == 0 || (!useCollateral && loanParamsLocal.loanToken == address(wethToken)), "wrong asset sent"); // pay outstanding interest to lender _payInterest( loanLocal.lender, loanParamsLocal.loanToken ); LoanInterest storage loanInterestLocal = loanInterest[loanLocal.id]; _settleFeeRewardForInterestExpense( loanInterestLocal, loanLocal.id, loanParamsLocal.loanToken, loanLocal.borrower, block.timestamp ); // Handle back interest: calculates interest owned since the loan endtime passed but the loan remained open uint256 backInterestOwed; if (block.timestamp > loanLocal.endTimestamp) { backInterestOwed = block.timestamp .sub(loanLocal.endTimestamp); backInterestOwed = backInterestOwed .mul(loanInterestLocal.owedPerDay); backInterestOwed = backInterestOwed .div(1 days); require(depositAmount > backInterestOwed, "deposit cannot cover back interest"); } // deposit interest uint256 collateralUsed; if (useCollateral) { collateralUsed = _doSwapWithCollateral( loanLocal, loanParamsLocal, depositAmount ); } else { if (msg.value == 0) { vaultDeposit( loanParamsLocal.loanToken, msg.sender, depositAmount ); } else { require(msg.value == depositAmount, "ether deposit mismatch"); vaultEtherDeposit( msg.sender, msg.value ); } } if (backInterestOwed != 0) { depositAmount = depositAmount .sub(backInterestOwed); // pay out backInterestOwed _payInterestTransfer( loanLocal.lender, loanParamsLocal.loanToken, backInterestOwed ); } secondsExtended = depositAmount .mul(1 days) .div(loanInterestLocal.owedPerDay); loanLocal.endTimestamp = loanLocal.endTimestamp .add(secondsExtended); require(loanLocal.endTimestamp > block.timestamp && (loanLocal.endTimestamp - block.timestamp) > 1 hours, "loan too short" ); loanInterestLocal.depositTotal = loanInterestLocal.depositTotal .add(depositAmount); lenderInterest[loanLocal.lender][loanParamsLocal.loanToken].owedTotal = lenderInterest[loanLocal.lender][loanParamsLocal.loanToken].owedTotal .add(depositAmount); emit ExtendLoanDuration( loanLocal.borrower, loanParamsLocal.loanToken, loanId, depositAmount, collateralUsed, loanLocal.endTimestamp ); } function reduceLoanDuration( bytes32 loanId, address receiver, uint256 withdrawAmount) external nonReentrant returns (uint256 secondsReduced) { require(withdrawAmount != 0, "withdrawAmount is 0"); Loan storage loanLocal = loans[loanId]; LoanParams storage loanParamsLocal = loanParams[loanLocal.loanParamsId]; require(loanLocal.active, "loan is closed"); require( msg.sender == loanLocal.borrower || delegatedManagers[loanLocal.id][msg.sender], "unauthorized" ); require(loanParamsLocal.maxLoanTerm == 0, "indefinite-term only"); require(loanLocal.endTimestamp > block.timestamp, "loan term has ended"); // pay outstanding interest to lender _payInterest( loanLocal.lender, loanParamsLocal.loanToken ); LoanInterest storage loanInterestLocal = loanInterest[loanLocal.id]; _settleFeeRewardForInterestExpense( loanInterestLocal, loanLocal.id, loanParamsLocal.loanToken, loanLocal.borrower, block.timestamp ); uint256 interestDepositRemaining = loanLocal.endTimestamp .sub(block.timestamp) .mul(loanInterestLocal.owedPerDay) .div(1 days); require(withdrawAmount < interestDepositRemaining, "withdraw amount too high"); // withdraw interest if (loanParamsLocal.loanToken == address(wethToken)) { vaultEtherWithdraw( receiver, withdrawAmount ); } else { vaultWithdraw( loanParamsLocal.loanToken, receiver, withdrawAmount ); } secondsReduced = withdrawAmount .mul(1 days) .div(loanInterestLocal.owedPerDay); require (loanLocal.endTimestamp > secondsReduced, "loan too short"); loanLocal.endTimestamp = loanLocal.endTimestamp .sub(secondsReduced); require(loanLocal.endTimestamp > block.timestamp && (loanLocal.endTimestamp - block.timestamp) > 1 hours, "loan too short" ); loanInterestLocal.depositTotal = loanInterestLocal.depositTotal .sub(withdrawAmount); lenderInterest[loanLocal.lender][loanParamsLocal.loanToken].owedTotal = lenderInterest[loanLocal.lender][loanParamsLocal.loanToken].owedTotal .sub(withdrawAmount); emit ReduceLoanDuration( loanLocal.borrower, loanParamsLocal.loanToken, loanId, withdrawAmount, loanLocal.endTimestamp ); } function setDepositAmount( bytes32 loanId, uint256 depositValueAsLoanToken, uint256 depositValueAsCollateralToken) external { // only callable by loan pools require(loanPoolToUnderlying[msg.sender] != address(0), "not authorized"); _setDepositAmount( loanId, depositValueAsLoanToken, depositValueAsCollateralToken, false // isSubtraction ); } function claimRewards( address receiver) external returns (uint256 claimAmount) { bytes32 slot = keccak256(abi.encodePacked(msg.sender, UserRewardsID)); assembly { claimAmount := sload(slot) } if (claimAmount != 0) { assembly { sstore(slot, 0) } protocolTokenPaid = protocolTokenPaid .add(claimAmount); IERC20(vbzrxTokenAddress).transfer( receiver, claimAmount ); emit ClaimReward( msg.sender, receiver, vbzrxTokenAddress, claimAmount ); } } function rewardsBalanceOf( address user) external view returns (uint256 rewardsBalance) { bytes32 slot = keccak256(abi.encodePacked(user, UserRewardsID)); assembly { rewardsBalance := sload(slot) } } /// @dev Gets current lender interest data totals for all loans with a specific oracle and interest token /// @param lender The lender address /// @param loanToken The loan token address /// @return interestPaid The total amount of interest that has been paid to a lender so far /// @return interestPaidDate The date of the last interest pay out, or 0 if no interest has been withdrawn yet /// @return interestOwedPerDay The amount of interest the lender is earning per day /// @return interestUnPaid The total amount of interest the lender is owned and not yet withdrawn /// @return interestFeePercent The fee retained by the protocol before interest is paid to the lender /// @return principalTotal The total amount of outstading principal the lender has loaned function getLenderInterestData( address lender, address loanToken) external view returns ( uint256 interestPaid, uint256 interestPaidDate, uint256 interestOwedPerDay, uint256 interestUnPaid, uint256 interestFeePercent, uint256 principalTotal) { LenderInterest memory lenderInterestLocal = lenderInterest[lender][loanToken]; interestUnPaid = block.timestamp.sub(lenderInterestLocal.updatedTimestamp).mul(lenderInterestLocal.owedPerDay).div(1 days); if (interestUnPaid > lenderInterestLocal.owedTotal) interestUnPaid = lenderInterestLocal.owedTotal; return ( lenderInterestLocal.paidTotal, lenderInterestLocal.paidTotal != 0 ? lenderInterestLocal.updatedTimestamp : 0, lenderInterestLocal.owedPerDay, lenderInterestLocal.updatedTimestamp != 0 ? interestUnPaid : 0, lendingFeePercent, lenderInterestLocal.principalTotal ); } /// @dev Gets current interest data for a loan /// @param loanId A unique id representing the loan /// @return loanToken The loan token that interest is paid in /// @return interestOwedPerDay The amount of interest the borrower is paying per day /// @return interestDepositTotal The total amount of interest the borrower has deposited /// @return interestDepositRemaining The amount of deposited interest that is not yet owed to a lender function getLoanInterestData( bytes32 loanId) external view returns ( address loanToken, uint256 interestOwedPerDay, uint256 interestDepositTotal, uint256 interestDepositRemaining) { loanToken = loanParams[loans[loanId].loanParamsId].loanToken; interestOwedPerDay = loanInterest[loanId].owedPerDay; interestDepositTotal = loanInterest[loanId].depositTotal; uint256 endTimestamp = loans[loanId].endTimestamp; uint256 interestTime = block.timestamp > endTimestamp ? endTimestamp : block.timestamp; interestDepositRemaining = endTimestamp > interestTime ? endTimestamp .sub(interestTime) .mul(interestOwedPerDay) .div(1 days) : 0; } // Only returns data for loans that are active // All(0): all loans // Margin(1): margin trade loans // NonMargin(2): non-margin trade loans // only active loans are returned function getUserLoans( address user, uint256 start, uint256 count, LoanType loanType, bool isLender, bool unsafeOnly) external view returns (LoanReturnData[] memory loansData) { EnumerableBytes32Set.Bytes32Set storage set = isLender ? lenderLoanSets[user] : borrowerLoanSets[user]; uint256 end = start.add(count).min256(set.length()); if (start >= end) { return loansData; } count = end-start; uint256 idx = count; LoanReturnData memory loanData; loansData = new LoanReturnData[](idx); for (uint256 i = --end; i >= start; i--) { loanData = _getLoan( set.get(i), // loanId loanType, unsafeOnly ); if (loanData.loanId == 0) { if (i == 0) { break; } else { continue; } } loansData[count-(idx--)] = loanData; if (i == 0) { break; } } if (idx != 0) { count -= idx; assembly { mstore(loansData, count) } } } function getUserLoansCount( address user, bool isLender) external view returns (uint256) { return isLender ? lenderLoanSets[user].length() : borrowerLoanSets[user].length(); } function getLoan( bytes32 loanId) external view returns (LoanReturnData memory loanData) { return _getLoan( loanId, LoanType.All, false // unsafeOnly ); } function getActiveLoans( uint256 start, uint256 count, bool unsafeOnly) external view returns (LoanReturnData[] memory loansData) { uint256 end = start.add(count).min256(activeLoansSet.length()); if (start >= end) { return loansData; } count = end-start; uint256 idx = count; LoanReturnData memory loanData; loansData = new LoanReturnData[](idx); for (uint256 i = --end; i >= start; i--) { loanData = _getLoan( activeLoansSet.get(i), // loanId LoanType.All, unsafeOnly ); if (loanData.loanId == 0) { if (i == 0) { break; } else { continue; } } loansData[count-(idx--)] = loanData; if (i == 0) { break; } } if (idx != 0) { count -= idx; assembly { mstore(loansData, count) } } } function getActiveLoansCount() external view returns (uint256) { return activeLoansSet.length(); } function _getLoan( bytes32 loanId, LoanType loanType, bool unsafeOnly) internal view returns (LoanReturnData memory loanData) { Loan memory loanLocal = loans[loanId]; LoanParams memory loanParamsLocal = loanParams[loanLocal.loanParamsId]; if ((loanType == LoanType.Margin && loanParamsLocal.maxLoanTerm == 0) || (loanType == LoanType.NonMargin && loanParamsLocal.maxLoanTerm != 0)) { return loanData; } LoanInterest memory loanInterestLocal = loanInterest[loanId]; (uint256 currentMargin, uint256 value) = IPriceFeeds(priceFeeds).getCurrentMargin( // currentMargin, collateralToLoanRate loanParamsLocal.loanToken, loanParamsLocal.collateralToken, loanLocal.principal, loanLocal.collateral ); uint256 maxLiquidatable; uint256 maxSeizable; if (currentMargin <= loanParamsLocal.maintenanceMargin) { (maxLiquidatable, maxSeizable) = _getLiquidationAmounts( loanLocal.principal, loanLocal.collateral, currentMargin, loanParamsLocal.maintenanceMargin, value, // collateralToLoanRate liquidationIncentivePercent[loanParamsLocal.loanToken][loanParamsLocal.collateralToken] ); } else if (unsafeOnly) { return loanData; } uint256 depositValueAsLoanToken; uint256 depositValueAsCollateralToken; bytes32 slot = keccak256(abi.encode(loanId, LoanDepositValueID)); assembly { depositValueAsLoanToken := sload(slot) depositValueAsCollateralToken := sload(add(slot, 1)) } if (loanLocal.endTimestamp > block.timestamp) { value = loanLocal.endTimestamp .sub(block.timestamp) .mul(loanInterestLocal.owedPerDay) .div(1 days); } else { value = 0; } return LoanReturnData({ loanId: loanId, endTimestamp: uint96(loanLocal.endTimestamp), loanToken: loanParamsLocal.loanToken, collateralToken: loanParamsLocal.collateralToken, principal: loanLocal.principal, collateral: loanLocal.collateral, interestOwedPerDay: loanInterestLocal.owedPerDay, interestDepositRemaining: value, startRate: loanLocal.startRate, startMargin: loanLocal.startMargin, maintenanceMargin: loanParamsLocal.maintenanceMargin, currentMargin: currentMargin, maxLoanTerm: loanParamsLocal.maxLoanTerm, maxLiquidatable: maxLiquidatable, maxSeizable: maxSeizable, depositValueAsLoanToken: depositValueAsLoanToken, depositValueAsCollateralToken: depositValueAsCollateralToken }); } function _doSwapWithCollateral( Loan storage loanLocal, LoanParams memory loanParamsLocal, uint256 depositAmount) internal returns (uint256) { // reverts in _loanSwap if amountNeeded can't be bought (,uint256 sourceTokenAmountUsed,) = _loanSwap( loanLocal.id, loanParamsLocal.collateralToken, loanParamsLocal.loanToken, loanLocal.borrower, loanLocal.collateral, // minSourceTokenAmount 0, // maxSourceTokenAmount (0 means minSourceTokenAmount) depositAmount, // requiredDestTokenAmount (partial spend of loanLocal.collateral to fill this amount) true, // bypassFee "" // loanDataBytes ); loanLocal.collateral = loanLocal.collateral .sub(sourceTokenAmountUsed); // ensure the loan is still healthy (uint256 currentMargin, uint256 collateralToLoanRate) = IPriceFeeds(priceFeeds).getCurrentMargin( loanParamsLocal.loanToken, loanParamsLocal.collateralToken, loanLocal.principal, loanLocal.collateral ); require( currentMargin > loanParamsLocal.maintenanceMargin, "unhealthy position" ); // update deposit amount if (sourceTokenAmountUsed != 0 && collateralToLoanRate != 0) { _setDepositAmount( loanLocal.id, sourceTokenAmountUsed .mul(collateralToLoanRate) .div(WEI_PRECISION), sourceTokenAmountUsed, true // isSubtraction ); } return sourceTokenAmountUsed; } function _setDepositAmount( bytes32 loanId, uint256 depositValueAsLoanToken, uint256 depositValueAsCollateralToken, bool isSubtraction) internal { bytes32 slot = keccak256(abi.encode(loanId, LoanDepositValueID)); assembly { let val := sload(slot) switch isSubtraction case 0 { sstore(slot, add(val, depositValueAsLoanToken)) } default { switch gt(val, depositValueAsLoanToken) case 1 { sstore(slot, sub(val, depositValueAsLoanToken)) } default { sstore(slot, 0) } } slot := add(slot, 1) val := sload(slot) switch isSubtraction case 0 { sstore(slot, add(val, depositValueAsCollateralToken)) } default { switch gt(val, depositValueAsCollateralToken) case 1 { sstore(slot, sub(val, depositValueAsCollateralToken)) } default { sstore(slot, 0) } } } emit LoanDeposit( loanId, depositValueAsLoanToken, depositValueAsCollateralToken ); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"depositToken","type":"address"},{"indexed":true,"internalType":"bytes32","name":"loanId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"depositAmount","type":"uint256"}],"name":"DepositCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"bytes32","name":"loanId","type":"bytes32"},{"indexed":true,"internalType":"enum FeesEvents.FeeType","name":"feeType","type":"uint8"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EarnReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"depositToken","type":"address"},{"indexed":true,"internalType":"bytes32","name":"loanId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"depositAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralUsedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newEndTimestamp","type":"uint256"}],"name":"ExtendLoanDuration","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"sourceToken","type":"address"},{"indexed":true,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"}],"name":"ExternalSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"loanId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"depositValueAsLoanToken","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositValueAsCollateralToken","type":"uint256"}],"name":"LoanDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"loanId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sourceToken","type":"address"},{"indexed":true,"internalType":"address","name":"destToken","type":"address"},{"indexed":false,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"destAmount","type":"uint256"}],"name":"LoanSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"bytes32","name":"loanId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PayBorrowingFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PayLendingFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"bytes32","name":"loanId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PayTradingFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"withdrawToken","type":"address"},{"indexed":true,"internalType":"bytes32","name":"loanId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"withdrawAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newEndTimestamp","type":"uint256"}],"name":"ReduceLoanDuration","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"bytes32","name":"loanId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SettleFeeRewardForInterestExpense","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"VaultDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"VaultWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"withdrawToken","type":"address"},{"indexed":true,"internalType":"bytes32","name":"loanId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"WithdrawCollateral","type":"event"},{"constant":true,"inputs":[],"name":"affiliateFeePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"borrowerOrders","outputs":[{"internalType":"uint256","name":"lockedAmount","type":"uint256"},{"internalType":"uint256","name":"interestRate","type":"uint256"},{"internalType":"uint256","name":"minLoanTerm","type":"uint256"},{"internalType":"uint256","name":"maxLoanTerm","type":"uint256"},{"internalType":"uint256","name":"createdTimestamp","type":"uint256"},{"internalType":"uint256","name":"expirationTimestamp","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"borrowingFeePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"borrowingFeeTokensHeld","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"borrowingFeeTokensPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"bzrxTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"claimRewards","outputs":[{"internalType":"uint256","name":"claimAmount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"delegatedManagers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"loanId","type":"bytes32"},{"internalType":"uint256","name":"depositAmount","type":"uint256"}],"name":"depositCollateral","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"loanId","type":"bytes32"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"bool","name":"useCollateral","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"extendLoanDuration","outputs":[{"internalType":"uint256","name":"secondsExtended","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"feesController","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"},{"internalType":"bool","name":"unsafeOnly","type":"bool"}],"name":"getActiveLoans","outputs":[{"components":[{"internalType":"bytes32","name":"loanId","type":"bytes32"},{"internalType":"uint96","name":"endTimestamp","type":"uint96"},{"internalType":"address","name":"loanToken","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"interestOwedPerDay","type":"uint256"},{"internalType":"uint256","name":"interestDepositRemaining","type":"uint256"},{"internalType":"uint256","name":"startRate","type":"uint256"},{"internalType":"uint256","name":"startMargin","type":"uint256"},{"internalType":"uint256","name":"maintenanceMargin","type":"uint256"},{"internalType":"uint256","name":"currentMargin","type":"uint256"},{"internalType":"uint256","name":"maxLoanTerm","type":"uint256"},{"internalType":"uint256","name":"maxLiquidatable","type":"uint256"},{"internalType":"uint256","name":"maxSeizable","type":"uint256"},{"internalType":"uint256","name":"depositValueAsLoanToken","type":"uint256"},{"internalType":"uint256","name":"depositValueAsCollateralToken","type":"uint256"}],"internalType":"struct LoanMaintenanceEvents.LoanReturnData[]","name":"loansData","type":"tuple[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getActiveLoansCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"loanToken","type":"address"}],"name":"getLenderInterestData","outputs":[{"internalType":"uint256","name":"interestPaid","type":"uint256"},{"internalType":"uint256","name":"interestPaidDate","type":"uint256"},{"internalType":"uint256","name":"interestOwedPerDay","type":"uint256"},{"internalType":"uint256","name":"interestUnPaid","type":"uint256"},{"internalType":"uint256","name":"interestFeePercent","type":"uint256"},{"internalType":"uint256","name":"principalTotal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"loanId","type":"bytes32"}],"name":"getLoan","outputs":[{"components":[{"internalType":"bytes32","name":"loanId","type":"bytes32"},{"internalType":"uint96","name":"endTimestamp","type":"uint96"},{"internalType":"address","name":"loanToken","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"interestOwedPerDay","type":"uint256"},{"internalType":"uint256","name":"interestDepositRemaining","type":"uint256"},{"internalType":"uint256","name":"startRate","type":"uint256"},{"internalType":"uint256","name":"startMargin","type":"uint256"},{"internalType":"uint256","name":"maintenanceMargin","type":"uint256"},{"internalType":"uint256","name":"currentMargin","type":"uint256"},{"internalType":"uint256","name":"maxLoanTerm","type":"uint256"},{"internalType":"uint256","name":"maxLiquidatable","type":"uint256"},{"internalType":"uint256","name":"maxSeizable","type":"uint256"},{"internalType":"uint256","name":"depositValueAsLoanToken","type":"uint256"},{"internalType":"uint256","name":"depositValueAsCollateralToken","type":"uint256"}],"internalType":"struct LoanMaintenanceEvents.LoanReturnData","name":"loanData","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"loanId","type":"bytes32"}],"name":"getLoanInterestData","outputs":[{"internalType":"address","name":"loanToken","type":"address"},{"internalType":"uint256","name":"interestOwedPerDay","type":"uint256"},{"internalType":"uint256","name":"interestDepositTotal","type":"uint256"},{"internalType":"uint256","name":"interestDepositRemaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"},{"internalType":"enum LoanMaintenanceEvents.LoanType","name":"loanType","type":"uint8"},{"internalType":"bool","name":"isLender","type":"bool"},{"internalType":"bool","name":"unsafeOnly","type":"bool"}],"name":"getUserLoans","outputs":[{"components":[{"internalType":"bytes32","name":"loanId","type":"bytes32"},{"internalType":"uint96","name":"endTimestamp","type":"uint96"},{"internalType":"address","name":"loanToken","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"interestOwedPerDay","type":"uint256"},{"internalType":"uint256","name":"interestDepositRemaining","type":"uint256"},{"internalType":"uint256","name":"startRate","type":"uint256"},{"internalType":"uint256","name":"startMargin","type":"uint256"},{"internalType":"uint256","name":"maintenanceMargin","type":"uint256"},{"internalType":"uint256","name":"currentMargin","type":"uint256"},{"internalType":"uint256","name":"maxLoanTerm","type":"uint256"},{"internalType":"uint256","name":"maxLiquidatable","type":"uint256"},{"internalType":"uint256","name":"maxSeizable","type":"uint256"},{"internalType":"uint256","name":"depositValueAsLoanToken","type":"uint256"},{"internalType":"uint256","name":"depositValueAsCollateralToken","type":"uint256"}],"internalType":"struct LoanMaintenanceEvents.LoanReturnData[]","name":"loansData","type":"tuple[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"isLender","type":"bool"}],"name":"getUserLoansCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"lenderInterest","outputs":[{"internalType":"uint256","name":"principalTotal","type":"uint256"},{"internalType":"uint256","name":"owedPerDay","type":"uint256"},{"internalType":"uint256","name":"owedTotal","type":"uint256"},{"internalType":"uint256","name":"paidTotal","type":"uint256"},{"internalType":"uint256","name":"updatedTimestamp","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"lenderOrders","outputs":[{"internalType":"uint256","name":"lockedAmount","type":"uint256"},{"internalType":"uint256","name":"interestRate","type":"uint256"},{"internalType":"uint256","name":"minLoanTerm","type":"uint256"},{"internalType":"uint256","name":"maxLoanTerm","type":"uint256"},{"internalType":"uint256","name":"createdTimestamp","type":"uint256"},{"internalType":"uint256","name":"expirationTimestamp","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lendingFeePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lendingFeeTokensHeld","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lendingFeeTokensPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"liquidationIncentivePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"loanInterest","outputs":[{"internalType":"uint256","name":"owedPerDay","type":"uint256"},{"internalType":"uint256","name":"depositTotal","type":"uint256"},{"internalType":"uint256","name":"updatedTimestamp","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"loanParams","outputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"loanToken","type":"address"},{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"uint256","name":"minInitialMargin","type":"uint256"},{"internalType":"uint256","name":"maintenanceMargin","type":"uint256"},{"internalType":"uint256","name":"maxLoanTerm","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"loanPoolToUnderlying","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"loans","outputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes32","name":"loanParamsId","type":"bytes32"},{"internalType":"bytes32","name":"pendingTradesId","type":"bytes32"},{"internalType":"uint256","name":"principal","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"startMargin","type":"uint256"},{"internalType":"uint256","name":"startRate","type":"uint256"},{"internalType":"address","name":"borrower","type":"address"},{"internalType":"address","name":"lender","type":"address"},{"internalType":"bool","name":"active","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"logicTargets","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxDisagreement","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxSwapSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"priceFeeds","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"protocolTokenHeld","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"protocolTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"loanId","type":"bytes32"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"reduceLoanDuration","outputs":[{"internalType":"uint256","name":"secondsReduced","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rewardsBalanceOf","outputs":[{"internalType":"uint256","name":"rewardsBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"loanId","type":"bytes32"},{"internalType":"uint256","name":"depositValueAsLoanToken","type":"uint256"},{"internalType":"uint256","name":"depositValueAsCollateralToken","type":"uint256"}],"name":"setDepositAmount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sourceBufferPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"swapsImpl","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tradingFeePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tradingFeeTokensHeld","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tradingFeeTokensPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"underlyingToLoanPool","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"vbzrxTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"wethToken","outputs":[{"internalType":"contract IWethERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"loanToken","type":"address"}],"name":"withdrawAccruedInterest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"loanId","type":"bytes32"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"withdrawCollateral","outputs":[{"internalType":"uint256","name":"actualWithdrawAmount","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040526001600055678ac7230489e80000601455670214e8348c4f000060175567013fbe85edc90000601a556801a055690d9db80000601f55674563918244f40000602655674563918244f40000602755685150ae84a8cdf00000602855600062000071620000c560201b60201c565b600180546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350620000c9565b3390565b61533b80620000d96000396000f3fe6080604052600436106102ff5760003560e01c80638da5cb5b11610190578063cb6eacd1116100dc578063dea9b46411610095578063edab119f1161006f578063edab119f146108f6578063ef5cfb8c1461090b578063f27451ac1461092b578063f2fde38b1461094b576102ff565b8063dea9b464146108ae578063e81fefa0146108c1578063e8f62764146108e1576102ff565b8063cb6eacd1146107f2578063cfc85c0614610826578063d1979fb014610839578063d473c2da14610859578063d485045e1461086e578063db35400d1461088e576102ff565b8063ab3bd42811610149578063b30643d911610123578063b30643d91461075a578063b7e152411461077a578063c4a908151461079a578063c4d66de8146107d2576102ff565b8063ab3bd42814610703578063ae0a853014610723578063b1bb822514610738576102ff565b80638da5cb5b146106545780638dc48ba5146106695780638f32d59b1461068957806392d894f81461069e5780639b16cd87146106be578063ab2c9d75146106ee576102ff565b80634699f8461161024f57806362fff3f6116102085780637420ca3e116101e25780637420ca3e146105e857806378d849ed146105fd5780637a8faeb8146106125780638932f5f714610627576102ff565b806362fff3f61461058257806368c4ac26146105b3578063691bfee8146105d3576102ff565b80634699f846146104d25780634b57b0be146104e75780634f28cac21461050957806351c4e7b21461051e578063569fc1fb1461053357806360857c2c14610562576102ff565b806333dc41c7116102bc578063369ed07211610296578063369ed0721461044357806339cd381e146104705780634115a2b6146104855780634203e395146104b2576102ff565b806333dc41c7146103e35780633432423c146104035780633452d2d414610423576102ff565b8063065d810f14610304578063122f0e3a1461033f57806317548b791461036c578063218b39c6146103995780632a324027146103b95780632f470764146103ce575b600080fd5b34801561031057600080fd5b5061032461031f3660046140cc565b61096b565b604051610336969594939291906151ba565b60405180910390f35b34801561034b57600080fd5b5061035f61035a3660046141de565b6109ab565b6040516103369190615175565b34801561037857600080fd5b5061038c6103873660046142fa565b610d66565b6040516103369190614c74565b3480156103a557600080fd5b5061038c6103b4366004614044565b610d81565b3480156103c557600080fd5b5061035f610d9c565b3480156103da57600080fd5b5061035f610da2565b3480156103ef57600080fd5b5061035f6103fe366004614044565b610da8565b34801561040f57600080fd5b5061032461041e3660046140cc565b610e01565b34801561042f57600080fd5b5061035f61043e366004614044565b610e41565b34801561044f57600080fd5b5061046361045e3660046140fc565b610e53565b6040516103369190614dfe565b34801561047c57600080fd5b5061038c610fb3565b34801561049157600080fd5b506104a56104a03660046141bf565b610fcb565b6040516103369190614e0f565b3480156104be57600080fd5b5061035f6104cd366004614044565b610feb565b3480156104de57600080fd5b5061035f610ffd565b3480156104f357600080fd5b506104fc611003565b6040516103369190614f67565b34801561051557600080fd5b5061035f61101b565b34801561052a57600080fd5b5061035f611021565b34801561053f57600080fd5b5061055361054e3660046141a1565b611032565b60405161033693929190615191565b34801561056e57600080fd5b5061046361057d366004614366565b611053565b34801561058e57600080fd5b506105a261059d366004614062565b611165565b60405161033695949392919061519f565b3480156105bf57600080fd5b506104a56105ce366004614044565b61119f565b3480156105df57600080fd5b5061035f6111b4565b3480156105f457600080fd5b5061038c6111ba565b34801561060957600080fd5b5061038c6111c9565b34801561061e57600080fd5b5061035f6111d8565b34801561063357600080fd5b506106476106423660046141a1565b6111de565b6040516103369190615166565b34801561066057600080fd5b5061038c6111f8565b34801561067557600080fd5b5061038c610684366004614044565b611207565b34801561069557600080fd5b506104a5611222565b3480156106aa57600080fd5b5061035f6106b9366004614044565b611248565b3480156106ca57600080fd5b506106de6106d93660046141a1565b61125a565b6040516103369493929190614de3565b3480156106fa57600080fd5b5061038c6112eb565b34801561070f57600080fd5b5061035f61071e36600461409c565b611303565b34801561072f57600080fd5b5061035f611351565b34801561074457600080fd5b506107586107533660046142c8565b611357565b005b34801561076657600080fd5b5061035f610775366004614044565b61139e565b34801561078657600080fd5b5061035f610795366004614044565b6113b0565b3480156107a657600080fd5b506107ba6107b53660046141a1565b6113c2565b6040516103369c9b9a99989796959493929190614e94565b3480156107de57600080fd5b506107586107ed366004614044565b611435565b3480156107fe57600080fd5b5061081261080d3660046141a1565b61155b565b604051610336989796959493929190614e1d565b61035f61083436600461424a565b6115b2565b34801561084557600080fd5b50610324610854366004614062565b611abc565b34801561086557600080fd5b5061035f611bab565b34801561087a57600080fd5b5061035f610889366004614044565b611bb1565b34801561089a57600080fd5b5061035f6108a93660046141de565b611bc3565b6107586108bc36600461422b565b611f0d565b3480156108cd57600080fd5b506107586108dc366004614044565b612164565b3480156108ed57600080fd5b5061038c61216e565b34801561090257600080fd5b5061035f61217d565b34801561091757600080fd5b5061035f610926366004614044565b612183565b34801561093757600080fd5b5061035f610946366004614062565b6122f6565b34801561095757600080fd5b50610758610966366004614044565b612311565b6008602090815260009283526040808420909152908252902080546001820154600283015460038401546004850154600590950154939492939192909186565b60006001600054146109d85760405162461bcd60e51b81526004016109cf906150d6565b60405180910390fd5b6002600055816109fa5760405162461bcd60e51b81526004016109cf90614f86565b6000848152600560209081526040808320600181015484526006909252909120600a820154600160a01b900460ff16610a455760405162461bcd60e51b81526004016109cf906150c6565b60098201546001600160a01b0316331480610a7b57508154600090815260096020908152604080832033845290915290205460ff165b610a975760405162461bcd60e51b81526004016109cf90615096565b600681015415610ab95760405162461bcd60e51b81526004016109cf90614fb6565b42826006015411610adc5760405162461bcd60e51b81526004016109cf90615106565b600a8201546002820154610afc916001600160a01b03908116911661233e565b81546000818152600b60205260409020600283015460098501549192610b319284926001600160a01b0390811691164261241c565b6000610b7162015180610b658460000154610b594289600601546124c990919063ffffffff16565b9063ffffffff61250b16565b9063ffffffff61254516565b9050808610610b925760405162461bcd60e51b81526004016109cf90615056565b60028301546001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415610bca57610bc58787612587565b610be3565b6002830154610be3906001600160a01b03168888612668565b8154610bfc90610b65886201518063ffffffff61250b16565b945084846006015411610c215760405162461bcd60e51b81526004016109cf90614ff6565b6006840154610c36908663ffffffff6124c916565b6006850181905542108015610c525750610e1042856006015403115b610c6e5760405162461bcd60e51b81526004016109cf90614ff6565b6001820154610c83908763ffffffff6124c916565b6001830155600a848101546001600160a01b039081166000908152602092835260408082206002808901549094168352909352919091200154610ccc908763ffffffff6124c916565b600a858101546001600160a01b039081166000908152602092835260408082206002808a0180548616855291909552918190209093019390935591546009870154600688015492518c949283169391909216917f2ccf872a9a65a45661ce779b7bc6808ef3a167e50289371df14de6df2f817c7d91610d4d918c9190615183565b60405180910390a4505060016000555090949350505050565b6004602052600090815260409020546001600160a01b031681565b6022602052600090815260409020546001600160a01b031681565b60175481565b601e5481565b600080826040518060400160405280600b81526020016a557365725265776172647360a81b815250604051602001610de1929190614c41565b60408051601f198184030181529190528051602090910120549392505050565b6007602090815260009283526040808420909152908252902080546001820154600283015460038401546004850154600590950154939492939192909186565b60196020526000908152604090205481565b6060600083610e79576001600160a01b0388166000908152601160205260409020610e92565b6001600160a01b03881660009081526010602052604090205b90506000610ebe610ea2836126d8565b610eb28a8a63ffffffff6126df16565b9063ffffffff61270416565b9050808810610ecf5750610fa99050565b878103965086610edd613e14565b81604051908082528060200260200182016040528015610f1757816020015b610f04613e14565b815260200190600190039081610efc5790505b50945060001990920191825b8a8110610f9457610f44610f3d868363ffffffff61271a16565b8a8961273e565b8051909250610f5c5780610f5757610f94565b610f8b565b818684806001900395508c0381518110610f7257fe5b60200260200101819052508060001415610f8b57610f94565b60001901610f23565b508115610fa45781890398508885525b505050505b9695505050505050565b73b72b31907c1c95f3650b64b2469e08edacee5e8f81565b600960209081526000928352604080842090915290825290205460ff1681565b60156020526000908152604090205481565b60145481565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b60285481565b600061102d600e6126d8565b905090565b600b6020526000908152604090208054600182015460029092015490919083565b60606000611074611064600e6126d8565b610eb2878763ffffffff6126df16565b9050808510611083575061115e565b848103935083611091613e14565b816040519080825280602002602001820160405280156110cb57816020015b6110b8613e14565b8152602001906001900390816110b05790505b50935060001990920191825b87811061114a576110fa6110f2600e8363ffffffff61271a16565b60008861273e565b8051909250611112578061110d5761114a565b611141565b8185848060019003955089038151811061112857fe5b602002602001018190525080600014156111415761114a565b600019016110d7565b50811561115a5781860395508584525b5050505b9392505050565b600a602090815260009283526040808420909152908252902080546001820154600283015460038401546004909401549293919290919085565b60256020526000908152604090205460ff1681565b60275481565b6003546001600160a01b031681565b6002546001600160a01b031681565b601d5481565b6111e6613e14565b6111f28260008061273e565b92915050565b6001546001600160a01b031690565b6021602052600090815260409020546001600160a01b031681565b6001546000906001600160a01b0316611239612ba1565b6001600160a01b031614905090565b60166020526000908152604090205481565b60008181526005602081815260408084206001808201548652600680855283872060020154888852600b86529387208054920154959094529201546001600160a01b039091169391929190814282106112b357426112b5565b815b90508082116112c55760006112e0565b6112e062015180610b6587610b59868663ffffffff6124c916565b925050509193509193565b7356d811088235f11c8920698a204a5010a788f4b381565b600081611330576001600160a01b038316600090815260116020526040902061132b906126d8565b61115e565b6001600160a01b038316600090815260106020526040902061115e906126d8565b601f5481565b336000908152602160205260409020546001600160a01b031661138c5760405162461bcd60e51b81526004016109cf90615076565b6113998383836000612ba5565b505050565b601c6020526000908152604090205481565b601b6020526000908152604090205481565b600560208190526000918252604090912080546001820154600283015460038401546004850154958501546006860154600787015460088801546009890154600a9099015497999698959794969593949293919290916001600160a01b039081169190811690600160a01b900460ff168c565b61143d611222565b6114595760405162461bcd60e51b81526004016109cf90615096565b61146a6337aa6d1960e21b82612ca2565b61147b63db35400d60e01b82612ca2565b61148c630740ff7d60e51b82612ca2565b61149d6367e42e0360e11b82612ca2565b6114ae630917871d60e11b82612ca2565b6114bf63b1bb822560e01b82612ca2565b6114d0633bd73ee360e21b82612ca2565b6114e16333dc41c760e01b82612ca2565b6114f2630d1979fb60e41b82612ca2565b611503639b16cd8760e01b82612ca2565b611514631b4f683960e11b82612ca2565b6115256315677a8560e31b82612ca2565b611536638932f5f760e01b82612ca2565b6115476318215f0b60e21b82612ca2565b6115586328e273d960e11b82612ca2565b50565b60066020819052600091825260409091208054600182015460028301546003840154600485015460058601549590960154939560ff8416956101009094046001600160a01b03908116959381169492169290919088565b60006001600054146115d65760405162461bcd60e51b81526004016109cf906150d6565b6002600055846115f85760405162461bcd60e51b81526004016109cf906150a6565b6000868152600560209081526040808320600181015484526006909252909120600a820154600160a01b900460ff166116435760405162461bcd60e51b81526004016109cf906150c6565b85158061165c575060098201546001600160a01b031633145b8061168257508154600090815260096020908152604080832033845290915290205460ff165b61169e5760405162461bcd60e51b81526004016109cf90615096565b6006810154156116c05760405162461bcd60e51b81526004016109cf90614fb6565b3415806116f65750851580156116f6575060028101546001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b6117125760405162461bcd60e51b81526004016109cf90614fe6565b600a8201546002820154611732916001600160a01b03908116911661233e565b81546000818152600b602052604090206002830154600985015491926117679284926001600160a01b0390811691164261241c565b600083600601544211156117d757600684015461178b90429063ffffffff6124c916565b82549091506117a190829063ffffffff61250b16565b90506117b6816201518063ffffffff61254516565b90508089116117d75760405162461bcd60e51b81526004016109cf90614fc6565b6000881561185c5760408051610100808201835286548252600187015460ff811615156020840152046001600160a01b039081169282019290925260028601548216606082015260038601549091166080820152600485015460a0820152600585015460c0820152600685015460e08201526118559086908c612d18565b90506118a8565b3461187f57600284015461187a906001600160a01b0316338c612e8b565b6118a8565b89341461189e5760405162461bcd60e51b81526004016109cf90615136565b6118a83334612eef565b81156118e2576118be8a8363ffffffff6124c916565b600a8601546002860154919b506118e2916001600160a01b03918216911684612f9f565b82546118fb90610b658c6201518063ffffffff61250b16565b6006860154909650611913908763ffffffff6126df16565b600686018190554210801561192f5750610e1042866006015403115b61194b5760405162461bcd60e51b81526004016109cf90614ff6565b6001830154611960908b63ffffffff6126df16565b6001840155600a858101546001600160a01b039081166000908152602092835260408082206002808a015490941683529093529190912001546119a9908b63ffffffff6126df16565b600a600087600a0160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002060008660020160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001908152602001600020600201819055508a8460020160009054906101000a90046001600160a01b03166001600160a01b03168660090160009054906101000a90046001600160a01b03166001600160a01b03167f1a82d5bf63a278f4fcb396bfc36eb7457ad565605dd62b6f0f80619f811279db8d858a60060154604051611aa093929190615191565b60405180910390a4505060016000555091979650505050505050565b600080600080600080611acd613eb6565b506001600160a01b038089166000908152600a60209081526040808320938b16835292815290829020825160a081018452815481526001820154928101839052600282015493810193909352600381015460608401526004015460808301819052611b4d916201518091610b659190610b5990429063ffffffff6124c916565b93508060400151841115611b6357806040015193505b606081015180611b74576000611b7a565b81608001515b60208301516080840151611b8f576000611b91565b865b6014549451939d929c50909a509850919650945092505050565b60265481565b60186020526000908152604090205481565b6000600160005414611be75760405162461bcd60e51b81526004016109cf906150d6565b600260005581611c095760405162461bcd60e51b81526004016109cf90614f86565b6000848152600560209081526040808320600181015484526006909252909120600a820154600160a01b900460ff16611c545760405162461bcd60e51b81526004016109cf906150c6565b60098201546001600160a01b0316331480611c8a57508154600090815260096020908152604080832033845290915290205460ff165b611ca65760405162461bcd60e51b81526004016109cf90615096565b600381810154600484810154600280549086015494870154600587015460405163f80b25fb60e01b81526001600160a01b039687169794966000969481169563f80b25fb95611cfe9592909116938a938a9201614d6b565b60206040518083038186803b158015611d1657600080fd5b505afa158015611d2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611d4e9190810190614318565b905080871115611d6057809550611d64565b8695505b60408051808201909152601781527f7769746864726177416d6f756e7420746f6f20686967680000000000000000006020820152611dab908390889063ffffffff612ff616565b6004860181905591506001600160a01b03831673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415611de857611de38887612587565b611df3565b611df3838988612668565b6002805490850154604051630a7549df60e21b815260009283926001600160a01b03918216926329d5277c92611e30928a92911690600401614c82565b604080518083038186803b158015611e4757600080fd5b505afa158015611e5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611e7f9190810190614336565b9150915081600014611eab57611eab8b611ea383610b658c8763ffffffff61250b16565b8a6001612ba5565b60098701546040518c916001600160a01b03808916929116907f7b1bab051266a4a36232da9b4341daf225fa42f7202b0e7207b9b502644ff1bb90611ef1908d90615175565b60405180910390a4505060016000555093979650505050505050565b600160005414611f2f5760405162461bcd60e51b81526004016109cf906150d6565b600260005580611f515760405162461bcd60e51b81526004016109cf906150a6565b6000828152600560205260409020600a810154600160a01b900460ff16611f8a5760405162461bcd60e51b81526004016109cf906150c6565b60018101546000908152600660205260409020600381015460048301546001600160a01b0390911690341580611fdc57506001600160a01b03821673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b611ff85760405162461bcd60e51b81526004016109cf90614fe6565b612008818663ffffffff6126df16565b6004850181905590503461202657612021823387612e8b565b61204f565b8434146120455760405162461bcd60e51b81526004016109cf90615136565b61204f3334612eef565b6002805490840154604051630a7549df60e21b815260009283926001600160a01b03918216926329d5277c9261208c928992911690600401614c82565b604080518083038186803b1580156120a357600080fd5b505afa1580156120b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506120db9190810190614336565b915091508160001461210757612107886120ff83610b658b8763ffffffff61250b16565b896000612ba5565b600986015460405189916001600160a01b03808816929116907fa8a69faa6a38cc9c2beed79e034e1bd99f7eac877a5cee9f0118a8667b7ed93e9061214d908c90615175565b60405180910390a450506001600055505050505050565b611558338261233e565b6013546001600160a01b031681565b601a5481565b600080336040518060400160405280600b81526020016a557365725265776172647360a81b8152506040516020016121bc929190614c41565b60405160208183030381529060405280519060200120905080549150816000146122f05760008155601e546121f7908363ffffffff6126df16565b601e5560405163a9059cbb60e01b815273b72b31907c1c95f3650b64b2469e08edacee5e8f9063a9059cbb906122339086908690600401614dad565b602060405180830381600087803b15801561224d57600080fd5b505af1158015612261573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506122859190810190614183565b5073b72b31907c1c95f3650b64b2469e08edacee5e8f6001600160a01b0316836001600160a01b0316336001600160a01b03167ff9ce28130cf0ab6ae397696b8e3f3c22063af7b518a2d85c64520eadcb39155f856040516122e79190615175565b60405180910390a45b50919050565b60208080526000928352604080842090915290825290205481565b612319611222565b6123355760405162461bcd60e51b81526004016109cf90615096565b61155881613022565b6001600160a01b038083166000908152600a60209081526040808320938516835292905290812060018101549091901580159061237e5750600482015415155b1561240f576123a962015180610b658460010154610b598660040154426124c990919063ffffffff16565b42600484015560028301549091508111156123c5575060028101545b801561240a5760038201546123e0908263ffffffff6126df16565b600383015560028201546123fa908263ffffffff6124c916565b600283015561240a848483612f9f565b612416565b4260048301555b50505050565b600285015460008115612459576014548754612456916a07259756a8d6199800000091610b659190610b599081898963ffffffff6124c916565b90505b6002870183905580156124c05785856001600160a01b0316856001600160a01b03167fcf877e0841dcb21fb3fc42f1273a3ad3b8e956ec5d00b514bbd34a43b4cda2ee846040516124aa9190615175565b60405180910390a46124c08487878460036130a4565b50505050505050565b600061115e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612ff6565b60008261251a575060006111f2565b8282028284828161252757fe5b041461115e5760405162461bcd60e51b81526004016109cf90615086565b600061115e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613280565b80156126645773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2478083111561260c57604051632e1a7d4d60e01b81526001600160a01b03831690632e1a7d4d906125d99084870390600401615175565b600060405180830381600087803b1580156125f357600080fd5b505af1158015612607573d6000803e3d6000fd5b505050505b61261684846132b7565b836001600160a01b0316826001600160a01b03167fc44aeefa68e8b9c1ad5f7be4b0dd194580f81f5c362862e72196503a320eb7a1856040516126599190615175565b60405180910390a350505b5050565b8015611399576126886001600160a01b038416838363ffffffff61335316565b816001600160a01b0316836001600160a01b03167fc44aeefa68e8b9c1ad5f7be4b0dd194580f81f5c362862e72196503a320eb7a1836040516126cb9190615175565b60405180910390a3505050565b6001015490565b60008282018381101561115e5760405162461bcd60e51b81526004016109cf90614fd6565b6000818310612713578161115e565b5090919050565b600082600101828154811061272b57fe5b9060005260206000200154905092915050565b612746613e14565b61274e613ee5565b506000848152600560208181526040928390208351610180810185528154815260018201549281019290925260028101549382019390935260038301546060820152600483015460808201529082015460a0820152600682015460c0820152600782015460e0820152600882015461010082015260098201546001600160a01b03908116610120830152600a90920154918216610140820152600160a01b90910460ff161515610160820152612802613f49565b5060208181015160009081526006808352604091829020825161010080820185528254825260018084015460ff811615159784019790975295046001600160a01b039081169482019490945260028201548416606082015260038201549093166080840152600481015460a0840152600581015460c0840152015460e08201529085600281111561288f57fe5b14801561289e575060e0810151155b806128c2575060028560028111156128b257fe5b1480156128c2575060e081015115155b156128cf575061115e9050565b6128d7613f8d565b506000868152600b602090815260408083208151606080820184528254825260018301549482019490945260029182015481840152905485840151608080880151958901519089015194516317f8680960e11b815293969586956001600160a01b0390941694632ff0d01294612951949391600401614d2d565b604080518083038186803b15801561296857600080fd5b505afa15801561297c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506129a09190810190614336565b915091506000808560c001518411612a2657612a1c87606001518860800151868960c0015187602060008d606001516001600160a01b03166001600160a01b0316815260200190815260200160002060008d608001516001600160a01b03166001600160a01b03168152602001908152602001600020546133ac565b9092509050612a39565b8815612a39575061115e95505050505050565b60008060008d6040518060400160405280601081526020016f4c6f616e4465706f73697456616c756560801b815250604051602001612a79929190614f47565b6040516020818303038152906040528051906020012090508054925060018101549150428a60c001511115612ad557612ace62015180610b658a60000151610b59428f60c001516124c990919063ffffffff16565b9550612ada565b600095505b6040518061022001604052808f81526020018b60c001516001600160601b031681526020018a606001516001600160a01b031681526020018a608001516001600160a01b031681526020018b6060015181526020018b608001518152602001896000015181526020018781526020018b610100015181526020018b60e0015181526020018a60c0015181526020018881526020018a60e001518152602001868152602001858152602001848152602001838152509a50505050505050505050509392505050565b3390565b6000846040518060400160405280601081526020016f4c6f616e4465706f73697456616c756560801b815250604051602001612be2929190614f47565b60405160208183030381529060405280519060200120905080548260008114612c255785821160018114612c195760008455612c1f565b86830384555b50612c2b565b85820183555b50506001018054828015612c595784821160018114612c4d5760008455612c53565b85830384555b50612c5f565b84820183555b5050847f6fdb66f06832f41be9e4313f93e9b50685b11f2540d275342262997f35da88108585604051612c93929190615183565b60405180910390a25050505050565b6001600160e01b03198216600090815260046020526040902080546001600160a01b0319166001600160a01b03831690811790915515612cfd57612cf7600c6001600160e01b0319841663ffffffff6134d816565b50612664565b611399600c6001600160e01b0319841663ffffffff61352016565b600080612d648560000154856080015186606001518860090160009054906101000a90046001600160a01b031689600401546000896001604051806020016040528060008152506135e1565b506004870154909250612d7e91508263ffffffff6124c916565b60048087018290556002546060870151608088015160038a01546040516317f8680960e11b815260009687966001600160a01b0390961695632ff0d01295612dcd959094909390929101614d2d565b604080518083038186803b158015612de457600080fd5b505afa158015612df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612e1c9190810190614336565b915091508560c001518211612e435760405162461bcd60e51b81526004016109cf906150b6565b8215801590612e5157508015155b15612e80578654612e8090612e78670de0b6b3a7640000610b65878663ffffffff61250b16565b856001612ba5565b509095945050505050565b801561139957612eac6001600160a01b03841683308463ffffffff61373e16565b816001600160a01b0316836001600160a01b03167f2790b90165fd3973ad7edde4eca71b4f8808dd4857a2a3a3e8ae5642a5cb196e836040516126cb9190615175565b600073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29050806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015612f4357600080fd5b505af1158015612f57573d6000803e3d6000fd5b5050505050826001600160a01b0316816001600160a01b03167f2790b90165fd3973ad7edde4eca71b4f8808dd4857a2a3a3e8ae5642a5cb196e846040516126cb9190615175565b6000612fcf68056bc75e2d63100000612fc36014548561250b90919063ffffffff16565b9063ffffffff61376216565b9050612fdc8484836137a4565b6124168385612ff1858563ffffffff6124c916565b612668565b6000818484111561301a5760405162461bcd60e51b81526004016109cf9190614f75565b505050900390565b6001600160a01b0381166130485760405162461bcd60e51b81526004016109cf90614fa6565b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b600280546040516000926001600160a01b03909216918391606091849163d138f9a160e01b916130f2918b917356d811088235f11c8920698a204a5010a788f4b391908c0490602401614d05565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516131309190614c5d565b600060405180830381855afa9150503d806000811461316b576040519150601f19603f3d011682016040523d82523d6000602084013e613170565b606091505b5091509150600182141561318657602081015193505b831561327557601d548085111561319b578094505b8415613273576131b1818663ffffffff6124c916565b601d8190555060008a6040518060400160405280600b81526020016a557365725265776172647360a81b8152506040516020016131ef929190614c41565b60405160208183030381529060405280519060200120905085815401815586600381111561321957fe5b8a8c6001600160a01b03167fe6c5d7a78caa3f3f24c92ef7f180efb19eb4cc6decff0d5b9cbc4d164b718d0973b72b31907c1c95f3650b64b2469e08edacee5e8f8a604051613269929190614dad565b60405180910390a4505b505b505050505050505050565b600081836132a15760405162461bcd60e51b81526004016109cf9190614f75565b5060008385816132ad57fe5b0495945050505050565b804710156132d75760405162461bcd60e51b81526004016109cf90615046565b6000826001600160a01b0316826040516132f090614c69565b60006040518083038185875af1925050503d806000811461332d576040519150601f19603f3d011682016040523d82523d6000602084013e613332565b606091505b50509050806113995760405162461bcd60e51b81526004016109cf90615036565b60405161139990849063a9059cbb60e01b906133759086908690602401614dad565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613825565b600080848611806133bb575083155b156133c5576134cd565b8286116133d65750869050856134cd565b60006133f086674563918244f4000063ffffffff6126df16565b905061341368056bc75e2d63100000610b658b610b59858463ffffffff6126df16565b9250613441613434670de0b6b3a7640000610b658b8963ffffffff61250b16565b849063ffffffff6124c916565b925061346f613456828663ffffffff6124c916565b610b658568056bc75e2d6310000063ffffffff61250b16565b92508883111561347d578892505b6134a66134998568056bc75e2d6310000063ffffffff6126df16565b849063ffffffff61250b16565b91506134bd6064610b65848863ffffffff61254516565b9150878211156134cb578791505b505b965096945050505050565b60006134e4838361390a565b61351857506001808301805480830180835560009283526020808420909201859055848352908590526040909120556111f2565b5060006111f2565b600061352c838361390a565b1561351857600082815260208490526040902054600184015460001991820191018082146135a457600085600101828154811061356557fe5b906000526020600020015490508086600101848154811061358257fe5b6000918252602080832090910192909255918252869052604090206001830190555b600084815260208690526040812055600185018054806135c057fe5b600190038181906000526020600020016000905590556001925050506111f2565b6040805160a0810182526001600160a01b03808b16825289811660208084019190915230838501819052606080850191909152918a1660808401528351918201845288825281018790529182018590526000918291829161364591908e888861391f565b90935091506136548b83613ad9565b600254602654604051631e2c62d360e01b81526001600160a01b0390921691631e2c62d39161368d918f918f9188918a91600401614d6b565b60206040518083038186803b1580156136a557600080fd5b505afa1580156136b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506136dd9190810190614318565b9050896001600160a01b03168b6001600160a01b03168d7fb4eb3c9b62efcce7021cba5fd9cd0c44df91c2272806ccc5e57df7c912e8d7168c868860405161372793929190614dc8565b60405180910390a499509950999650505050505050565b6040516124169085906323b872dd60e01b9061337590879087908790602401614d05565b600061115e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613bb5565b8015611399576001600160a01b0382166000908152601560205260409020546137d3908263ffffffff6126df16565b6001600160a01b0380841660008181526015602052604090819020939093559151908516907f40a75ae5f7a5336e75f7c7977e12c4b46a9ac0f30de01a2d5b6c1a4f4af63587906126cb908590615175565b613837826001600160a01b0316613bff565b6138535760405162461bcd60e51b81526004016109cf90615146565b60006060836001600160a01b03168360405161386f9190614c5d565b6000604051808303816000865af19150503d80600081146138ac576040519150601f19603f3d011682016040523d82523d6000602084013e6138b1565b606091505b5091509150816138d35760405162461bcd60e51b81526004016109cf90615006565b80511561241657808060200190516138ee9190810190614183565b6124165760405162461bcd60e51b81526004016109cf906150f6565b60009081526020919091526040902054151590565b835160009081906139425760405162461bcd60e51b81526004016109cf90615026565b6000806000866139c357604089015161399b576139668960005b6020020151613c3b565b905080156139965760808a015161398790898c60005b602002015184613c5f565b885161399390826124c9565b89525b6139c3565b6139a689600261395c565b905080156139c35760408901516139bd90826126df565b60408a01525b60208901516139d857885160208a01526139fd565b6020890151895111156139fd5760405162461bcd60e51b81526004016109cf90615156565b855115613a1c5760405162461bcd60e51b81526004016109cf906150e6565b613a268a8a613cf8565b60408b01519194509250613a645788518214613a545760405162461bcd60e51b81526004016109cf90615126565b8015613a5f57908101905b613aca565b6020890151821115613a885760405162461bcd60e51b81526004016109cf90615016565b6040890151831015613aac5760405162461bcd60e51b81526004016109cf90614f96565b8015613aca5760808a0151613ac490898c600161397c565b80830392505b50909890975095505050505050565b60285480156113995760006001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415613b10575081613b95565b600254604051635967aa7560e11b81526001600160a01b039091169063b2cf54ea90613b429087908790600401614dad565b60206040518083038186803b158015613b5a57600080fd5b505afa158015613b6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613b929190810190614318565b90505b818111156124165760405162461bcd60e51b81526004016109cf90615066565b60008183613bd65760405162461bcd60e51b81526004016109cf9190614f75565b5083613be45750600061115e565b6000836001860381613bf257fe5b0460010195945050505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590613c3357508115155b949350505050565b60006111f268056bc75e2d63100000612fc36017548561250b90919063ffffffff16565b8015612416576001600160a01b038216600090815260186020526040902054613c8e908263ffffffff6126df16565b6001600160a01b03808416600081815260186020526040908190209390935591518592918716907fb23479169712c443e6b00fb0cec3506a5f5926f541df4243d313e11c8c5c71ed90613ce2908690615175565b60405180910390a46124168484848460016130a4565b815160208084015160408086015160608781015187519588015188850151945160009889989497632bea876360e01b97613d3f979296919592949293919291602401614c9d565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925260035491519092506000916001600160a01b031690613d91908490614c5d565b600060405180830381855af49150503d8060008114613dcc576040519150601f19603f3d011682016040523d82523d6000602084013e613dd1565b606091505b509250905080613df35760405162461bcd60e51b81526004016109cf90615116565b81806020019051613e079190810190614336565b9097909650945050505050565b6040518061022001604052806000801916815260200160006001600160601b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081019190915290565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b60405180606001604052806000815260200160008152602001600081525090565b80356111f2816152bc565b80356111f2816152d0565b80516111f2816152d0565b80356111f2816152d9565b80356111f2816152e2565b60008083601f840112613ff757600080fd5b50813567ffffffffffffffff81111561400f57600080fd5b60208301915083600182028301111561402757600080fd5b9250929050565b80356111f2816152eb565b80516111f2816152d9565b60006020828403121561405657600080fd5b6000613c338484613fae565b6000806040838503121561407557600080fd5b60006140818585613fae565b925050602061409285828601613fae565b9150509250929050565b600080604083850312156140af57600080fd5b60006140bb8585613fae565b925050602061409285828601613fb9565b600080604083850312156140df57600080fd5b60006140eb8585613fae565b925050602061409285828601613fcf565b60008060008060008060c0878903121561411557600080fd5b60006141218989613fae565b965050602061413289828a01613fcf565b955050604061414389828a01613fcf565b945050606061415489828a0161402e565b935050608061416589828a01613fb9565b92505060a061417689828a01613fb9565b9150509295509295509295565b60006020828403121561419557600080fd5b6000613c338484613fc4565b6000602082840312156141b357600080fd5b6000613c338484613fcf565b600080604083850312156141d257600080fd5b60006140818585613fcf565b6000806000606084860312156141f357600080fd5b60006141ff8686613fcf565b935050602061421086828701613fae565b925050604061422186828701613fcf565b9150509250925092565b6000806040838503121561423e57600080fd5b60006140eb8585613fcf565b60008060008060006080868803121561426257600080fd5b600061426e8888613fcf565b955050602061427f88828901613fcf565b945050604061429088828901613fb9565b935050606086013567ffffffffffffffff8111156142ad57600080fd5b6142b988828901613fe5565b92509250509295509295909350565b6000806000606084860312156142dd57600080fd5b60006142e98686613fcf565b935050602061421086828701613fcf565b60006020828403121561430c57600080fd5b6000613c338484613fda565b60006020828403121561432a57600080fd5b6000613c338484614039565b6000806040838503121561434957600080fd5b60006143558585614039565b925050602061409285828601614039565b60008060006060848603121561437b57600080fd5b60006143878686613fcf565b935050602061439886828701613fcf565b925050604061422186828701613fb9565b60006143b58383614ae4565b50506102200190565b6143cf6143ca8261522c565b61529b565b82525050565b6143cf8161522c565b60006143e98261521a565b6143f3818561521e565b93506143fe83615214565b8060005b8381101561442c57815161441688826143a9565b975061442183615214565b925050600101614402565b509495945050505050565b6143cf81615237565b6143cf8161523c565b60006144548261521a565b61445e8185615227565b935061446e81856020860161526f565b9290920192915050565b6143cf81615264565b600061448c8261521a565b614496818561521e565b93506144a681856020860161526f565b6144af816152ac565b9093019392505050565b60006144c660138361521e565b7207769746864726177416d6f756e74206973203606c1b815260200192915050565b60006144f5601b8361521e565b7f696e73756666696369656e742073776170206c69717569646974790000000000815260200192915050565b600061452e60268361521e565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181526564647265737360d01b602082015260400192915050565b600061457660148361521e565b73696e646566696e6974652d7465726d206f6e6c7960601b815260200192915050565b60006145a660228361521e565b7f6465706f7369742063616e6e6f7420636f766572206261636b20696e746572658152611cdd60f21b602082015260400192915050565b60006145ea601b8361521e565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061462360108361521e565b6f1ddc9bdb99c8185cdcd95d081cd95b9d60821b815260200192915050565b600061464f600e8361521e565b6d1b1bd85b881d1bdbc81cda1bdc9d60921b815260200192915050565b600061467960208361521e565b7f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815260200192915050565b60006146b260138361521e565b72737761702066696c6c20746f6f206c6172676560681b815260200192915050565b60006146e160118361521e565b700736f75726365416d6f756e74203d3d203607c1b815260200192915050565b600061470e603a8361521e565b7f416464726573733a20756e61626c6520746f2073656e642076616c75652c207281527f6563697069656e74206d61792068617665207265766572746564000000000000602082015260400192915050565b600061476d601d8361521e565b7f416464726573733a20696e73756666696369656e742062616c616e6365000000815260200192915050565b60006147a660188361521e565b7f776974686472617720616d6f756e7420746f6f20686967680000000000000000815260200192915050565b60006147df600e8361521e565b6d7377617020746f6f206c6172676560901b815260200192915050565b6000614809600e8361521e565b6d1b9bdd08185d5d1a1bdc9a5e995960921b815260200192915050565b600061483360218361521e565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b6000614876600c8361521e565b6b1d5b985d5d1a1bdc9a5e995960a21b815260200192915050565b600061489e60128361521e565b7106465706f736974416d6f756e7420697320360741b815260200192915050565b60006148cc60128361521e565b713ab73432b0b63a343c903837b9b4ba34b7b760711b815260200192915050565b60006111f2600083615227565b6000614907600e8361521e565b6d1b1bd85b881a5cc818db1bdcd95960921b815260200192915050565b6000614931600c8361521e565b6b1b9bdb9499595b9d1c985b9d60a21b815260200192915050565b6000614959600d8361521e565b6c696e76616c696420737461746560981b815260200192915050565b6000614982602a8361521e565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b602082015260400192915050565b60006149ce60138361521e565b721b1bd85b881d195c9b481a185cc8195b991959606a1b815260200192915050565b60006149fd600b8361521e565b6a1cddd85c0819985a5b195960aa1b815260200192915050565b6000614a2460168361521e565b751cddd85c081d1bdbc81b185c99d9481d1bc8199a5b1b60521b815260200192915050565b6000614a5660168361521e565b750cae8d0cae440c8cae0dee6d2e840dad2e6dac2e8c6d60531b815260200192915050565b6000614a88601f8361521e565b7f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400815260200192915050565b6000614ac160148361521e565b730dad2dc40cee4cac2e8cae440e8d0c2dc40dac2f60631b815260200192915050565b8051610220830190614af68482614440565b506020820151614b096020850182614c38565b506040820151614b1c60408501826143d5565b506060820151614b2f60608501826143d5565b506080820151614b426080850182614440565b5060a0820151614b5560a0850182614440565b5060c0820151614b6860c0850182614440565b5060e0820151614b7b60e0850182614440565b50610100820151614b90610100850182614440565b50610120820151614ba5610120850182614440565b50610140820151614bba610140850182614440565b50610160820151614bcf610160850182614440565b50610180820151614be4610180850182614440565b506101a0820151614bf96101a0850182614440565b506101c0820151614c0e6101c0850182614440565b506101e0820151614c236101e0850182614440565b50610200820151612416610200850182614440565b6143cf81615258565b6000614c4d82856143be565b601482019150613c338284614449565b600061115e8284614449565b60006111f2826148ed565b602081016111f282846143d5565b60408101614c9082856143d5565b61115e60208301846143d5565b60e08101614cab828a6143d5565b614cb860208301896143d5565b614cc560408301886143d5565b614cd260608301876143d5565b614cdf6080830186614440565b614cec60a0830185614440565b614cf960c0830184614440565b98975050505050505050565b60608101614d1382866143d5565b614d2060208301856143d5565b613c336040830184614440565b60808101614d3b82876143d5565b614d4860208301866143d5565b614d556040830185614440565b614d626060830184614440565b95945050505050565b60a08101614d7982886143d5565b614d8660208301876143d5565b614d936040830186614440565b614da06060830185614440565b610fa96080830184614440565b60408101614dbb82856143d5565b61115e6020830184614440565b60608101614dd682866143d5565b614d206020830185614440565b60808101614df182876143d5565b614d486020830186614440565b6020808252810161115e81846143de565b602081016111f28284614437565b6101008101614e2c828b614440565b614e39602083018a614437565b614e4660408301896143d5565b614e5360608301886143d5565b614e6060808301876143d5565b614e6d60a0830186614440565b614e7a60c0830185614440565b614e8760e0830184614440565b9998505050505050505050565b6101808101614ea3828f614440565b614eb0602083018e614440565b614ebd604083018d614440565b614eca606083018c614440565b614ed7608083018b614440565b614ee460a083018a614440565b614ef160c0830189614440565b614efe60e0830188614440565b614f0c610100830187614440565b614f1a6101208301866143d5565b614f286101408301856143d5565b614f36610160830184614437565b9d9c50505050505050505050505050565b60408101614f558285614440565b8181036020830152613c338184614481565b602081016111f28284614478565b6020808252810161115e8184614481565b602080825281016111f2816144b9565b602080825281016111f2816144e8565b602080825281016111f281614521565b602080825281016111f281614569565b602080825281016111f281614599565b602080825281016111f2816145dd565b602080825281016111f281614616565b602080825281016111f281614642565b602080825281016111f28161466c565b602080825281016111f2816146a5565b602080825281016111f2816146d4565b602080825281016111f281614701565b602080825281016111f281614760565b602080825281016111f281614799565b602080825281016111f2816147d2565b602080825281016111f2816147fc565b602080825281016111f281614826565b602080825281016111f281614869565b602080825281016111f281614891565b602080825281016111f2816148bf565b602080825281016111f2816148fa565b602080825281016111f281614924565b602080825281016111f28161494c565b602080825281016111f281614975565b602080825281016111f2816149c1565b602080825281016111f2816149f0565b602080825281016111f281614a17565b602080825281016111f281614a49565b602080825281016111f281614a7b565b602080825281016111f281614ab4565b61022081016111f28284614ae4565b602081016111f28284614440565b60408101614dbb8285614440565b60608101614dd68286614440565b60a081016151ad8288614440565b614d866020830187614440565b60c081016151c88289614440565b6151d56020830188614440565b6151e26040830187614440565b6151ef6060830186614440565b6151fc6080830185614440565b61520960a0830184614440565b979650505050505050565b60200190565b5190565b90815260200190565b919050565b60006111f28261524c565b151590565b90565b6001600160e01b03191690565b6001600160a01b031690565b6001600160601b031690565b60006111f28261522c565b60005b8381101561528a578181015183820152602001615272565b838111156124165750506000910152565b60006111f28260006111f2826152b6565b601f01601f191690565b60601b90565b6152c58161522c565b811461155857600080fd5b6152c581615237565b6152c58161523c565b6152c58161523f565b6003811061155857600080fdfea365627a7a7231582054acbafafa6908356df4b14019a2815a4f242caed603fbe98f637bc9471c488f6c6578706572696d656e74616cf564736f6c63430005110040
Deployed Bytecode
0x6080604052600436106102ff5760003560e01c80638da5cb5b11610190578063cb6eacd1116100dc578063dea9b46411610095578063edab119f1161006f578063edab119f146108f6578063ef5cfb8c1461090b578063f27451ac1461092b578063f2fde38b1461094b576102ff565b8063dea9b464146108ae578063e81fefa0146108c1578063e8f62764146108e1576102ff565b8063cb6eacd1146107f2578063cfc85c0614610826578063d1979fb014610839578063d473c2da14610859578063d485045e1461086e578063db35400d1461088e576102ff565b8063ab3bd42811610149578063b30643d911610123578063b30643d91461075a578063b7e152411461077a578063c4a908151461079a578063c4d66de8146107d2576102ff565b8063ab3bd42814610703578063ae0a853014610723578063b1bb822514610738576102ff565b80638da5cb5b146106545780638dc48ba5146106695780638f32d59b1461068957806392d894f81461069e5780639b16cd87146106be578063ab2c9d75146106ee576102ff565b80634699f8461161024f57806362fff3f6116102085780637420ca3e116101e25780637420ca3e146105e857806378d849ed146105fd5780637a8faeb8146106125780638932f5f714610627576102ff565b806362fff3f61461058257806368c4ac26146105b3578063691bfee8146105d3576102ff565b80634699f846146104d25780634b57b0be146104e75780634f28cac21461050957806351c4e7b21461051e578063569fc1fb1461053357806360857c2c14610562576102ff565b806333dc41c7116102bc578063369ed07211610296578063369ed0721461044357806339cd381e146104705780634115a2b6146104855780634203e395146104b2576102ff565b806333dc41c7146103e35780633432423c146104035780633452d2d414610423576102ff565b8063065d810f14610304578063122f0e3a1461033f57806317548b791461036c578063218b39c6146103995780632a324027146103b95780632f470764146103ce575b600080fd5b34801561031057600080fd5b5061032461031f3660046140cc565b61096b565b604051610336969594939291906151ba565b60405180910390f35b34801561034b57600080fd5b5061035f61035a3660046141de565b6109ab565b6040516103369190615175565b34801561037857600080fd5b5061038c6103873660046142fa565b610d66565b6040516103369190614c74565b3480156103a557600080fd5b5061038c6103b4366004614044565b610d81565b3480156103c557600080fd5b5061035f610d9c565b3480156103da57600080fd5b5061035f610da2565b3480156103ef57600080fd5b5061035f6103fe366004614044565b610da8565b34801561040f57600080fd5b5061032461041e3660046140cc565b610e01565b34801561042f57600080fd5b5061035f61043e366004614044565b610e41565b34801561044f57600080fd5b5061046361045e3660046140fc565b610e53565b6040516103369190614dfe565b34801561047c57600080fd5b5061038c610fb3565b34801561049157600080fd5b506104a56104a03660046141bf565b610fcb565b6040516103369190614e0f565b3480156104be57600080fd5b5061035f6104cd366004614044565b610feb565b3480156104de57600080fd5b5061035f610ffd565b3480156104f357600080fd5b506104fc611003565b6040516103369190614f67565b34801561051557600080fd5b5061035f61101b565b34801561052a57600080fd5b5061035f611021565b34801561053f57600080fd5b5061055361054e3660046141a1565b611032565b60405161033693929190615191565b34801561056e57600080fd5b5061046361057d366004614366565b611053565b34801561058e57600080fd5b506105a261059d366004614062565b611165565b60405161033695949392919061519f565b3480156105bf57600080fd5b506104a56105ce366004614044565b61119f565b3480156105df57600080fd5b5061035f6111b4565b3480156105f457600080fd5b5061038c6111ba565b34801561060957600080fd5b5061038c6111c9565b34801561061e57600080fd5b5061035f6111d8565b34801561063357600080fd5b506106476106423660046141a1565b6111de565b6040516103369190615166565b34801561066057600080fd5b5061038c6111f8565b34801561067557600080fd5b5061038c610684366004614044565b611207565b34801561069557600080fd5b506104a5611222565b3480156106aa57600080fd5b5061035f6106b9366004614044565b611248565b3480156106ca57600080fd5b506106de6106d93660046141a1565b61125a565b6040516103369493929190614de3565b3480156106fa57600080fd5b5061038c6112eb565b34801561070f57600080fd5b5061035f61071e36600461409c565b611303565b34801561072f57600080fd5b5061035f611351565b34801561074457600080fd5b506107586107533660046142c8565b611357565b005b34801561076657600080fd5b5061035f610775366004614044565b61139e565b34801561078657600080fd5b5061035f610795366004614044565b6113b0565b3480156107a657600080fd5b506107ba6107b53660046141a1565b6113c2565b6040516103369c9b9a99989796959493929190614e94565b3480156107de57600080fd5b506107586107ed366004614044565b611435565b3480156107fe57600080fd5b5061081261080d3660046141a1565b61155b565b604051610336989796959493929190614e1d565b61035f61083436600461424a565b6115b2565b34801561084557600080fd5b50610324610854366004614062565b611abc565b34801561086557600080fd5b5061035f611bab565b34801561087a57600080fd5b5061035f610889366004614044565b611bb1565b34801561089a57600080fd5b5061035f6108a93660046141de565b611bc3565b6107586108bc36600461422b565b611f0d565b3480156108cd57600080fd5b506107586108dc366004614044565b612164565b3480156108ed57600080fd5b5061038c61216e565b34801561090257600080fd5b5061035f61217d565b34801561091757600080fd5b5061035f610926366004614044565b612183565b34801561093757600080fd5b5061035f610946366004614062565b6122f6565b34801561095757600080fd5b50610758610966366004614044565b612311565b6008602090815260009283526040808420909152908252902080546001820154600283015460038401546004850154600590950154939492939192909186565b60006001600054146109d85760405162461bcd60e51b81526004016109cf906150d6565b60405180910390fd5b6002600055816109fa5760405162461bcd60e51b81526004016109cf90614f86565b6000848152600560209081526040808320600181015484526006909252909120600a820154600160a01b900460ff16610a455760405162461bcd60e51b81526004016109cf906150c6565b60098201546001600160a01b0316331480610a7b57508154600090815260096020908152604080832033845290915290205460ff165b610a975760405162461bcd60e51b81526004016109cf90615096565b600681015415610ab95760405162461bcd60e51b81526004016109cf90614fb6565b42826006015411610adc5760405162461bcd60e51b81526004016109cf90615106565b600a8201546002820154610afc916001600160a01b03908116911661233e565b81546000818152600b60205260409020600283015460098501549192610b319284926001600160a01b0390811691164261241c565b6000610b7162015180610b658460000154610b594289600601546124c990919063ffffffff16565b9063ffffffff61250b16565b9063ffffffff61254516565b9050808610610b925760405162461bcd60e51b81526004016109cf90615056565b60028301546001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415610bca57610bc58787612587565b610be3565b6002830154610be3906001600160a01b03168888612668565b8154610bfc90610b65886201518063ffffffff61250b16565b945084846006015411610c215760405162461bcd60e51b81526004016109cf90614ff6565b6006840154610c36908663ffffffff6124c916565b6006850181905542108015610c525750610e1042856006015403115b610c6e5760405162461bcd60e51b81526004016109cf90614ff6565b6001820154610c83908763ffffffff6124c916565b6001830155600a848101546001600160a01b039081166000908152602092835260408082206002808901549094168352909352919091200154610ccc908763ffffffff6124c916565b600a858101546001600160a01b039081166000908152602092835260408082206002808a0180548616855291909552918190209093019390935591546009870154600688015492518c949283169391909216917f2ccf872a9a65a45661ce779b7bc6808ef3a167e50289371df14de6df2f817c7d91610d4d918c9190615183565b60405180910390a4505060016000555090949350505050565b6004602052600090815260409020546001600160a01b031681565b6022602052600090815260409020546001600160a01b031681565b60175481565b601e5481565b600080826040518060400160405280600b81526020016a557365725265776172647360a81b815250604051602001610de1929190614c41565b60408051601f198184030181529190528051602090910120549392505050565b6007602090815260009283526040808420909152908252902080546001820154600283015460038401546004850154600590950154939492939192909186565b60196020526000908152604090205481565b6060600083610e79576001600160a01b0388166000908152601160205260409020610e92565b6001600160a01b03881660009081526010602052604090205b90506000610ebe610ea2836126d8565b610eb28a8a63ffffffff6126df16565b9063ffffffff61270416565b9050808810610ecf5750610fa99050565b878103965086610edd613e14565b81604051908082528060200260200182016040528015610f1757816020015b610f04613e14565b815260200190600190039081610efc5790505b50945060001990920191825b8a8110610f9457610f44610f3d868363ffffffff61271a16565b8a8961273e565b8051909250610f5c5780610f5757610f94565b610f8b565b818684806001900395508c0381518110610f7257fe5b60200260200101819052508060001415610f8b57610f94565b60001901610f23565b508115610fa45781890398508885525b505050505b9695505050505050565b73b72b31907c1c95f3650b64b2469e08edacee5e8f81565b600960209081526000928352604080842090915290825290205460ff1681565b60156020526000908152604090205481565b60145481565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b60285481565b600061102d600e6126d8565b905090565b600b6020526000908152604090208054600182015460029092015490919083565b60606000611074611064600e6126d8565b610eb2878763ffffffff6126df16565b9050808510611083575061115e565b848103935083611091613e14565b816040519080825280602002602001820160405280156110cb57816020015b6110b8613e14565b8152602001906001900390816110b05790505b50935060001990920191825b87811061114a576110fa6110f2600e8363ffffffff61271a16565b60008861273e565b8051909250611112578061110d5761114a565b611141565b8185848060019003955089038151811061112857fe5b602002602001018190525080600014156111415761114a565b600019016110d7565b50811561115a5781860395508584525b5050505b9392505050565b600a602090815260009283526040808420909152908252902080546001820154600283015460038401546004909401549293919290919085565b60256020526000908152604090205460ff1681565b60275481565b6003546001600160a01b031681565b6002546001600160a01b031681565b601d5481565b6111e6613e14565b6111f28260008061273e565b92915050565b6001546001600160a01b031690565b6021602052600090815260409020546001600160a01b031681565b6001546000906001600160a01b0316611239612ba1565b6001600160a01b031614905090565b60166020526000908152604090205481565b60008181526005602081815260408084206001808201548652600680855283872060020154888852600b86529387208054920154959094529201546001600160a01b039091169391929190814282106112b357426112b5565b815b90508082116112c55760006112e0565b6112e062015180610b6587610b59868663ffffffff6124c916565b925050509193509193565b7356d811088235f11c8920698a204a5010a788f4b381565b600081611330576001600160a01b038316600090815260116020526040902061132b906126d8565b61115e565b6001600160a01b038316600090815260106020526040902061115e906126d8565b601f5481565b336000908152602160205260409020546001600160a01b031661138c5760405162461bcd60e51b81526004016109cf90615076565b6113998383836000612ba5565b505050565b601c6020526000908152604090205481565b601b6020526000908152604090205481565b600560208190526000918252604090912080546001820154600283015460038401546004850154958501546006860154600787015460088801546009890154600a9099015497999698959794969593949293919290916001600160a01b039081169190811690600160a01b900460ff168c565b61143d611222565b6114595760405162461bcd60e51b81526004016109cf90615096565b61146a6337aa6d1960e21b82612ca2565b61147b63db35400d60e01b82612ca2565b61148c630740ff7d60e51b82612ca2565b61149d6367e42e0360e11b82612ca2565b6114ae630917871d60e11b82612ca2565b6114bf63b1bb822560e01b82612ca2565b6114d0633bd73ee360e21b82612ca2565b6114e16333dc41c760e01b82612ca2565b6114f2630d1979fb60e41b82612ca2565b611503639b16cd8760e01b82612ca2565b611514631b4f683960e11b82612ca2565b6115256315677a8560e31b82612ca2565b611536638932f5f760e01b82612ca2565b6115476318215f0b60e21b82612ca2565b6115586328e273d960e11b82612ca2565b50565b60066020819052600091825260409091208054600182015460028301546003840154600485015460058601549590960154939560ff8416956101009094046001600160a01b03908116959381169492169290919088565b60006001600054146115d65760405162461bcd60e51b81526004016109cf906150d6565b6002600055846115f85760405162461bcd60e51b81526004016109cf906150a6565b6000868152600560209081526040808320600181015484526006909252909120600a820154600160a01b900460ff166116435760405162461bcd60e51b81526004016109cf906150c6565b85158061165c575060098201546001600160a01b031633145b8061168257508154600090815260096020908152604080832033845290915290205460ff165b61169e5760405162461bcd60e51b81526004016109cf90615096565b6006810154156116c05760405162461bcd60e51b81526004016109cf90614fb6565b3415806116f65750851580156116f6575060028101546001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b6117125760405162461bcd60e51b81526004016109cf90614fe6565b600a8201546002820154611732916001600160a01b03908116911661233e565b81546000818152600b602052604090206002830154600985015491926117679284926001600160a01b0390811691164261241c565b600083600601544211156117d757600684015461178b90429063ffffffff6124c916565b82549091506117a190829063ffffffff61250b16565b90506117b6816201518063ffffffff61254516565b90508089116117d75760405162461bcd60e51b81526004016109cf90614fc6565b6000881561185c5760408051610100808201835286548252600187015460ff811615156020840152046001600160a01b039081169282019290925260028601548216606082015260038601549091166080820152600485015460a0820152600585015460c0820152600685015460e08201526118559086908c612d18565b90506118a8565b3461187f57600284015461187a906001600160a01b0316338c612e8b565b6118a8565b89341461189e5760405162461bcd60e51b81526004016109cf90615136565b6118a83334612eef565b81156118e2576118be8a8363ffffffff6124c916565b600a8601546002860154919b506118e2916001600160a01b03918216911684612f9f565b82546118fb90610b658c6201518063ffffffff61250b16565b6006860154909650611913908763ffffffff6126df16565b600686018190554210801561192f5750610e1042866006015403115b61194b5760405162461bcd60e51b81526004016109cf90614ff6565b6001830154611960908b63ffffffff6126df16565b6001840155600a858101546001600160a01b039081166000908152602092835260408082206002808a015490941683529093529190912001546119a9908b63ffffffff6126df16565b600a600087600a0160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b0316815260200190815260200160002060008660020160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b03168152602001908152602001600020600201819055508a8460020160009054906101000a90046001600160a01b03166001600160a01b03168660090160009054906101000a90046001600160a01b03166001600160a01b03167f1a82d5bf63a278f4fcb396bfc36eb7457ad565605dd62b6f0f80619f811279db8d858a60060154604051611aa093929190615191565b60405180910390a4505060016000555091979650505050505050565b600080600080600080611acd613eb6565b506001600160a01b038089166000908152600a60209081526040808320938b16835292815290829020825160a081018452815481526001820154928101839052600282015493810193909352600381015460608401526004015460808301819052611b4d916201518091610b659190610b5990429063ffffffff6124c916565b93508060400151841115611b6357806040015193505b606081015180611b74576000611b7a565b81608001515b60208301516080840151611b8f576000611b91565b865b6014549451939d929c50909a509850919650945092505050565b60265481565b60186020526000908152604090205481565b6000600160005414611be75760405162461bcd60e51b81526004016109cf906150d6565b600260005581611c095760405162461bcd60e51b81526004016109cf90614f86565b6000848152600560209081526040808320600181015484526006909252909120600a820154600160a01b900460ff16611c545760405162461bcd60e51b81526004016109cf906150c6565b60098201546001600160a01b0316331480611c8a57508154600090815260096020908152604080832033845290915290205460ff165b611ca65760405162461bcd60e51b81526004016109cf90615096565b600381810154600484810154600280549086015494870154600587015460405163f80b25fb60e01b81526001600160a01b039687169794966000969481169563f80b25fb95611cfe9592909116938a938a9201614d6b565b60206040518083038186803b158015611d1657600080fd5b505afa158015611d2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611d4e9190810190614318565b905080871115611d6057809550611d64565b8695505b60408051808201909152601781527f7769746864726177416d6f756e7420746f6f20686967680000000000000000006020820152611dab908390889063ffffffff612ff616565b6004860181905591506001600160a01b03831673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415611de857611de38887612587565b611df3565b611df3838988612668565b6002805490850154604051630a7549df60e21b815260009283926001600160a01b03918216926329d5277c92611e30928a92911690600401614c82565b604080518083038186803b158015611e4757600080fd5b505afa158015611e5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611e7f9190810190614336565b9150915081600014611eab57611eab8b611ea383610b658c8763ffffffff61250b16565b8a6001612ba5565b60098701546040518c916001600160a01b03808916929116907f7b1bab051266a4a36232da9b4341daf225fa42f7202b0e7207b9b502644ff1bb90611ef1908d90615175565b60405180910390a4505060016000555093979650505050505050565b600160005414611f2f5760405162461bcd60e51b81526004016109cf906150d6565b600260005580611f515760405162461bcd60e51b81526004016109cf906150a6565b6000828152600560205260409020600a810154600160a01b900460ff16611f8a5760405162461bcd60e51b81526004016109cf906150c6565b60018101546000908152600660205260409020600381015460048301546001600160a01b0390911690341580611fdc57506001600160a01b03821673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2145b611ff85760405162461bcd60e51b81526004016109cf90614fe6565b612008818663ffffffff6126df16565b6004850181905590503461202657612021823387612e8b565b61204f565b8434146120455760405162461bcd60e51b81526004016109cf90615136565b61204f3334612eef565b6002805490840154604051630a7549df60e21b815260009283926001600160a01b03918216926329d5277c9261208c928992911690600401614c82565b604080518083038186803b1580156120a357600080fd5b505afa1580156120b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506120db9190810190614336565b915091508160001461210757612107886120ff83610b658b8763ffffffff61250b16565b896000612ba5565b600986015460405189916001600160a01b03808816929116907fa8a69faa6a38cc9c2beed79e034e1bd99f7eac877a5cee9f0118a8667b7ed93e9061214d908c90615175565b60405180910390a450506001600055505050505050565b611558338261233e565b6013546001600160a01b031681565b601a5481565b600080336040518060400160405280600b81526020016a557365725265776172647360a81b8152506040516020016121bc929190614c41565b60405160208183030381529060405280519060200120905080549150816000146122f05760008155601e546121f7908363ffffffff6126df16565b601e5560405163a9059cbb60e01b815273b72b31907c1c95f3650b64b2469e08edacee5e8f9063a9059cbb906122339086908690600401614dad565b602060405180830381600087803b15801561224d57600080fd5b505af1158015612261573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506122859190810190614183565b5073b72b31907c1c95f3650b64b2469e08edacee5e8f6001600160a01b0316836001600160a01b0316336001600160a01b03167ff9ce28130cf0ab6ae397696b8e3f3c22063af7b518a2d85c64520eadcb39155f856040516122e79190615175565b60405180910390a45b50919050565b60208080526000928352604080842090915290825290205481565b612319611222565b6123355760405162461bcd60e51b81526004016109cf90615096565b61155881613022565b6001600160a01b038083166000908152600a60209081526040808320938516835292905290812060018101549091901580159061237e5750600482015415155b1561240f576123a962015180610b658460010154610b598660040154426124c990919063ffffffff16565b42600484015560028301549091508111156123c5575060028101545b801561240a5760038201546123e0908263ffffffff6126df16565b600383015560028201546123fa908263ffffffff6124c916565b600283015561240a848483612f9f565b612416565b4260048301555b50505050565b600285015460008115612459576014548754612456916a07259756a8d6199800000091610b659190610b599081898963ffffffff6124c916565b90505b6002870183905580156124c05785856001600160a01b0316856001600160a01b03167fcf877e0841dcb21fb3fc42f1273a3ad3b8e956ec5d00b514bbd34a43b4cda2ee846040516124aa9190615175565b60405180910390a46124c08487878460036130a4565b50505050505050565b600061115e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612ff6565b60008261251a575060006111f2565b8282028284828161252757fe5b041461115e5760405162461bcd60e51b81526004016109cf90615086565b600061115e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613280565b80156126645773c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2478083111561260c57604051632e1a7d4d60e01b81526001600160a01b03831690632e1a7d4d906125d99084870390600401615175565b600060405180830381600087803b1580156125f357600080fd5b505af1158015612607573d6000803e3d6000fd5b505050505b61261684846132b7565b836001600160a01b0316826001600160a01b03167fc44aeefa68e8b9c1ad5f7be4b0dd194580f81f5c362862e72196503a320eb7a1856040516126599190615175565b60405180910390a350505b5050565b8015611399576126886001600160a01b038416838363ffffffff61335316565b816001600160a01b0316836001600160a01b03167fc44aeefa68e8b9c1ad5f7be4b0dd194580f81f5c362862e72196503a320eb7a1836040516126cb9190615175565b60405180910390a3505050565b6001015490565b60008282018381101561115e5760405162461bcd60e51b81526004016109cf90614fd6565b6000818310612713578161115e565b5090919050565b600082600101828154811061272b57fe5b9060005260206000200154905092915050565b612746613e14565b61274e613ee5565b506000848152600560208181526040928390208351610180810185528154815260018201549281019290925260028101549382019390935260038301546060820152600483015460808201529082015460a0820152600682015460c0820152600782015460e0820152600882015461010082015260098201546001600160a01b03908116610120830152600a90920154918216610140820152600160a01b90910460ff161515610160820152612802613f49565b5060208181015160009081526006808352604091829020825161010080820185528254825260018084015460ff811615159784019790975295046001600160a01b039081169482019490945260028201548416606082015260038201549093166080840152600481015460a0840152600581015460c0840152015460e08201529085600281111561288f57fe5b14801561289e575060e0810151155b806128c2575060028560028111156128b257fe5b1480156128c2575060e081015115155b156128cf575061115e9050565b6128d7613f8d565b506000868152600b602090815260408083208151606080820184528254825260018301549482019490945260029182015481840152905485840151608080880151958901519089015194516317f8680960e11b815293969586956001600160a01b0390941694632ff0d01294612951949391600401614d2d565b604080518083038186803b15801561296857600080fd5b505afa15801561297c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506129a09190810190614336565b915091506000808560c001518411612a2657612a1c87606001518860800151868960c0015187602060008d606001516001600160a01b03166001600160a01b0316815260200190815260200160002060008d608001516001600160a01b03166001600160a01b03168152602001908152602001600020546133ac565b9092509050612a39565b8815612a39575061115e95505050505050565b60008060008d6040518060400160405280601081526020016f4c6f616e4465706f73697456616c756560801b815250604051602001612a79929190614f47565b6040516020818303038152906040528051906020012090508054925060018101549150428a60c001511115612ad557612ace62015180610b658a60000151610b59428f60c001516124c990919063ffffffff16565b9550612ada565b600095505b6040518061022001604052808f81526020018b60c001516001600160601b031681526020018a606001516001600160a01b031681526020018a608001516001600160a01b031681526020018b6060015181526020018b608001518152602001896000015181526020018781526020018b610100015181526020018b60e0015181526020018a60c0015181526020018881526020018a60e001518152602001868152602001858152602001848152602001838152509a50505050505050505050509392505050565b3390565b6000846040518060400160405280601081526020016f4c6f616e4465706f73697456616c756560801b815250604051602001612be2929190614f47565b60405160208183030381529060405280519060200120905080548260008114612c255785821160018114612c195760008455612c1f565b86830384555b50612c2b565b85820183555b50506001018054828015612c595784821160018114612c4d5760008455612c53565b85830384555b50612c5f565b84820183555b5050847f6fdb66f06832f41be9e4313f93e9b50685b11f2540d275342262997f35da88108585604051612c93929190615183565b60405180910390a25050505050565b6001600160e01b03198216600090815260046020526040902080546001600160a01b0319166001600160a01b03831690811790915515612cfd57612cf7600c6001600160e01b0319841663ffffffff6134d816565b50612664565b611399600c6001600160e01b0319841663ffffffff61352016565b600080612d648560000154856080015186606001518860090160009054906101000a90046001600160a01b031689600401546000896001604051806020016040528060008152506135e1565b506004870154909250612d7e91508263ffffffff6124c916565b60048087018290556002546060870151608088015160038a01546040516317f8680960e11b815260009687966001600160a01b0390961695632ff0d01295612dcd959094909390929101614d2d565b604080518083038186803b158015612de457600080fd5b505afa158015612df8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612e1c9190810190614336565b915091508560c001518211612e435760405162461bcd60e51b81526004016109cf906150b6565b8215801590612e5157508015155b15612e80578654612e8090612e78670de0b6b3a7640000610b65878663ffffffff61250b16565b856001612ba5565b509095945050505050565b801561139957612eac6001600160a01b03841683308463ffffffff61373e16565b816001600160a01b0316836001600160a01b03167f2790b90165fd3973ad7edde4eca71b4f8808dd4857a2a3a3e8ae5642a5cb196e836040516126cb9190615175565b600073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc29050806001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015612f4357600080fd5b505af1158015612f57573d6000803e3d6000fd5b5050505050826001600160a01b0316816001600160a01b03167f2790b90165fd3973ad7edde4eca71b4f8808dd4857a2a3a3e8ae5642a5cb196e846040516126cb9190615175565b6000612fcf68056bc75e2d63100000612fc36014548561250b90919063ffffffff16565b9063ffffffff61376216565b9050612fdc8484836137a4565b6124168385612ff1858563ffffffff6124c916565b612668565b6000818484111561301a5760405162461bcd60e51b81526004016109cf9190614f75565b505050900390565b6001600160a01b0381166130485760405162461bcd60e51b81526004016109cf90614fa6565b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b600280546040516000926001600160a01b03909216918391606091849163d138f9a160e01b916130f2918b917356d811088235f11c8920698a204a5010a788f4b391908c0490602401614d05565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516131309190614c5d565b600060405180830381855afa9150503d806000811461316b576040519150601f19603f3d011682016040523d82523d6000602084013e613170565b606091505b5091509150600182141561318657602081015193505b831561327557601d548085111561319b578094505b8415613273576131b1818663ffffffff6124c916565b601d8190555060008a6040518060400160405280600b81526020016a557365725265776172647360a81b8152506040516020016131ef929190614c41565b60405160208183030381529060405280519060200120905085815401815586600381111561321957fe5b8a8c6001600160a01b03167fe6c5d7a78caa3f3f24c92ef7f180efb19eb4cc6decff0d5b9cbc4d164b718d0973b72b31907c1c95f3650b64b2469e08edacee5e8f8a604051613269929190614dad565b60405180910390a4505b505b505050505050505050565b600081836132a15760405162461bcd60e51b81526004016109cf9190614f75565b5060008385816132ad57fe5b0495945050505050565b804710156132d75760405162461bcd60e51b81526004016109cf90615046565b6000826001600160a01b0316826040516132f090614c69565b60006040518083038185875af1925050503d806000811461332d576040519150601f19603f3d011682016040523d82523d6000602084013e613332565b606091505b50509050806113995760405162461bcd60e51b81526004016109cf90615036565b60405161139990849063a9059cbb60e01b906133759086908690602401614dad565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613825565b600080848611806133bb575083155b156133c5576134cd565b8286116133d65750869050856134cd565b60006133f086674563918244f4000063ffffffff6126df16565b905061341368056bc75e2d63100000610b658b610b59858463ffffffff6126df16565b9250613441613434670de0b6b3a7640000610b658b8963ffffffff61250b16565b849063ffffffff6124c916565b925061346f613456828663ffffffff6124c916565b610b658568056bc75e2d6310000063ffffffff61250b16565b92508883111561347d578892505b6134a66134998568056bc75e2d6310000063ffffffff6126df16565b849063ffffffff61250b16565b91506134bd6064610b65848863ffffffff61254516565b9150878211156134cb578791505b505b965096945050505050565b60006134e4838361390a565b61351857506001808301805480830180835560009283526020808420909201859055848352908590526040909120556111f2565b5060006111f2565b600061352c838361390a565b1561351857600082815260208490526040902054600184015460001991820191018082146135a457600085600101828154811061356557fe5b906000526020600020015490508086600101848154811061358257fe5b6000918252602080832090910192909255918252869052604090206001830190555b600084815260208690526040812055600185018054806135c057fe5b600190038181906000526020600020016000905590556001925050506111f2565b6040805160a0810182526001600160a01b03808b16825289811660208084019190915230838501819052606080850191909152918a1660808401528351918201845288825281018790529182018590526000918291829161364591908e888861391f565b90935091506136548b83613ad9565b600254602654604051631e2c62d360e01b81526001600160a01b0390921691631e2c62d39161368d918f918f9188918a91600401614d6b565b60206040518083038186803b1580156136a557600080fd5b505afa1580156136b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506136dd9190810190614318565b9050896001600160a01b03168b6001600160a01b03168d7fb4eb3c9b62efcce7021cba5fd9cd0c44df91c2272806ccc5e57df7c912e8d7168c868860405161372793929190614dc8565b60405180910390a499509950999650505050505050565b6040516124169085906323b872dd60e01b9061337590879087908790602401614d05565b600061115e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613bb5565b8015611399576001600160a01b0382166000908152601560205260409020546137d3908263ffffffff6126df16565b6001600160a01b0380841660008181526015602052604090819020939093559151908516907f40a75ae5f7a5336e75f7c7977e12c4b46a9ac0f30de01a2d5b6c1a4f4af63587906126cb908590615175565b613837826001600160a01b0316613bff565b6138535760405162461bcd60e51b81526004016109cf90615146565b60006060836001600160a01b03168360405161386f9190614c5d565b6000604051808303816000865af19150503d80600081146138ac576040519150601f19603f3d011682016040523d82523d6000602084013e6138b1565b606091505b5091509150816138d35760405162461bcd60e51b81526004016109cf90615006565b80511561241657808060200190516138ee9190810190614183565b6124165760405162461bcd60e51b81526004016109cf906150f6565b60009081526020919091526040902054151590565b835160009081906139425760405162461bcd60e51b81526004016109cf90615026565b6000806000866139c357604089015161399b576139668960005b6020020151613c3b565b905080156139965760808a015161398790898c60005b602002015184613c5f565b885161399390826124c9565b89525b6139c3565b6139a689600261395c565b905080156139c35760408901516139bd90826126df565b60408a01525b60208901516139d857885160208a01526139fd565b6020890151895111156139fd5760405162461bcd60e51b81526004016109cf90615156565b855115613a1c5760405162461bcd60e51b81526004016109cf906150e6565b613a268a8a613cf8565b60408b01519194509250613a645788518214613a545760405162461bcd60e51b81526004016109cf90615126565b8015613a5f57908101905b613aca565b6020890151821115613a885760405162461bcd60e51b81526004016109cf90615016565b6040890151831015613aac5760405162461bcd60e51b81526004016109cf90614f96565b8015613aca5760808a0151613ac490898c600161397c565b80830392505b50909890975095505050505050565b60285480156113995760006001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415613b10575081613b95565b600254604051635967aa7560e11b81526001600160a01b039091169063b2cf54ea90613b429087908790600401614dad565b60206040518083038186803b158015613b5a57600080fd5b505afa158015613b6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250613b929190810190614318565b90505b818111156124165760405162461bcd60e51b81526004016109cf90615066565b60008183613bd65760405162461bcd60e51b81526004016109cf9190614f75565b5083613be45750600061115e565b6000836001860381613bf257fe5b0460010195945050505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590613c3357508115155b949350505050565b60006111f268056bc75e2d63100000612fc36017548561250b90919063ffffffff16565b8015612416576001600160a01b038216600090815260186020526040902054613c8e908263ffffffff6126df16565b6001600160a01b03808416600081815260186020526040908190209390935591518592918716907fb23479169712c443e6b00fb0cec3506a5f5926f541df4243d313e11c8c5c71ed90613ce2908690615175565b60405180910390a46124168484848460016130a4565b815160208084015160408086015160608781015187519588015188850151945160009889989497632bea876360e01b97613d3f979296919592949293919291602401614c9d565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925260035491519092506000916001600160a01b031690613d91908490614c5d565b600060405180830381855af49150503d8060008114613dcc576040519150601f19603f3d011682016040523d82523d6000602084013e613dd1565b606091505b509250905080613df35760405162461bcd60e51b81526004016109cf90615116565b81806020019051613e079190810190614336565b9097909650945050505050565b6040518061022001604052806000801916815260200160006001600160601b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081019190915290565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b60405180606001604052806000815260200160008152602001600081525090565b80356111f2816152bc565b80356111f2816152d0565b80516111f2816152d0565b80356111f2816152d9565b80356111f2816152e2565b60008083601f840112613ff757600080fd5b50813567ffffffffffffffff81111561400f57600080fd5b60208301915083600182028301111561402757600080fd5b9250929050565b80356111f2816152eb565b80516111f2816152d9565b60006020828403121561405657600080fd5b6000613c338484613fae565b6000806040838503121561407557600080fd5b60006140818585613fae565b925050602061409285828601613fae565b9150509250929050565b600080604083850312156140af57600080fd5b60006140bb8585613fae565b925050602061409285828601613fb9565b600080604083850312156140df57600080fd5b60006140eb8585613fae565b925050602061409285828601613fcf565b60008060008060008060c0878903121561411557600080fd5b60006141218989613fae565b965050602061413289828a01613fcf565b955050604061414389828a01613fcf565b945050606061415489828a0161402e565b935050608061416589828a01613fb9565b92505060a061417689828a01613fb9565b9150509295509295509295565b60006020828403121561419557600080fd5b6000613c338484613fc4565b6000602082840312156141b357600080fd5b6000613c338484613fcf565b600080604083850312156141d257600080fd5b60006140818585613fcf565b6000806000606084860312156141f357600080fd5b60006141ff8686613fcf565b935050602061421086828701613fae565b925050604061422186828701613fcf565b9150509250925092565b6000806040838503121561423e57600080fd5b60006140eb8585613fcf565b60008060008060006080868803121561426257600080fd5b600061426e8888613fcf565b955050602061427f88828901613fcf565b945050604061429088828901613fb9565b935050606086013567ffffffffffffffff8111156142ad57600080fd5b6142b988828901613fe5565b92509250509295509295909350565b6000806000606084860312156142dd57600080fd5b60006142e98686613fcf565b935050602061421086828701613fcf565b60006020828403121561430c57600080fd5b6000613c338484613fda565b60006020828403121561432a57600080fd5b6000613c338484614039565b6000806040838503121561434957600080fd5b60006143558585614039565b925050602061409285828601614039565b60008060006060848603121561437b57600080fd5b60006143878686613fcf565b935050602061439886828701613fcf565b925050604061422186828701613fb9565b60006143b58383614ae4565b50506102200190565b6143cf6143ca8261522c565b61529b565b82525050565b6143cf8161522c565b60006143e98261521a565b6143f3818561521e565b93506143fe83615214565b8060005b8381101561442c57815161441688826143a9565b975061442183615214565b925050600101614402565b509495945050505050565b6143cf81615237565b6143cf8161523c565b60006144548261521a565b61445e8185615227565b935061446e81856020860161526f565b9290920192915050565b6143cf81615264565b600061448c8261521a565b614496818561521e565b93506144a681856020860161526f565b6144af816152ac565b9093019392505050565b60006144c660138361521e565b7207769746864726177416d6f756e74206973203606c1b815260200192915050565b60006144f5601b8361521e565b7f696e73756666696369656e742073776170206c69717569646974790000000000815260200192915050565b600061452e60268361521e565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181526564647265737360d01b602082015260400192915050565b600061457660148361521e565b73696e646566696e6974652d7465726d206f6e6c7960601b815260200192915050565b60006145a660228361521e565b7f6465706f7369742063616e6e6f7420636f766572206261636b20696e746572658152611cdd60f21b602082015260400192915050565b60006145ea601b8361521e565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b600061462360108361521e565b6f1ddc9bdb99c8185cdcd95d081cd95b9d60821b815260200192915050565b600061464f600e8361521e565b6d1b1bd85b881d1bdbc81cda1bdc9d60921b815260200192915050565b600061467960208361521e565b7f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815260200192915050565b60006146b260138361521e565b72737761702066696c6c20746f6f206c6172676560681b815260200192915050565b60006146e160118361521e565b700736f75726365416d6f756e74203d3d203607c1b815260200192915050565b600061470e603a8361521e565b7f416464726573733a20756e61626c6520746f2073656e642076616c75652c207281527f6563697069656e74206d61792068617665207265766572746564000000000000602082015260400192915050565b600061476d601d8361521e565b7f416464726573733a20696e73756666696369656e742062616c616e6365000000815260200192915050565b60006147a660188361521e565b7f776974686472617720616d6f756e7420746f6f20686967680000000000000000815260200192915050565b60006147df600e8361521e565b6d7377617020746f6f206c6172676560901b815260200192915050565b6000614809600e8361521e565b6d1b9bdd08185d5d1a1bdc9a5e995960921b815260200192915050565b600061483360218361521e565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b6000614876600c8361521e565b6b1d5b985d5d1a1bdc9a5e995960a21b815260200192915050565b600061489e60128361521e565b7106465706f736974416d6f756e7420697320360741b815260200192915050565b60006148cc60128361521e565b713ab73432b0b63a343c903837b9b4ba34b7b760711b815260200192915050565b60006111f2600083615227565b6000614907600e8361521e565b6d1b1bd85b881a5cc818db1bdcd95960921b815260200192915050565b6000614931600c8361521e565b6b1b9bdb9499595b9d1c985b9d60a21b815260200192915050565b6000614959600d8361521e565b6c696e76616c696420737461746560981b815260200192915050565b6000614982602a8361521e565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b602082015260400192915050565b60006149ce60138361521e565b721b1bd85b881d195c9b481a185cc8195b991959606a1b815260200192915050565b60006149fd600b8361521e565b6a1cddd85c0819985a5b195960aa1b815260200192915050565b6000614a2460168361521e565b751cddd85c081d1bdbc81b185c99d9481d1bc8199a5b1b60521b815260200192915050565b6000614a5660168361521e565b750cae8d0cae440c8cae0dee6d2e840dad2e6dac2e8c6d60531b815260200192915050565b6000614a88601f8361521e565b7f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400815260200192915050565b6000614ac160148361521e565b730dad2dc40cee4cac2e8cae440e8d0c2dc40dac2f60631b815260200192915050565b8051610220830190614af68482614440565b506020820151614b096020850182614c38565b506040820151614b1c60408501826143d5565b506060820151614b2f60608501826143d5565b506080820151614b426080850182614440565b5060a0820151614b5560a0850182614440565b5060c0820151614b6860c0850182614440565b5060e0820151614b7b60e0850182614440565b50610100820151614b90610100850182614440565b50610120820151614ba5610120850182614440565b50610140820151614bba610140850182614440565b50610160820151614bcf610160850182614440565b50610180820151614be4610180850182614440565b506101a0820151614bf96101a0850182614440565b506101c0820151614c0e6101c0850182614440565b506101e0820151614c236101e0850182614440565b50610200820151612416610200850182614440565b6143cf81615258565b6000614c4d82856143be565b601482019150613c338284614449565b600061115e8284614449565b60006111f2826148ed565b602081016111f282846143d5565b60408101614c9082856143d5565b61115e60208301846143d5565b60e08101614cab828a6143d5565b614cb860208301896143d5565b614cc560408301886143d5565b614cd260608301876143d5565b614cdf6080830186614440565b614cec60a0830185614440565b614cf960c0830184614440565b98975050505050505050565b60608101614d1382866143d5565b614d2060208301856143d5565b613c336040830184614440565b60808101614d3b82876143d5565b614d4860208301866143d5565b614d556040830185614440565b614d626060830184614440565b95945050505050565b60a08101614d7982886143d5565b614d8660208301876143d5565b614d936040830186614440565b614da06060830185614440565b610fa96080830184614440565b60408101614dbb82856143d5565b61115e6020830184614440565b60608101614dd682866143d5565b614d206020830185614440565b60808101614df182876143d5565b614d486020830186614440565b6020808252810161115e81846143de565b602081016111f28284614437565b6101008101614e2c828b614440565b614e39602083018a614437565b614e4660408301896143d5565b614e5360608301886143d5565b614e6060808301876143d5565b614e6d60a0830186614440565b614e7a60c0830185614440565b614e8760e0830184614440565b9998505050505050505050565b6101808101614ea3828f614440565b614eb0602083018e614440565b614ebd604083018d614440565b614eca606083018c614440565b614ed7608083018b614440565b614ee460a083018a614440565b614ef160c0830189614440565b614efe60e0830188614440565b614f0c610100830187614440565b614f1a6101208301866143d5565b614f286101408301856143d5565b614f36610160830184614437565b9d9c50505050505050505050505050565b60408101614f558285614440565b8181036020830152613c338184614481565b602081016111f28284614478565b6020808252810161115e8184614481565b602080825281016111f2816144b9565b602080825281016111f2816144e8565b602080825281016111f281614521565b602080825281016111f281614569565b602080825281016111f281614599565b602080825281016111f2816145dd565b602080825281016111f281614616565b602080825281016111f281614642565b602080825281016111f28161466c565b602080825281016111f2816146a5565b602080825281016111f2816146d4565b602080825281016111f281614701565b602080825281016111f281614760565b602080825281016111f281614799565b602080825281016111f2816147d2565b602080825281016111f2816147fc565b602080825281016111f281614826565b602080825281016111f281614869565b602080825281016111f281614891565b602080825281016111f2816148bf565b602080825281016111f2816148fa565b602080825281016111f281614924565b602080825281016111f28161494c565b602080825281016111f281614975565b602080825281016111f2816149c1565b602080825281016111f2816149f0565b602080825281016111f281614a17565b602080825281016111f281614a49565b602080825281016111f281614a7b565b602080825281016111f281614ab4565b61022081016111f28284614ae4565b602081016111f28284614440565b60408101614dbb8285614440565b60608101614dd68286614440565b60a081016151ad8288614440565b614d866020830187614440565b60c081016151c88289614440565b6151d56020830188614440565b6151e26040830187614440565b6151ef6060830186614440565b6151fc6080830185614440565b61520960a0830184614440565b979650505050505050565b60200190565b5190565b90815260200190565b919050565b60006111f28261524c565b151590565b90565b6001600160e01b03191690565b6001600160a01b031690565b6001600160601b031690565b60006111f28261522c565b60005b8381101561528a578181015183820152602001615272565b838111156124165750506000910152565b60006111f28260006111f2826152b6565b601f01601f191690565b60601b90565b6152c58161522c565b811461155857600080fd5b6152c581615237565b6152c58161523c565b6152c58161523f565b6003811061155857600080fdfea365627a7a7231582054acbafafa6908356df4b14019a2815a4f242caed603fbe98f637bc9471c488f6c6578706572696d656e74616cf564736f6c63430005110040
Deployed Bytecode Sourcemap
59902:27073:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29147:69;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;29147:69:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;69578:2856;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;69578:2856:0;;;;;;;;:::i;:::-;;;;;;;;28646:47;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;28646:47:0;;;;;;;;:::i;:::-;;;;;;;;32572:56;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;32572:56:0;;;;;;;;:::i;30912:45::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;30912:45:0;;;:::i;32006:32::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32006:32:0;;;:::i;73707:285::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;73707:285:0;;;;;;;;:::i;29018:67::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;29018:67:0;;;;;;;;:::i;31184:56::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;31184:56:0;;;;;;;;:::i;77477:1357::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;77477:1357:0;;;;;;;;:::i;:::-;;;;;;;;1707:86;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1707:86:0;;;:::i;29280:71::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;29280:71:0;;;;;;;;:::i;:::-;;;;;;;;30560:56;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;30560:56:0;;;;;;;;:::i;30424:43::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;30424:43:0;;;:::i;1515:93::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1515:93:0;;;:::i;:::-;;;;;;;;33219:39;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33219:39:0;;;:::i;80557:144::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;80557:144:0;;;:::i;29568:53::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;29568:53:0;;;;;;;;:::i;:::-;;;;;;;;;;79380:1169;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;79380:1169:0;;;;;;;;:::i;29427:78::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;29427:78:0;;;;;;;;:::i;:::-;;;;;;;;;;;;32804:48;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;32804:48:0;;;;;;;;:::i;33079:44::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33079:44:0;;;:::i;28508:24::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;28508:24:0;;;:::i;28374:25::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;28374:25:0;;;:::i;31871:32::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31871:32:0;;;:::i;79115:257::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;79115:257:0;;;;;;;;:::i;:::-;;;;;;;;11041:79;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11041:79:0;;;:::i;32453:56::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;32453:56:0;;;;;;;;:::i;11387:94::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11387:94:0;;;:::i;30713:56::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;30713:56:0;;;;;;;;:::i;76379:890::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;76379:890:0;;;;;;;;:::i;:::-;;;;;;;;;;;1615:85;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1615:85:0;;;:::i;78842:265::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;78842:265:0;;;;;;;;:::i;32144:45::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32144:45:0;;;:::i;72442:478::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;72442:478:0;;;;;;;;:::i;:::-;;31667:58;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;31667:58:0;;;;;;;;:::i;31513:::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;31513:58:0;;;;;;;;:::i;28782:38::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;28782:38:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;60029:1018;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;60029:1018:0;;;;;;;;:::i;28893:49::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;28893:49:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;65603:3967;;;;;;;;;:::i;74809:1094::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;74809:1094:0;;;;;;;;:::i;32929:40::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32929:40:0;;;:::i;31032:56::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;31032:56:0;;;;;;;;:::i;62937:2417::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;62937:2417:0;;;;;;;;:::i;61055:1874::-;;;;;;;;;:::i;65362:233::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;65362:233:0;;;;;;;;:::i;30290:29::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;30290:29:0;;;:::i;31382:47::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31382:47:0;;;:::i;72928:771::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;72928:771:0;;;;;;;;:::i;32274:84::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;32274:84:0;;;;;;;;:::i;11636:109::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;11636:109:0;;;;;;;;:::i;29147:69::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;69578:2856::-;69750:22;8177:1;8870:14;;:39;8862:64;;;;-1:-1:-1;;;8862:64:0;;;;;;;;;;;;;;;;;8285:1;8937:14;:40;69798:19;69790:51;;;;-1:-1:-1;;;69790:51:0;;;;;;;;;69852:22;69877:13;;;:5;:13;;;;;;;;69949:22;;;;69938:34;;:10;:34;;;;;;69993:16;;;;-1:-1:-1;;;69993:16:0;;;;69985:43;;;;-1:-1:-1;;;69985:43:0;;;;;;;;;70075:18;;;;-1:-1:-1;;;;;70075:18:0;70061:10;:32;;:92;;-1:-1:-1;70128:12:0;;70110:31;;;;:17;:31;;;;;;;;70142:10;70110:43;;;;;;;;;;70061:92;70039:154;;;;-1:-1:-1;;;70039:154:0;;;;;;;;;70212:27;;;;:32;70204:65;;;;-1:-1:-1;;;70204:65:0;;;;;;;;;70313:15;70288:9;:22;;;:40;70280:72;;;;-1:-1:-1;;;70280:72:0;;;;;;;;;70439:16;;;;70470:25;;;;70412:94;;-1:-1:-1;;;;;70439:16:0;;;;70470:25;70412:12;:94::i;:::-;70573:12;;70519:38;70560:26;;;:12;:26;;;;;70707:25;;;;70747:18;;;;70560:26;;70599:207;;70560:26;;-1:-1:-1;;;;;70707:25:0;;;;70747:18;70780:15;70599:34;:207::i;:::-;70819:32;70854:131;70978:6;70854:105;70930:17;:28;;;70854:57;70895:15;70854:9;:22;;;:40;;:57;;;;:::i;:::-;:75;:105;:75;:105;:::i;:::-;:123;:131;:123;:131;:::i;:::-;70819:166;;71021:24;71004:14;:41;70996:78;;;;-1:-1:-1;;;70996:78:0;;;;;;;;;71121:25;;;;-1:-1:-1;;;;;71121:25:0;1565:42;71121:47;71117:338;;;71185:93;71222:8;71249:14;71185:18;:93::i;:::-;71117:338;;;71343:25;;;;71311:132;;-1:-1:-1;;;;;71343:25:0;71387:8;71414:14;71311:13;:132::i;:::-;71543:28;;71484:88;;:40;:14;71517:6;71484:40;:32;:40;:::i;:88::-;71467:105;;71619:14;71594:9;:22;;;:39;71585:67;;;;-1:-1:-1;;;71585:67:0;;;;;;;;;71690:22;;;;:56;;71731:14;71690:56;:40;:56;:::i;:::-;71665:22;;;:81;;;71792:15;-1:-1:-1;71767:112:0;;;;;71872:7;71853:15;71828:9;:22;;;:40;71827:52;71767:112;71759:162;;;;-1:-1:-1;;;71759:162:0;;;;;;;;;71967:30;;;;:64;;72016:14;71967:64;:48;:64;:::i;:::-;71934:30;;;:97;72116:14;72131:16;;;;-1:-1:-1;;;;;72131:16:0;;;72116:32;;;;;;;;;;;;72149:25;;;;;;;;72116:59;;;;;;;;;:69;;:103;;72204:14;72116:103;:87;:103;:::i;:::-;72044:14;72059:16;;;;-1:-1:-1;;;;;72059:16:0;;;72044:32;;;;;;;;;;;;72077:25;;;;;;;;72044:59;;;;;;;;;;:69;;;:175;;;;72303:25;;72270:18;;;;72393:22;;;;72237:189;;72343:6;;72303:25;;;;72270:18;;;;;72237:189;;;;72364:14;;72393:22;72237:189;;;;;;;;;;-1:-1:-1;;8177:1:0;9000:14;:38;-1:-1:-1;69578:2856:0;;;-1:-1:-1;;;;69578:2856:0:o;28646:47::-;;;;;;;;;;;;-1:-1:-1;;;;;28646:47:0;;:::o;32572:56::-;;;;;;;;;;;;-1:-1:-1;;;;;32572:56:0;;:::o;30912:45::-;;;;:::o;32006:32::-;;;;:::o;73707:285::-;73807:22;73847:12;73889:4;73895:13;;;;;;;;;;;;;-1:-1:-1;;;73895:13:0;;;73872:37;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;73872:37:0;;;73862:48;;49:4:-1;73862:48:0;;;;73963:11;;73930:55;-1:-1:-1;;;73930:55:0:o;29018:67::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;31184:56::-;;;;;;;;;;;;;:::o;77477:1357::-;77699:33;77750:43;77796:8;:82;;-1:-1:-1;;;;;77856:22:0;;;;;;:16;:22;;;;;77796:82;;;-1:-1:-1;;;;;77820:20:0;;;;;;:14;:20;;;;;77796:82;77750:128;;77891:11;77905:37;77929:12;:3;:10;:12::i;:::-;77905:16;:5;77915;77905:16;:9;:16;:::i;:::-;:23;:37;:23;:37;:::i;:::-;77891:51;;77966:3;77957:5;:12;77953:61;;-1:-1:-1;77986:16:0;;-1:-1:-1;77986:16:0;77953:61;78032:9;;;;-1:-1:-1;78032:9:0;78084:30;;:::i;:::-;78158:3;78137:25;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;78125:37:0;-1:-1:-1;;;78190:5:0;;;;;78173:508;78202:5;78197:1;:10;78173:508;;78240:118;78267:10;:3;78275:1;78267:10;:7;:10;:::i;:::-;78306:8;78333:10;78240:8;:118::i;:::-;78377:15;;78229:129;;-1:-1:-1;78373:177:0;;78422:6;78418:117;;78453:5;;78418:117;78507:8;;78418:117;78593:8;78566:9;78583:5;;;;;;;78576;:13;78566:24;;;;;;;;;;;;;:35;;;;78622:1;78627;78622:6;78618:52;;;78649:5;;78618:52;-1:-1:-1;;78209:3:0;78173:508;;;-1:-1:-1;78697:8:0;;78693:134;;78731:3;78722:12;;;;78795:5;78784:9;78777:24;78758:58;77477:1357;;;;;;;;;;;;;:::o;1707:86::-;1751:42;1707:86;:::o;29280:71::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;30560:56::-;;;;;;;;;;;;;:::o;30424:43::-;;;;:::o;1515:93::-;1565:42;1515:93;:::o;33219:39::-;;;;:::o;80557:144::-;80638:7;80670:23;:14;:21;:23::i;:::-;80663:30;;80557:144;:::o;29568:53::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;79380:1169::-;79529:33;79580:11;79594:48;79618:23;:14;:21;:23::i;:::-;79594:16;:5;79604;79594:16;:9;:16;:::i;:48::-;79580:62;;79666:3;79657:5;:12;79653:61;;-1:-1:-1;79686:16:0;;79653:61;79732:9;;;;-1:-1:-1;79732:9:0;79784:30;;:::i;:::-;79858:3;79837:25;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;79825:37:0;-1:-1:-1;;;79890:5:0;;;;;79873:523;79902:5;79897:1;:10;79873:523;;79940:133;79967:21;:14;79986:1;79967:21;:18;:21;:::i;:::-;80017:12;80048:10;79940:8;:133::i;:::-;80092:15;;79929:144;;-1:-1:-1;80088:177:0;;80137:6;80133:117;;80168:5;;80133:117;80222:8;;80133:117;80308:8;80281:9;80298:5;;;;;;;80291;:13;80281:24;;;;;;;;;;;;;:35;;;;80337:1;80342;80337:6;80333:52;;;80364:5;;80333:52;-1:-1:-1;;79909:3:0;79873:523;;;-1:-1:-1;80412:8:0;;80408:134;;80446:3;80437:12;;;;80510:5;80499:9;80492:24;80473:58;79380:1169;;;;;;;;;:::o;29427:78::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;32804:48::-;;;;;;;;;;;;;;;:::o;33079:44::-;;;;:::o;28508:24::-;;;-1:-1:-1;;;;;28508:24:0;;:::o;28374:25::-;;;-1:-1:-1;;;;;28374:25:0;;:::o;31871:32::-;;;;:::o;79115:257::-;79208:30;;:::i;:::-;79263:101;79286:6;79307:12;79334:5;79263:8;:101::i;:::-;79256:108;79115:257;-1:-1:-1;;79115:257:0:o;11041:79::-;11106:6;;-1:-1:-1;;;;;11106:6:0;11041:79;:::o;32453:56::-;;;;;;;;;;;;-1:-1:-1;;;;;32453:56:0;;:::o;11387:94::-;11467:6;;11427:4;;-1:-1:-1;;;;;11467:6:0;11451:12;:10;:12::i;:::-;-1:-1:-1;;;;;11451:22:0;;11444:29;;11387:94;:::o;30713:56::-;;;;;;;;;;;;;:::o;76379:890::-;76498:17;76687:13;;;:5;:13;;;;;;;;:26;;;;;76676:38;;:10;:38;;;;;;:48;;;76756:20;;;:12;:20;;;;;:31;;76821:33;;;76890:13;;;;:26;;;-1:-1:-1;;;;;76676:48:0;;;;76756:31;;76821:33;76498:17;;76950:15;:30;-1:-1:-1;76950:89:0;;77024:15;76950:89;;;76996:12;76950:89;76927:112;;77092:12;77077;:27;:184;;77260:1;77077:184;;;77120:120;77233:6;77120:90;77191:18;77120:48;:12;77155;77120:48;:34;:48;:::i;:120::-;77050:211;;76379:890;;;;;;;:::o;1615:85::-;1658:42;1615:85;:::o;78842:265::-;78967:7;78999:8;:100;;-1:-1:-1;;;;;79068:22:0;;;;;;:16;:22;;;;;:31;;:29;:31::i;:::-;78999:100;;;-1:-1:-1;;;;;79023:20:0;;;;;;:14;:20;;;;;:29;;:27;:29::i;32144:45::-;;;;:::o;72442:478::-;72687:10;72710:1;72666:32;;;:20;:32;;;;;;-1:-1:-1;;;;;72666:32:0;72658:73;;;;-1:-1:-1;;;72658:73:0;;;;;;;;;72744:168;72776:6;72797:23;72835:29;72879:5;72744:17;:168::i;:::-;72442:478;;;:::o;31667:58::-;;;;;;;;;;;;;:::o;31513:::-;;;;;;;;;;;;;:::o;28782:38::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;28782:38:0;;;;;;;;-1:-1:-1;;;28782:38:0;;;;;:::o;60029:1018::-;11253:9;:7;:9::i;:::-;11245:34;;;;-1:-1:-1;;;11245:34:0;;;;;;;;;60128:51;-1:-1:-1;;;60172:6:0;60128:10;:51::i;:::-;60190:52;-1:-1:-1;;;60235:6:0;60190:10;:52::i;:::-;60253:57;-1:-1:-1;;;60303:6:0;60253:10;:57::i;:::-;60321:52;-1:-1:-1;;;60366:6:0;60321:10;:52::i;:::-;60384;-1:-1:-1;;;60429:6:0;60384:10;:52::i;:::-;60447:50;-1:-1:-1;;;60490:6:0;60447:10;:50::i;:::-;60508:46;-1:-1:-1;;;60547:6:0;60508:10;:46::i;:::-;60565:50;-1:-1:-1;;;60608:6:0;60565:10;:50::i;:::-;60626:55;-1:-1:-1;;;60674:6:0;60626:10;:55::i;:::-;60692:53;-1:-1:-1;;;60738:6:0;60692:10;:53::i;:::-;60756:46;-1:-1:-1;;;60795:6:0;60756:10;:46::i;:::-;60813:51;-1:-1:-1;;;60857:6:0;60813:10;:51::i;:::-;60875:41;-1:-1:-1;;;60909:6:0;60875:10;:41::i;:::-;60927:48;-1:-1:-1;;;60968:6:0;60927:10;:48::i;:::-;60986:53;-1:-1:-1;;;61032:6:0;60986:10;:53::i;:::-;60029:1018;:::o;28893:49::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;28893:49:0;;;;;;;;;;;;;;;:::o;65603:3967::-;65854:23;8177:1;8870:14;;:39;8862:64;;;;-1:-1:-1;;;8862:64:0;;;;;;;;;8285:1;8937:14;:40;65903:18;65895:49;;;;-1:-1:-1;;;65895:49:0;;;;;;;;;65955:22;65980:13;;;:5;:13;;;;;;;;66052:22;;;;66041:34;;:10;:34;;;;;;66096:16;;;;-1:-1:-1;;;66096:16:0;;;;66088:43;;;;-1:-1:-1;;;66088:43:0;;;;;;;;;66165:13;66164:14;:63;;;-1:-1:-1;66209:18:0;;;;-1:-1:-1;;;;;66209:18:0;66195:10;:32;66164:63;:123;;;-1:-1:-1;66262:12:0;;66244:31;;;;:17;:31;;;;;;;;66276:10;66244:43;;;;;;;;;;66164:123;66142:185;;;;-1:-1:-1;;;66142:185:0;;;;;;;;;66346:27;;;;:32;66338:65;;;;-1:-1:-1;;;66338:65:0;;;;;;;;;66422:9;:14;;:85;;;66442:13;66441:14;:65;;;;-1:-1:-1;66459:25:0;;;;-1:-1:-1;;;;;66459:25:0;1565:42;66459:47;66441:65;66414:114;;;;-1:-1:-1;;;66414:114:0;;;;;;;;;66615:16;;;;66646:25;;;;66588:94;;-1:-1:-1;;;;;66615:16:0;;;;66646:25;66588:12;:94::i;:::-;66749:12;;66695:38;66736:26;;;:12;:26;;;;;66883:25;;;;66923:18;;;;66736:26;;66775:207;;66736:26;;-1:-1:-1;;;;;66883:25:0;;;;66923:18;66956:15;66775:34;:207::i;:::-;67112:24;67169:9;:22;;;67151:15;:40;67147:431;;;67265:22;;;;67227:61;;:15;;:61;:37;:61;:::i;:::-;67361:28;;67208:80;;-1:-1:-1;67322:68:0;;67208:80;;67322:68;:38;:68;:::i;:::-;67303:87;-1:-1:-1;67424:46:0;67303:87;67463:6;67424:46;:38;:46;:::i;:::-;67405:65;;67511:16;67495:13;:32;67487:79;;;;-1:-1:-1;;;67487:79:0;;;;;;;;;67619:22;67656:13;67652:650;;;67703:130;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;67703:130:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67743:9;;67805:13;67703:21;:130::i;:::-;67686:147;;67652:650;;;67870:9;67866:425;;67940:25;;;;67905:148;;-1:-1:-1;;;;;67940:25:0;67988:10;68021:13;67905:12;:148::i;:::-;67866:425;;;68115:13;68102:9;:26;68094:61;;;;-1:-1:-1;;;68094:61:0;;;;;;;;;68174:101;68214:10;68247:9;68174:17;:101::i;:::-;68318:21;;68314:330;;68372:53;:13;68408:16;68372:53;:35;:53;:::i;:::-;68522:16;;;;68557:25;;;;68356:69;;-1:-1:-1;68483:149:0;;-1:-1:-1;;;;;68522:16:0;;;;68557:25;68601:16;68483:20;:149::i;:::-;68732:28;;68674:87;;:39;:13;68706:6;68674:39;:31;:39;:::i;:87::-;68799:22;;;;68656:105;;-1:-1:-1;68799:57:0;;68656:105;68799:57;:40;:57;:::i;:::-;68774:22;;;:82;;;68902:15;-1:-1:-1;68877:112:0;;;;;68982:7;68963:15;68938:9;:22;;;:40;68937:52;68877:112;68869:162;;;;-1:-1:-1;;;68869:162:0;;;;;;;;;69077:30;;;;:63;;69126:13;69077:63;:48;:63;:::i;:::-;69044:30;;;:96;69225:14;69240:16;;;;-1:-1:-1;;;;;69240:16:0;;;69225:32;;;;;;;;;;;;69258:25;;;;;;;;69225:59;;;;;;;;;:69;;:102;;69313:13;69225:102;:87;:102;:::i;:::-;69153:14;:32;69168:9;:16;;;;;;;;;;-1:-1:-1;;;;;69168:16:0;-1:-1:-1;;;;;69153:32:0;-1:-1:-1;;;;;69153:32:0;;;;;;;;;;;;:59;69186:15;:25;;;;;;;;;;-1:-1:-1;;;;;69186:25:0;-1:-1:-1;;;;;69153:59:0;-1:-1:-1;;;;;69153:59:0;;;;;;;;;;;;:69;;:174;;;;69451:6;69411:15;:25;;;;;;;;;;-1:-1:-1;;;;;69411:25:0;-1:-1:-1;;;;;69345:217:0;69378:9;:18;;;;;;;;;;-1:-1:-1;;;;;69378:18:0;-1:-1:-1;;;;;69345:217:0;;69472:13;69500:14;69529:9;:22;;;69345:217;;;;;;;;;;;;;;;;;-1:-1:-1;;8177:1:0;9000:14;:38;-1:-1:-1;65603:3967:0;;;-1:-1:-1;;;;;;;65603:3967:0:o;74809:1094::-;74958:20;74993:24;75032:26;75073:22;75110:26;75151:22;75191:41;;:::i;:::-;-1:-1:-1;;;;;;75235:22:0;;;;;;;:14;:22;;;;;;;;:33;;;;;;;;;;;;75191:77;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75298:105;;75396:6;;75298:93;;75191:77;75298:57;;:15;;:57;:19;:57;:::i;:105::-;75281:122;;75435:19;:29;;;75418:14;:46;75414:111;;;75496:19;:29;;;75479:46;;75414:111;75560:29;;;;75604:34;:77;;75680:1;75604:77;;;75641:19;:36;;;75604:77;75696:30;;;;75741:36;;;;:62;;75802:1;75741:62;;;75785:14;75741:62;75818:17;;75850:34;;75538:357;;;;-1:-1:-1;75538:357:0;;-1:-1:-1;75538:357:0;-1:-1:-1;75818:17:0;;-1:-1:-1;75850:34:0;-1:-1:-1;74809:1094:0;-1:-1:-1;;;74809:1094:0:o;32929:40::-;;;;:::o;31032:56::-;;;;;;;;;;;;;:::o;62937:2417::-;63109:28;8177:1;8870:14;;:39;8862:64;;;;-1:-1:-1;;;8862:64:0;;;;;;;;;8285:1;8937:14;:40;63163:19;63155:51;;;;-1:-1:-1;;;63155:51:0;;;;;;;;;63217:22;63242:13;;;:5;:13;;;;;;;;63314:22;;;;63303:34;;:10;:34;;;;;;63358:16;;;;-1:-1:-1;;;63358:16:0;;;;63350:43;;;;-1:-1:-1;;;63350:43:0;;;;;;;;;63440:18;;;;-1:-1:-1;;;;;63440:18:0;63426:10;:32;;:92;;-1:-1:-1;63493:12:0;;63475:31;;;;:17;:31;;;;;;;;63507:10;63475:43;;;;;;;;;;63426:92;63404:154;;;;-1:-1:-1;;;63404:154:0;;;;;;;;;63597:31;;;;;63660:20;;;;;63727:10;;;63768:25;;;;63838:19;;;;63897:33;;;;63715:226;;-1:-1:-1;;;63715:226:0;;-1:-1:-1;;;;;63597:31:0;;;;63660:20;;63571:23;;63727:10;;;;63715:38;;:226;;63768:25;;;;;63597:31;;63660:20;;63715:226;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63715:226:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;63715:226: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;63715:226:0;;;;;;;;;63693:248;;63975:11;63958:14;:28;63954:165;;;64026:11;64003:34;;63954:165;;;64093:14;64070:37;;63954:165;64144:77;;;;;;;;;;;;;;;;;;;:10;;64173:20;;64144:77;:28;:77;:::i;:::-;64232:20;;;:33;;;64131:90;-1:-1:-1;;;;;;64282:37:0;;1565:42;64282:37;64278:330;;;64336:99;64373:8;64400:20;64336:18;:99::i;:::-;64278:330;;;64468:128;64500:15;64534:8;64561:20;64468:13;:128::i;:::-;64734:10;;;64800:25;;;;64722:114;;-1:-1:-1;;;64722:114:0;;64655:28;;;;-1:-1:-1;;;;;64734:10:0;;;;64722:33;;:114;;64770:15;;64800:25;;;64722:114;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;64722:114:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;64722:114: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;64722:114:0;;;;;;;;;64654:182;;;;64851:20;64875:1;64851:25;64847:334;;64893:276;64929:6;64954:121;65049:25;64954:68;:20;65001;64954:68;:46;:68;:::i;:121::-;65094:20;65133:4;64893:17;:276::i;:::-;65231:18;;;;65198:148;;65294:6;;-1:-1:-1;;;;;65198:148:0;;;;65231:18;;;65198:148;;;;65315:20;;65198:148;;;;;;;;;;-1:-1:-1;;8177:1:0;9000:14;:38;-1:-1:-1;62937:2417:0;;;-1:-1:-1;;;;;;;62937:2417:0:o;61055:1874::-;8177:1;8870:14;;:39;8862:64;;;;-1:-1:-1;;;8862:64:0;;;;;;;;;8285:1;8937:14;:40;61262:18;61254:49;;;;-1:-1:-1;;;61254:49:0;;;;;;;;;61316:22;61341:13;;;:5;:13;;;;;61373:16;;;;-1:-1:-1;;;61373:16:0;;;;61365:43;;;;-1:-1:-1;;;61365:43:0;;;;;;;;;61469:22;;;;61421:34;61458;;;:10;:34;;;;;61531:31;;;;61594:20;;;;-1:-1:-1;;;;;61531:31:0;;;;61635:9;:14;;:55;;-1:-1:-1;;;;;;61653:37:0;;1565:42;61653:37;61635:55;61627:84;;;;-1:-1:-1;;;61627:84:0;;;;;;;;;61737:43;:10;61766:13;61737:43;:28;:43;:::i;:::-;61791:20;;;:33;;;61724:56;-1:-1:-1;61841:9:0;61837:367;;61872:122;61903:15;61937:10;61966:13;61872:12;:122::i;:::-;61837:367;;;62048:13;62035:9;:26;62027:61;;;;-1:-1:-1;;;62027:61:0;;;;;;;;;62103:89;62139:10;62168:9;62103:17;:89::i;:::-;62330:10;;;62396:25;;;;62318:114;;-1:-1:-1;;;62318:114:0;;62251:28;;;;-1:-1:-1;;;;;62330:10:0;;;;62318:33;;:114;;62366:15;;62396:25;;;62318:114;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;62318:114:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62318:114: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;62318:114:0;;;;;;;;;62250:182;;;;62447:20;62471:1;62447:25;62443:321;;62489:263;62525:6;62550:114;62638:25;62550:61;:13;62590:20;62550:61;:39;:61;:::i;:114::-;62683:13;62715:5;62489:17;:263::i;:::-;62813:18;;;;62781:140;;62876:6;;-1:-1:-1;;;;;62781:140:0;;;;62813:18;;;62781:140;;;;62897:13;;62781:140;;;;;;;;;;-1:-1:-1;;8177:1:0;9000:14;:38;-1:-1:-1;;;;;;61055:1874:0:o;65362:233::-;65505:82;65532:10;65567:9;65505:12;:82::i;30290:29::-;;;-1:-1:-1;;;;;30290:29:0;;:::o;31382:47::-;;;;:::o;72928:771::-;73014:19;73051:12;73093:10;73105:13;;;;;;;;;;;;;-1:-1:-1;;;73105:13:0;;;73076:43;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;73076:43:0;;;73066:54;;;;;;73051:69;;73176:4;73170:11;73155:26;;73208:11;73223:1;73208:16;73204:488;;73282:1;73269:15;;73335:17;;:52;;73375:11;73335:52;:39;:52;:::i;:::-;73315:17;:72;73404:106;;-1:-1:-1;;;73404:106:0;;1751:42;;73404:34;;:106;;73457:8;;73484:11;;73404:106;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;73404:106:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;73404:106: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;73404:106:0;;;;;;;;;;1751:42;-1:-1:-1;;;;;73532:148:0;73591:8;-1:-1:-1;;;;;73532:148:0;73562:10;-1:-1:-1;;;;;73532:148:0;;73654:11;73532:148;;;;;;;;;;;;;;;73204:488;72928:771;;;;:::o;32274:84::-;;;;;;;;;;;;;;;;;;;;;;;:::o;11636:109::-;11253:9;:7;:9::i;:::-;11245:34;;;;-1:-1:-1;;;11245:34:0;;;;;;;;;11709:28;11728:8;11709:18;:28::i;45526:1300::-;-1:-1:-1;;;;;45685:22:0;;;45640:42;45685:22;;;:14;:22;;;;;;;;:37;;;;;;;;;;;45777:30;;;;45685:37;;45640:42;45777:35;;;;:80;;-1:-1:-1;45816:36:0;;;;:41;;45777:80;45773:1046;;;45892:159;46044:6;45892:129;45990:19;:30;;;45892:75;45930:19;:36;;;45892:15;:37;;:75;;;;:::i;:159::-;46107:15;46068:36;;;:54;46161:29;;;;45874:177;;-1:-1:-1;46143:47:0;;46139:114;;;-1:-1:-1;46224:29:0;;;;46139:114;46274:20;;46270:451;;46347:29;;;;:72;;46403:15;46347:72;:55;:72;:::i;:::-;46315:29;;;:104;46470:29;;;;:72;;46526:15;46470:72;:55;:72;:::i;:::-;46438:29;;;:104;46563:142;46606:6;46635:13;46671:15;46563:20;:142::i;:::-;45773:1046;;;46792:15;46753:36;;;:54;45773:1046;45526:1300;;;;:::o;39434:1202::-;39695:34;;;;39668:24;39783:21;;39779:357;;40052:17;;40000:28;;39925:199;;40093:30;;39925:145;;40052:17;39925:104;;;:12;39960:16;39925:52;:34;:52;:::i;:199::-;39904:220;;39779:357;40148:34;;;:49;;;40214:23;;40210:419;;40361:6;40334:8;-1:-1:-1;;;;;40259:160:0;40311:4;-1:-1:-1;;;;;40259:160:0;;40386:18;40259:160;;;;;;;;;;;;;;;40436:181;40468:4;40491:6;40516:8;40543:18;40580:22;40436:13;:181::i;:::-;39434:1202;;;;;;;:::o;13375:136::-;13433:7;13460:43;13464:1;13467;13460:43;;;;;;;;;;;;;;;;;:3;:43::i;14291:471::-;14349:7;14594:6;14590:47;;-1:-1:-1;14624:1:0;14617:8;;14590:47;14661:5;;;14665:1;14661;:5;:1;14685:5;;;;;:10;14677:56;;;;-1:-1:-1;;;14677:56:0;;;;;;;;15230:132;15288:7;15315:39;15319:1;15322;15315:39;;;;;;;;;;;;;;;;;:3;:39::i;43219:527::-;43331:10;;43327:412;;1565:42;43424:21;43464:15;;;43460:92;;;43500:36;;-1:-1:-1;;;43500:36:0;;-1:-1:-1;;;;;43500:19:0;;;;;:36;;43520:15;;;;43500:36;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;43500:36:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;43500:36:0;;;;43460:92;43566:28;43584:2;43588:5;43566:17;:28::i;:::-;43686:2;-1:-1:-1;;;;;43616:111:0;43656:10;-1:-1:-1;;;;;43616:111:0;;43707:5;43616:111;;;;;;;;;;;;;;;43327:412;;;43219:527;;:::o;44184:382::-;44315:10;;44311:248;;44342:86;-1:-1:-1;;;;;44342:26:0;;44387:2;44408:5;44342:86;:26;:86;:::i;:::-;44506:2;-1:-1:-1;;;;;44450:97:0;44482:5;-1:-1:-1;;;;;44450:97:0;;44527:5;44450:97;;;;;;;;;;;;;;;44184:382;;;:::o;6427:147::-;6549:10;;:17;;6427:147::o;12919:181::-;12977:7;13009:5;;;13033:6;;;;13025:46;;;;-1:-1:-1;;;13025:46:0;;;;;;;;18212:115;18275:7;18307:2;18302;:7;:17;;18317:2;18302:17;;;-1:-1:-1;18312:2:0;;18212:115;-1:-1:-1;18212:115:0:o;6906:159::-;7008:7;7040:3;:10;;7051:5;7040:17;;;;;;;;;;;;;;;;7033:24;;6906:159;;;;:::o;80709:3039::-;80857:30;;:::i;:::-;80905:21;;:::i;:::-;-1:-1:-1;80929:13:0;;;;:5;:13;;;;;;;;;80905:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;80905:37:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;80905:37:0;;;;;;;;;;;80953:33;;:::i;:::-;-1:-1:-1;81000:22:0;;;;;80989:34;;;;:10;:34;;;;;;;;80953:70;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;80953:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81041:8;:27;;;;;;;;;:63;;;;-1:-1:-1;81072:27:0;;;;:32;81041:63;81040:150;;;-1:-1:-1;81135:18:0;81123:8;:30;;;;;;;;;:66;;;;-1:-1:-1;81157:27:0;;;;:32;;81123:66;81036:198;;;-1:-1:-1;81207:15:0;;-1:-1:-1;81207:15:0;81036:198;81246:37;;:::i;:::-;-1:-1:-1;81286:20:0;;;;:12;:20;;;;;;;;81246:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81372:10;;81454:25;;;;81494:31;;;;;81540:19;;;;81574:20;;;;81360:245;;-1:-1:-1;;;81360:245:0;;81246:60;;81286:20;;;-1:-1:-1;;;;;81372:10:0;;;;81360:40;;:245;;81454:25;81540:19;81360:245;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;81360:245:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;81360:245: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;81360:245:0;;;;;;;;;81319:286;;;;81618:23;81652:19;81703:15;:33;;;81686:13;:50;81682:532;;81786:352;81827:9;:19;;;81865:9;:20;;;81904:13;81936:15;:33;;;81988:5;82036:27;:54;82064:15;:25;;;-1:-1:-1;;;;;82036:54:0;-1:-1:-1;;;;;82036:54:0;;;;;;;;;;;;:87;82091:15;:31;;;-1:-1:-1;;;;;82036:87:0;-1:-1:-1;;;;;82036:87:0;;;;;;;;;;;;;81786:22;:352::i;:::-;81753:385;;-1:-1:-1;81753:385:0;-1:-1:-1;81682:532:0;;;82160:10;82156:58;;;-1:-1:-1;82187:15:0;;-1:-1:-1;;;;;;82187:15:0;82156:58;82226:31;82268:37;82316:12;82352:6;82360:18;;;;;;;;;;;;;-1:-1:-1;;;82360:18:0;;;82341:38;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;82341:38:0;;;82331:49;;;;;;82316:64;;82448:4;82442:11;82415:38;;82516:1;82510:4;82506:12;82500:19;82467:52;;82571:15;82546:9;:22;;;:40;82542:266;;;82611:143;82747:6;82611:113;82695:17;:28;;;82611:61;82656:15;82611:9;:22;;;:44;;:61;;;;:::i;:143::-;82603:151;;82542:266;;;82795:1;82787:9;;82542:266;82827:913;;;;;;;;82865:6;82827:913;;;;82907:9;:22;;;-1:-1:-1;;;;;82827:913:0;;;;;82956:15;:25;;;-1:-1:-1;;;;;82827:913:0;;;;;83013:15;:31;;;-1:-1:-1;;;;;82827:913:0;;;;;83070:9;:19;;;82827:913;;;;83116:9;:20;;;82827:913;;;;83171:17;:28;;;82827:913;;;;83240:5;82827:913;;;;83271:9;:19;;;82827:913;;;;83318:9;:21;;;82827:913;;;;83373:15;:33;;;82827:913;;;;83436:13;82827:913;;;;83477:15;:27;;;82827:913;;;;83536:15;82827:913;;;;83579:11;82827:913;;;;83630:23;82827:913;;;;83699:29;82827:913;;;82820:920;;;;;;;;;;;;80709:3039;;;;;:::o;9832:98::-;9912:10;9832:98;:::o;85542:1430::-;85748:12;85784:6;85792:18;;;;;;;;;;;;;-1:-1:-1;;;85792:18:0;;;85773:38;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;85773:38:0;;;85763:49;;;;;;85748:64;;85864:4;85858:11;85890:13;85922:1;85917:88;;;;86061:23;86056:3;86053:32;86108:1;86103:96;;;;86261:1;86255:4;86248:15;86046:236;;86103:96;86155:23;86150:3;86146:33;86140:4;86133:47;86046:236;;85883:414;;85917:88;85965:23;85960:3;85956:33;85950:4;85943:47;85883:414;-1:-1:-1;;86331:1:0;86321:12;86354:11;;86386:13;86413:94;;;;86563:29;86558:3;86555:38;86616:1;86611:102;;;;86775:1;86769:4;86762:15;86548:248;;86611:102;86663:29;86658:3;86654:39;86648:4;86641:53;86548:248;;86379:432;;86413:94;86461:29;86456:3;86452:39;86446:4;86439:53;86379:432;;85832:990;86865:6;86839:125;86886:23;86924:29;86839:125;;;;;;;;;;;;;;;;85542:1430;;;;;:::o;33354:316::-;-1:-1:-1;;;;;;33455:17:0;;;;;;:12;:17;;;;;:26;;-1:-1:-1;;;;;;33455:26:0;-1:-1:-1;;;;;33455:26:0;;;;;;;;33498:20;33494:169;;33535:40;:15;-1:-1:-1;;;;;;33562:12:0;;33535:40;:26;:40;:::i;:::-;;33494:169;;;33608:43;:15;-1:-1:-1;;;;;;33638:12:0;;33608:43;:29;:43;:::i;83756:1778::-;83933:7;84025:29;84059:477;84083:9;:12;;;84110:15;:31;;;84156:15;:25;;;84196:9;:18;;;;;;;;;;-1:-1:-1;;;;;84196:18:0;84229:9;:20;;;84288:1;84359:13;84474:4;84059:477;;;;;;;;;;;;:9;:477::i;:::-;-1:-1:-1;84570:20:0;;;;84023:513;;-1:-1:-1;84570:61:0;;-1:-1:-1;84023:513:0;84570:61;:38;:61;:::i;:::-;84547:20;;;;:84;;;84757:10;;84800:25;;;;84840:31;;;;84886:19;;;;84745:206;;-1:-1:-1;;;84745:206:0;;84690:21;;;;-1:-1:-1;;;;;84757:10:0;;;;84745:40;;:206;;84800:25;;84840:31;;84886:19;;84547:84;84745:206;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;84745:206:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;84745:206: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;84745:206:0;;;;;;;;;84689:262;;;;85000:15;:33;;;84984:13;:49;84962:117;;;;-1:-1:-1;;;84962:117:0;;;;;;;;;85130:26;;;;;:55;;-1:-1:-1;85160:25:0;;;85130:55;85126:360;;;85238:12;;85202:272;;85269:110;1166:6;85269:69;:21;85317:20;85269:69;:47;:69;:::i;:110::-;85398:21;85438:4;85202:17;:272::i;:::-;-1:-1:-1;85505:21:0;;83756:1778;-1:-1:-1;;;;;83756:1778:0:o;43754:422::-;43886:10;;43882:287;;43913:124;-1:-1:-1;;;;;43913:30:0;;43962:4;43993;44017:5;43913:124;:30;:124;:::i;:::-;44114:4;-1:-1:-1;;;;;44059:98:0;44090:5;-1:-1:-1;;;;;44059:98:0;;44137:5;44059:98;;;;;;;42903:308;43012:21;1565:42;43012:33;;43056:10;-1:-1:-1;;;;;43056:18:0;;43081:5;43056:33;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;43056:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;43056:33:0;;;;;43168:4;-1:-1:-1;;;;;43107:96:0;43142:10;-1:-1:-1;;;;;43107:96:0;;43187:5;43107:96;;;;;;;46834:616;46990:18;47011:97;1229:6;47011:52;47045:17;;47011:15;:33;;:52;;;;:::i;:::-;:74;:97;:74;:97;:::i;:::-;46990:118;;47121:99;47150:6;47171:13;47199:10;47121:14;:99::i;:::-;47305:137;47333:13;47361:6;47382:49;:15;47420:10;47382:49;:37;:49;:::i;:::-;47305:13;:137::i;13848:192::-;13934:7;13970:12;13962:6;;;;13954:29;;;;-1:-1:-1;;;13954:29:0;;;;;;;;;;-1:-1:-1;;;14006:5:0;;;13848:192::o;11851:229::-;-1:-1:-1;;;;;11925:22:0;;11917:73;;;;-1:-1:-1;;;11917:73:0;;;;;;;;;12027:6;;12006:38;;-1:-1:-1;;;;;12006:38:0;;;;12027:6;;12006:38;;12027:6;;12006:38;12055:6;:17;;-1:-1:-1;;;;;;12055:17:0;-1:-1:-1;;;;;12055:17:0;;;;;;;;;;11851:229::o;40685:1890::-;41264:10;;;41358:282;;41211:20;;-1:-1:-1;;;;;41264:10:0;;;;41211:20;;41300:17;;41264:10;;-1:-1:-1;;;41399:45:0;41358:282;;41463:8;;1658:42;;41591:13;;;;41358:282;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;41358:282:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;41358:282:0;;;179:29:-1;;;;160:49;;;41321:330:0;;;;41358:282;41321:330;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;41285:366:0;;;;41701:1;41692:7;41689:14;41686:2;;;41755;41749:4;41745:13;41739:20;41723:36;;41686:2;41801:17;;41797:771;;41858:17;;41894:27;;;41890:95;;;41957:12;41942:27;;41890:95;42003:17;;41999:558;;42061:52;:12;42100;42061:52;:38;:52;:::i;:::-;42041:17;:72;;;;42134:12;42176:4;42182:13;;;;;;;;;;;;;-1:-1:-1;;;42182:13:0;;;42159:37;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;42159:37:0;;;42149:48;;;;;;42134:63;;42278:12;42271:4;42265:11;42261:30;42255:4;42248:44;42425:7;42336:205;;;;;;;;42396:6;42369:4;-1:-1:-1;;;;;42336:205:0;;1751:42;42510:12;42336:205;;;;;;;;;;;;;;;;41999:558;;41797:771;;40685:1890;;;;;;;;;:::o;15892:346::-;15978:7;16081:12;16073:6;16065:29;;;;-1:-1:-1;;;16065:29:0;;;;;;;;;;;16105:9;16121:1;16117;:5;;;;;;;15892:346;-1:-1:-1;;;;;15892:346:0:o;20956:363::-;21063:6;21038:21;:31;;21030:73;;;;-1:-1:-1;;;21030:73:0;;;;;;;;;21172:12;21190:9;-1:-1:-1;;;;;21190:14:0;21211:6;21190:32;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;21171:51:0;;;21241:7;21233:78;;;;-1:-1:-1;;;21233:78:0;;;;;;;;21884:176;21993:58;;21967:85;;21986:5;;-1:-1:-1;;;22016:23:0;21993:58;;22041:2;;22045:5;;21993:58;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;21993:58:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;21993:58:0;;;179:29:-1;;;;160:49;;;21967:18:0;:85::i;47502:1970::-;47784:23;47809:19;47866:17;47850:13;:33;:62;;;-1:-1:-1;47887:25:0;;47850:62;47846:234;;;47929:37;;47846:234;48005:16;47988:13;:33;47984:96;;-1:-1:-1;48046:9:0;;-1:-1:-1;48057:10:0;48038:30;;47984:96;48092:21;48116:44;:17;48152:7;48116:44;:35;:44;:::i;:::-;48092:68;-1:-1:-1;48365:124:0;1229:6;48365:83;48438:9;48365:54;48092:68;1229:6;48365:54;:31;:54;:::i;:124::-;48347:142;-1:-1:-1;48518:166:0;48570:99;1166:6;48570:58;:10;48607:20;48570:58;:36;:58;:::i;:99::-;48518:15;;:166;:33;:166;:::i;:::-;48500:184;-1:-1:-1;48713:165:0;48806:57;:13;48846:16;48806:57;:39;:57;:::i;:::-;48713:56;:15;1229:6;48713:56;:33;:56;:::i;:165::-;48695:183;;48911:9;48893:15;:27;48889:87;;;48955:9;48937:27;;48889:87;49092:132;49144:65;:16;1229:6;49144:65;:42;:65;:::i;:::-;49092:15;;:132;:33;:132;:::i;:::-;49078:146;-1:-1:-1;49249:74:0;49319:3;49249:51;49078:146;49279:20;49249:51;:29;:51;:::i;:74::-;49235:88;;49352:10;49338:11;:24;49334:81;;;49393:10;49379:24;;49334:81;-1:-1:-1;47502:1970:0;;;;;;;;;;:::o;2927:289::-;3022:4;3049:20;3058:3;3063:5;3049:8;:20::i;:::-;3044:165;;-1:-1:-1;3104:10:0;;;;27::-1;;23:18;;;45:23;;;-1:-1;3104:22:0;;;;;;;;;;;;;3085:16;;;;;;;;;;;:41;3141:11;;3044:165;-1:-1:-1;3192:5:0;3185:12;;3748:1054;3846:4;3872:20;3881:3;3886:5;3872:8;:20::i;:::-;3868:927;;;3908:21;3932:16;;;;;;;;;;;3951:1;3987:10;;:17;-1:-1:-1;;3932:20:0;;;;3987:21;4135:26;;;4131:389;;4182:17;4202:3;:10;;4213:9;4202:21;;;;;;;;;;;;;;;;4182:41;;4352:9;4324:3;:10;;4335:13;4324:25;;;;;;;;;;;;;;;;;;;:37;;;;4437:20;;;;;;;;;4476:1;4460:17;;4437:40;;4131:389;4604:9;:16;;;;;;;;;;4597:23;4694:10;;;:16;;;;;;;;;;;;;;;;;;;;;;;;4734:4;4727:11;;;;;;50613:1566;51118:449;;;;;;;;-1:-1:-1;;;;;51118:449:0;;;;;;;;;;;;;;;;51228:4;51118:449;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50957:31;;;;;;51118:449;;;51498:6;51519:9;51543:13;51118:10;:449::i;:::-;51067:500;;-1:-1:-1;51067:500:0;-1:-1:-1;51627:50:0;51642:11;51067:500;51627:14;:50::i;:::-;51771:10;;51944:15;;51759:211;;-1:-1:-1;;;51759:211:0;;-1:-1:-1;;;;;51771:10:0;;;;51759:46;;:211;;51820:11;;51846:9;;51870:21;;51906:23;;51759:211;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;51759:211:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;51759:211: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;51759:211:0;;;;;;;;;51736:234;;52058:9;-1:-1:-1;;;;;51988:183:0;52032:11;-1:-1:-1;;;;;51988:183:0;52011:6;51988:183;52082:4;52101:21;52137:23;51988:183;;;;;;;;;;;;;;;;;50613:1566;;;;;;;;;;;;;:::o;22068:204::-;22195:68;;22169:95;;22188:5;;-1:-1:-1;;;22218:27:0;22195:68;;22247:4;;22253:2;;22257:5;;22195:68;;;;16348:140;16410:7;16437:43;16445:1;16448;16437:43;;;;;;;;;;;;;;;;;:7;:43::i;38849:487::-;38991:15;;38987:342;;-1:-1:-1;;;;;39056:30:0;;;;;;:20;:30;;;;;;:64;;39109:10;39056:64;:52;:64;:::i;:::-;-1:-1:-1;;;;;39023:30:0;;;;;;;:20;:30;;;;;;;:97;;;;39142:107;;;;;;;;;;39224:10;;39142:107;;23923:1114;24527:27;24535:5;-1:-1:-1;;;;;24527:25:0;;:27::i;:::-;24519:71;;;;-1:-1:-1;;;24519:71:0;;;;;;;;;24664:12;24678:23;24713:5;-1:-1:-1;;;;;24705:19:0;24725:4;24705:25;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;24663:67:0;;;;24749:7;24741:52;;;;-1:-1:-1;;;24741:52:0;;;;;;;;;24810:17;;:21;24806:224;;24952:10;24941:30;;;;;;;;;;;;;;24933:85;;;;-1:-1:-1;;;24933:85:0;;;;;;;;4888:165;4995:4;5024:16;;;;;;;;;;;;:21;;;4888:165::o;52187:3129::-;52739:7;;52410;;;;52731:42;;;;-1:-1:-1;;;52731:42:0;;;;;;;;;52786:31;52828:29;52870:18;52904:8;52899:873;;52946:7;;;;52942:819;;53069:23;53084:4;53089:1;53084:7;;;;;53069:14;:23::i;:::-;53056:36;-1:-1:-1;53115:15:0;;53111:348;;53196:8;;;;53155:200;;53239:6;53196:5;53278:1;53272:8;;;;;53322:10;53155:14;:200::i;:::-;53390:7;;:49;;53428:10;53390:37;:49::i;:::-;53380:59;;53111:348;52942:819;;;53579:23;53594:4;53599:1;53594:7;;53579:23;53566:36;-1:-1:-1;53627:15:0;;53623:123;;53677:7;;;;:49;;53715:10;53677:37;:49::i;:::-;53667:7;;;:59;53623:123;53788:7;;;;53784:146;;53827:7;;;53817;;:17;53784:146;;;53886:7;;;;53875;;:18;;53867:51;;;;-1:-1:-1;;;53867:51:0;;;;;;;;;53950:20;;:25;53942:51;;;;-1:-1:-1;;;53942:51:0;;;;;;;;;54055:69;54089:5;54109:4;54055:19;:69::i;:::-;54141:7;;;;54004:120;;-1:-1:-1;54004:120:0;-1:-1:-1;54137:1104:0;;54350:7;;54325:32;;54317:67;;;;-1:-1:-1;;;54317:67:0;;;;;;;;;54405:15;;54401:137;;54465:34;;;;54401:137;54137:1104;;;54742:7;;;;54717:32;;;54709:64;;;;-1:-1:-1;;;54709:64:0;;;;;;;;;54823:7;;;;54796:34;;;54788:74;;;;-1:-1:-1;;;54788:74:0;;;;;;;;;54883:15;;54879:351;;54956:8;;;;54919:189;;54995:6;54956:5;55041:1;55035:8;;54919:189;55181:10;55155:23;:36;55129:62;;54879:351;-1:-1:-1;55261:23:0;;;;-1:-1:-1;52187:3129:0;-1:-1:-1;;;;;;52187:3129:0:o;57017:540::-;57169:11;;57195:17;;57191:359;;57229:19;-1:-1:-1;;;;;57267:34:0;;1565:42;57267:34;57263:207;;;-1:-1:-1;57336:6:0;57263:207;;;57409:10;;57397:57;;-1:-1:-1;;;57397:57:0;;-1:-1:-1;;;;;57409:10:0;;;;57397:35;;:57;;57433:12;;57447:6;;57397:57;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57397:57:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;57397:57: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;57397:57:0;;;;;;;;;57383:71;;57263:207;57507:12;57492:11;:27;;57484:54;;;;-1:-1:-1;;;57484:54:0;;;;;;;;16598:334;16688:7;16791:12;16783:6;16775:29;;;;-1:-1:-1;;;16775:29:0;;;;;;;;;;-1:-1:-1;16821:6:0;16817:47;;-1:-1:-1;16851:1:0;16844:8;;16817:47;16874:9;16897:1;16892;16888;:5;16887:11;;;;;;16902:1;16886:17;;16598:334;-1:-1:-1;;;;;16598:334:0:o;19016:619::-;19076:4;19544:20;;19387:66;19584:23;;;;;;:42;;-1:-1:-1;19611:15:0;;;19584:42;19576:51;19016:619;-1:-1:-1;;;;19016:619:0:o;36862:244::-;36970:7;37002:96;1229:6;37002:51;37035:17;;37002:14;:32;;:51;;;;:::i;37436:652::-;37603:15;;37599:482;;-1:-1:-1;;;;;37668:30:0;;;;;;:20;:30;;;;;;:64;;37721:10;37668:64;:52;:64;:::i;:::-;-1:-1:-1;;;;;37635:30:0;;;;;;;:20;:30;;;;;;;:97;;;;37754:132;;37836:6;;37635:30;37754:132;;;;;;;37861:10;;37754:132;;;;;;;;;;37903:166;37935:4;37958:6;37983:8;38010:10;38039:15;37903:13;:166::i;55324:860::-;55647:8;;;55685;;;;55721;;;;;55537:17;55763:8;;;;55811:7;;55858;;;;55905;;;;55557:395;;55457:31;;;;55537:17;;-1:-1:-1;;;55594:38:0;55557:395;;55647:8;;55685;;55721;;55763;;55811:7;;55858;55557:395;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;55557:395:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;55557:395:0;;;179:29:-1;;;;160:49;;;56006:9:0;;:28;;55557:395;;-1:-1:-1;;;;;;;;56006:9:0;;:28;;55557:395;;56006:28;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;55988:46:0;-1:-1:-1;55988:46:0;-1:-1:-1;55988:46:0;56045:31;;;;-1:-1:-1;;;56045:31:0;;;;;;;;;56151:4;56140:36;;;;;;;;;;;;;;56089:87;;;;-1:-1:-1;55324:860:0;-1:-1:-1;;;;;55324:860:0:o;59902:27073::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;59902:27073:0;;;;;;-1:-1:-1;;;;;59902:27073:0;;;;;;-1:-1:-1;;;;;59902:27073:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;59902:27073:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;59902:27073:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;5:130:-1:-;72:20;;97:33;72:20;97:33;;142:124;206:20;;231:30;206:20;231:30;;273:128;348:13;;366:30;348:13;366:30;;408:130;475:20;;500:33;475:20;500:33;;545:128;611:20;;636:32;611:20;636:32;;694:336;;;808:3;801:4;793:6;789:17;785:27;775:2;;826:1;823;816:12;775:2;-1:-1;846:20;;886:18;875:30;;872:2;;;918:1;915;908:12;872:2;952:4;944:6;940:17;928:29;;1003:3;995:4;987:6;983:17;973:8;969:32;966:41;963:2;;;1020:1;1017;1010:12;963:2;768:262;;;;;;1038:156;1118:20;;1143:46;1118:20;1143:46;;1338:134;1416:13;;1434:33;1416:13;1434:33;;1479:241;;1583:2;1571:9;1562:7;1558:23;1554:32;1551:2;;;1599:1;1596;1589:12;1551:2;1634:1;1651:53;1696:7;1676:9;1651:53;;1727:366;;;1848:2;1836:9;1827:7;1823:23;1819:32;1816:2;;;1864:1;1861;1854:12;1816:2;1899:1;1916:53;1961:7;1941:9;1916:53;;;1906:63;;1878:97;2006:2;2024:53;2069:7;2060:6;2049:9;2045:22;2024:53;;;2014:63;;1985:98;1810:283;;;;;;2100:360;;;2218:2;2206:9;2197:7;2193:23;2189:32;2186:2;;;2234:1;2231;2224:12;2186:2;2269:1;2286:53;2331:7;2311:9;2286:53;;;2276:63;;2248:97;2376:2;2394:50;2436:7;2427:6;2416:9;2412:22;2394:50;;2467:366;;;2588:2;2576:9;2567:7;2563:23;2559:32;2556:2;;;2604:1;2601;2594:12;2556:2;2639:1;2656:53;2701:7;2681:9;2656:53;;;2646:63;;2618:97;2746:2;2764:53;2809:7;2800:6;2789:9;2785:22;2764:53;;2840:883;;;;;;;3036:3;3024:9;3015:7;3011:23;3007:33;3004:2;;;3053:1;3050;3043:12;3004:2;3088:1;3105:53;3150:7;3130:9;3105:53;;;3095:63;;3067:97;3195:2;3213:53;3258:7;3249:6;3238:9;3234:22;3213:53;;;3203:63;;3174:98;3303:2;3321:53;3366:7;3357:6;3346:9;3342:22;3321:53;;;3311:63;;3282:98;3411:2;3429:66;3487:7;3478:6;3467:9;3463:22;3429:66;;;3419:76;;3390:111;3532:3;3551:50;3593:7;3584:6;3573:9;3569:22;3551:50;;;3541:60;;3511:96;3638:3;3657:50;3699:7;3690:6;3679:9;3675:22;3657:50;;;3647:60;;3617:96;2998:725;;;;;;;;;3730:257;;3842:2;3830:9;3821:7;3817:23;3813:32;3810:2;;;3858:1;3855;3848:12;3810:2;3893:1;3910:61;3963:7;3943:9;3910:61;;3994:241;;4098:2;4086:9;4077:7;4073:23;4069:32;4066:2;;;4114:1;4111;4104:12;4066:2;4149:1;4166:53;4211:7;4191:9;4166:53;;4242:366;;;4363:2;4351:9;4342:7;4338:23;4334:32;4331:2;;;4379:1;4376;4369:12;4331:2;4414:1;4431:53;4476:7;4456:9;4431:53;;4615:491;;;;4753:2;4741:9;4732:7;4728:23;4724:32;4721:2;;;4769:1;4766;4759:12;4721:2;4804:1;4821:53;4866:7;4846:9;4821:53;;;4811:63;;4783:97;4911:2;4929:53;4974:7;4965:6;4954:9;4950:22;4929:53;;;4919:63;;4890:98;5019:2;5037:53;5082:7;5073:6;5062:9;5058:22;5037:53;;;5027:63;;4998:98;4715:391;;;;;;5113:366;;;5234:2;5222:9;5213:7;5209:23;5205:32;5202:2;;;5250:1;5247;5240:12;5202:2;5285:1;5302:53;5347:7;5327:9;5302:53;;5486:735;;;;;;5657:3;5645:9;5636:7;5632:23;5628:33;5625:2;;;5674:1;5671;5664:12;5625:2;5709:1;5726:53;5771:7;5751:9;5726:53;;;5716:63;;5688:97;5816:2;5834:53;5879:7;5870:6;5859:9;5855:22;5834:53;;;5824:63;;5795:98;5924:2;5942:50;5984:7;5975:6;5964:9;5960:22;5942:50;;;5932:60;;5903:95;6057:2;6046:9;6042:18;6029:32;6081:18;6073:6;6070:30;6067:2;;;6113:1;6110;6103:12;6067:2;6141:64;6197:7;6188:6;6177:9;6173:22;6141:64;;;6131:74;;;;6008:203;5619:602;;;;;;;;;6228:491;;;;6366:2;6354:9;6345:7;6341:23;6337:32;6334:2;;;6382:1;6379;6372:12;6334:2;6417:1;6434:53;6479:7;6459:9;6434:53;;;6424:63;;6396:97;6524:2;6542:53;6587:7;6578:6;6567:9;6563:22;6542:53;;6726:239;;6829:2;6817:9;6808:7;6804:23;6800:32;6797:2;;;6845:1;6842;6835:12;6797:2;6880:1;6897:52;6941:7;6921:9;6897:52;;6972:263;;7087:2;7075:9;7066:7;7062:23;7058:32;7055:2;;;7103:1;7100;7093:12;7055:2;7138:1;7155:64;7211:7;7191:9;7155:64;;7242:399;;;7374:2;7362:9;7353:7;7349:23;7345:32;7342:2;;;7390:1;7387;7380:12;7342:2;7425:1;7442:64;7498:7;7478:9;7442:64;;;7432:74;;7404:108;7543:2;7561:64;7617:7;7608:6;7597:9;7593:22;7561:64;;7648:485;;;;7783:2;7771:9;7762:7;7758:23;7754:32;7751:2;;;7799:1;7796;7789:12;7751:2;7834:1;7851:53;7896:7;7876:9;7851:53;;;7841:63;;7813:97;7941:2;7959:53;8004:7;7995:6;7984:9;7980:22;7959:53;;;7949:63;;7920:98;8049:2;8067:50;8109:7;8100:6;8089:9;8085:22;8067:50;;8141:291;;8284:106;8386:3;8378:6;8284:106;;;-1:-1;;8419:6;8410:16;;8277:155;8440:184;8557:61;8585:32;8611:5;8585:32;;;8557:61;;;8552:3;8545:74;8539:85;;;8631:103;8704:24;8722:5;8704:24;;9123:914;;9324:82;9400:5;9324:82;;;9419:114;9526:6;9521:3;9419:114;;;9412:121;;9554:84;9632:5;9554:84;;;9658:7;9686:1;9671:344;9696:6;9693:1;9690:13;9671:344;;;9763:6;9757:13;9784:119;9899:3;9884:13;9784:119;;;9777:126;;9920:88;10001:6;9920:88;;;9910:98;-1:-1;;9718:1;9711:9;9671:344;;;-1:-1;10028:3;;9303:734;-1:-1;;;;;9303:734;10045:104;10122:21;10137:5;10122:21;;10156:103;10229:24;10247:5;10229:24;;10386:356;;10514:38;10546:5;10514:38;;;10564:88;10645:6;10640:3;10564:88;;;10557:95;;10657:52;10702:6;10697:3;10690:4;10683:5;10679:16;10657:52;;;10721:16;;;;;10494:248;-1:-1;;10494:248;10749:160;10849:54;10897:5;10849:54;;10916:347;;11028:39;11061:5;11028:39;;;11079:71;11143:6;11138:3;11079:71;;;11072:78;;11155:52;11200:6;11195:3;11188:4;11181:5;11177:16;11155:52;;;11228:29;11250:6;11228:29;;;11219:39;;;;11008:255;-1:-1;;;11008:255;11976:319;;12136:67;12200:2;12195:3;12136:67;;;-1:-1;;;12216:42;;12286:2;12277:12;;12122:173;-1:-1;;12122:173;12304:327;;12464:67;12528:2;12523:3;12464:67;;;12564:29;12544:50;;12622:2;12613:12;;12450:181;-1:-1;;12450:181;12640:375;;12800:67;12864:2;12859:3;12800:67;;;12900:34;12880:55;;-1:-1;;;12964:2;12955:12;;12948:30;13006:2;12997:12;;12786:229;-1:-1;;12786:229;13024:320;;13184:67;13248:2;13243:3;13184:67;;;-1:-1;;;13264:43;;13335:2;13326:12;;13170:174;-1:-1;;13170:174;13353:371;;13513:67;13577:2;13572:3;13513:67;;;13613:34;13593:55;;-1:-1;;;13677:2;13668:12;;13661:26;13715:2;13706:12;;13499:225;-1:-1;;13499:225;13733:327;;13893:67;13957:2;13952:3;13893:67;;;13993:29;13973:50;;14051:2;14042:12;;13879:181;-1:-1;;13879:181;14069:316;;14229:67;14293:2;14288:3;14229:67;;;-1:-1;;;14309:39;;14376:2;14367:12;;14215:170;-1:-1;;14215:170;14394:314;;14554:67;14618:2;14613:3;14554:67;;;-1:-1;;;14634:37;;14699:2;14690:12;;14540:168;-1:-1;;14540:168;14717:332;;14877:67;14941:2;14936:3;14877:67;;;14977:34;14957:55;;15040:2;15031:12;;14863:186;-1:-1;;14863:186;15058:319;;15218:67;15282:2;15277:3;15218:67;;;-1:-1;;;15298:42;;15368:2;15359:12;;15204:173;-1:-1;;15204:173;15386:317;;15546:67;15610:2;15605:3;15546:67;;;-1:-1;;;15626:40;;15694:2;15685:12;;15532:171;-1:-1;;15532:171;15712:395;;15872:67;15936:2;15931:3;15872:67;;;15972:34;15952:55;;16041:28;16036:2;16027:12;;16020:50;16098:2;16089:12;;15858:249;-1:-1;;15858:249;16116:329;;16276:67;16340:2;16335:3;16276:67;;;16376:31;16356:52;;16436:2;16427:12;;16262:183;-1:-1;;16262:183;16454:324;;16614:67;16678:2;16673:3;16614:67;;;16714:26;16694:47;;16769:2;16760:12;;16600:178;-1:-1;;16600:178;16787:314;;16947:67;17011:2;17006:3;16947:67;;;-1:-1;;;17027:37;;17092:2;17083:12;;16933:168;-1:-1;;16933:168;17110:314;;17270:67;17334:2;17329:3;17270:67;;;-1:-1;;;17350:37;;17415:2;17406:12;;17256:168;-1:-1;;17256:168;17433:370;;17593:67;17657:2;17652:3;17593:67;;;17693:34;17673:55;;-1:-1;;;17757:2;17748:12;;17741:25;17794:2;17785:12;;17579:224;-1:-1;;17579:224;17812:312;;17972:67;18036:2;18031:3;17972:67;;;-1:-1;;;18052:35;;18115:2;18106:12;;17958:166;-1:-1;;17958:166;18133:318;;18293:67;18357:2;18352:3;18293:67;;;-1:-1;;;18373:41;;18442:2;18433:12;;18279:172;-1:-1;;18279:172;18460:318;;18620:67;18684:2;18679:3;18620:67;;;-1:-1;;;18700:41;;18769:2;18760:12;;18606:172;-1:-1;;18606:172;18787:296;;18964:83;19045:1;19040:3;18964:83;;19092:314;;19252:67;19316:2;19311:3;19252:67;;;-1:-1;;;19332:37;;19397:2;19388:12;;19238:168;-1:-1;;19238:168;19415:312;;19575:67;19639:2;19634:3;19575:67;;;-1:-1;;;19655:35;;19718:2;19709:12;;19561:166;-1:-1;;19561:166;19736:313;;19896:67;19960:2;19955:3;19896:67;;;-1:-1;;;19976:36;;20040:2;20031:12;;19882:167;-1:-1;;19882:167;20058:379;;20218:67;20282:2;20277:3;20218:67;;;20318:34;20298:55;;-1:-1;;;20382:2;20373:12;;20366:34;20428:2;20419:12;;20204:233;-1:-1;;20204:233;20446:319;;20606:67;20670:2;20665:3;20606:67;;;-1:-1;;;20686:42;;20756:2;20747:12;;20592:173;-1:-1;;20592:173;20774:311;;20934:67;20998:2;20993:3;20934:67;;;-1:-1;;;21014:34;;21076:2;21067:12;;20920:165;-1:-1;;20920:165;21094:322;;21254:67;21318:2;21313:3;21254:67;;;-1:-1;;;21334:45;;21407:2;21398:12;;21240:176;-1:-1;;21240:176;21425:322;;21585:67;21649:2;21644:3;21585:67;;;-1:-1;;;21665:45;;21738:2;21729:12;;21571:176;-1:-1;;21571:176;21756:331;;21916:67;21980:2;21975:3;21916:67;;;22016:33;21996:54;;22078:2;22069:12;;21902:185;-1:-1;;21902:185;22096:320;;22256:67;22320:2;22315:3;22256:67;;;-1:-1;;;22336:43;;22407:2;22398:12;;22242:174;-1:-1;;22242:174;22521:3010;22748:23;;22678:6;22669:16;;;22777:63;22673:3;22748:23;22777:63;;;22700:146;22927:4;22920:5;22916:16;22910:23;22939:61;22994:4;22989:3;22985:14;22971:12;22939:61;;;22856:150;23084:4;23077:5;23073:16;23067:23;23096:63;23153:4;23148:3;23144:14;23130:12;23096:63;;;23016:149;23249:4;23242:5;23238:16;23232:23;23261:63;23318:4;23313:3;23309:14;23295:12;23261:63;;;23175:155;23408:4;23401:5;23397:16;23391:23;23420:63;23477:4;23472:3;23468:14;23454:12;23420:63;;;23340:149;23568:4;23561:5;23557:16;23551:23;23580:63;23637:4;23632:3;23628:14;23614:12;23580:63;;;23499:150;23736:4;23729:5;23725:16;23719:23;23748:63;23805:4;23800:3;23796:14;23782:12;23748:63;;;23659:158;23910:4;23903:5;23899:16;23893:23;23922:63;23979:4;23974:3;23970:14;23956:12;23922:63;;;23827:164;24069:6;24062:5;24058:18;24052:25;24083:65;24140:6;24135:3;24131:16;24117:12;24083:65;;;24001:153;24234:6;24227:5;24223:18;24217:25;24248:65;24305:6;24300:3;24296:16;24282:12;24248:65;;;24164:155;24405:6;24398:5;24394:18;24388:25;24419:65;24476:6;24471:3;24467:16;24453:12;24419:65;;;24329:161;24572:6;24565:5;24561:18;24555:25;24586:65;24643:6;24638:3;24634:16;24620:12;24586:65;;;24500:157;24737:6;24730:5;24726:18;24720:25;24751:65;24808:6;24803:3;24799:16;24785:12;24751:65;;;24667:155;24906:6;24899:5;24895:18;24889:25;24920:65;24977:6;24972:3;24968:16;24954:12;24920:65;;;24832:159;25071:6;25064:5;25060:18;25054:25;25085:65;25142:6;25137:3;25133:16;25119:12;25085:65;;;25001:155;25248:6;25241:5;25237:18;25231:25;25262:65;25319:6;25314:3;25310:16;25296:12;25262:65;;;25166:167;25431:6;25424:5;25420:18;25414:25;25445:65;25502:6;25497:3;25493:16;25479:12;25445:65;;28868:100;28939:23;28956:5;28939:23;;28975:429;;29154:91;29241:3;29232:6;29154:91;;;29267:2;29262:3;29258:12;29251:19;;29288:91;29375:3;29366:6;29288:91;;29815:262;;29959:93;30048:3;30039:6;29959:93;;30084:370;;30282:147;30425:3;30282:147;;30461:213;30579:2;30564:18;;30593:71;30568:9;30637:6;30593:71;;30681:324;30827:2;30812:18;;30841:71;30816:9;30885:6;30841:71;;;30923:72;30991:2;30980:9;30976:18;30967:6;30923:72;;31012:883;31298:3;31283:19;;31313:71;31287:9;31357:6;31313:71;;;31395:72;31463:2;31452:9;31448:18;31439:6;31395:72;;;31478;31546:2;31535:9;31531:18;31522:6;31478:72;;;31561;31629:2;31618:9;31614:18;31605:6;31561:72;;;31644:73;31712:3;31701:9;31697:19;31688:6;31644:73;;;31728;31796:3;31785:9;31781:19;31772:6;31728:73;;;31812;31880:3;31869:9;31865:19;31856:6;31812:73;;;31269:626;;;;;;;;;;;31902:435;32076:2;32061:18;;32090:71;32065:9;32134:6;32090:71;;;32172:72;32240:2;32229:9;32225:18;32216:6;32172:72;;;32255;32323:2;32312:9;32308:18;32299:6;32255:72;;32344:547;32546:3;32531:19;;32561:71;32535:9;32605:6;32561:71;;;32643:72;32711:2;32700:9;32696:18;32687:6;32643:72;;;32726;32794:2;32783:9;32779:18;32770:6;32726:72;;;32809;32877:2;32866:9;32862:18;32853:6;32809:72;;;32517:374;;;;;;;;32898:659;33128:3;33113:19;;33143:71;33117:9;33187:6;33143:71;;;33225:72;33293:2;33282:9;33278:18;33269:6;33225:72;;;33308;33376:2;33365:9;33361:18;33352:6;33308:72;;;33391;33459:2;33448:9;33444:18;33435:6;33391:72;;;33474:73;33542:3;33531:9;33527:19;33518:6;33474:73;;33564:324;33710:2;33695:18;;33724:71;33699:9;33768:6;33724:71;;;33806:72;33874:2;33863:9;33859:18;33850:6;33806:72;;33895:435;34069:2;34054:18;;34083:71;34058:9;34127:6;34083:71;;;34165:72;34233:2;34222:9;34218:18;34209:6;34165:72;;34337:547;34539:3;34524:19;;34554:71;34528:9;34598:6;34554:71;;;34636:72;34704:2;34693:9;34689:18;34680:6;34636:72;;34891:473;35115:2;35129:47;;;35100:18;;35190:164;35100:18;35340:6;35190:164;;35371:201;35483:2;35468:18;;35497:65;35472:9;35535:6;35497:65;;35579:983;35887:3;35872:19;;35902:71;35876:9;35946:6;35902:71;;;35984:66;36046:2;36035:9;36031:18;36022:6;35984:66;;;36061:72;36129:2;36118:9;36114:18;36105:6;36061:72;;;36144;36212:2;36201:9;36197:18;36188:6;36144:72;;;36227:73;36295:3;36284:9;36280:19;36271:6;36227:73;;;36311;36379:3;36368:9;36364:19;36355:6;36311:73;;;36395;36463:3;36452:9;36448:19;36439:6;36395:73;;;36479;36547:3;36536:9;36532:19;36523:6;36479:73;;;35858:704;;;;;;;;;;;;36569:1435;36991:3;36976:19;;37006:71;36980:9;37050:6;37006:71;;;37088:72;37156:2;37145:9;37141:18;37132:6;37088:72;;;37171;37239:2;37228:9;37224:18;37215:6;37171:72;;;37254;37322:2;37311:9;37307:18;37298:6;37254:72;;;37337:73;37405:3;37394:9;37390:19;37381:6;37337:73;;;37421;37489:3;37478:9;37474:19;37465:6;37421:73;;;37505;37573:3;37562:9;37558:19;37549:6;37505:73;;;37589;37657:3;37646:9;37642:19;37633:6;37589:73;;;37673;37741:3;37730:9;37726:19;37717:6;37673:73;;;37757;37825:3;37814:9;37810:19;37801:6;37757:73;;;37841:74;37910:3;37899:9;37895:19;37885:7;37841:74;;;37926:68;37989:3;37978:9;37974:19;37964:7;37926:68;;;36962:1042;;;;;;;;;;;;;;;;38011:404;38173:2;38158:18;;38187:71;38162:9;38231:6;38187:71;;;38306:9;38300:4;38296:20;38291:2;38280:9;38276:18;38269:48;38331:74;38400:4;38391:6;38331:74;;38422:247;38557:2;38542:18;;38571:88;38546:9;38632:6;38571:88;;38676:301;38814:2;38828:47;;;38799:18;;38889:78;38799:18;38953:6;38889:78;;38984:407;39175:2;39189:47;;;39160:18;;39250:131;39160:18;39250:131;;39398:407;39589:2;39603:47;;;39574:18;;39664:131;39574:18;39664:131;;39812:407;40003:2;40017:47;;;39988:18;;40078:131;39988:18;40078:131;;40226:407;40417:2;40431:47;;;40402:18;;40492:131;40402:18;40492:131;;40640:407;40831:2;40845:47;;;40816:18;;40906:131;40816:18;40906:131;;41054:407;41245:2;41259:47;;;41230:18;;41320:131;41230:18;41320:131;;41468:407;41659:2;41673:47;;;41644:18;;41734:131;41644:18;41734:131;;41882:407;42073:2;42087:47;;;42058:18;;42148:131;42058:18;42148:131;;42296:407;42487:2;42501:47;;;42472:18;;42562:131;42472:18;42562:131;;42710:407;42901:2;42915:47;;;42886:18;;42976:131;42886:18;42976:131;;43124:407;43315:2;43329:47;;;43300:18;;43390:131;43300:18;43390:131;;43538:407;43729:2;43743:47;;;43714:18;;43804:131;43714:18;43804:131;;43952:407;44143:2;44157:47;;;44128:18;;44218:131;44128:18;44218:131;;44366:407;44557:2;44571:47;;;44542:18;;44632:131;44542:18;44632:131;;44780:407;44971:2;44985:47;;;44956:18;;45046:131;44956:18;45046:131;;45194:407;45385:2;45399:47;;;45370:18;;45460:131;45370:18;45460:131;;45608:407;45799:2;45813:47;;;45784:18;;45874:131;45784:18;45874:131;;46022:407;46213:2;46227:47;;;46198:18;;46288:131;46198:18;46288:131;;46436:407;46627:2;46641:47;;;46612:18;;46702:131;46612:18;46702:131;;46850:407;47041:2;47055:47;;;47026:18;;47116:131;47026:18;47116:131;;47264:407;47455:2;47469:47;;;47440:18;;47530:131;47440:18;47530:131;;47678:407;47869:2;47883:47;;;47854:18;;47944:131;47854:18;47944:131;;48092:407;48283:2;48297:47;;;48268:18;;48358:131;48268:18;48358:131;;48506:407;48697:2;48711:47;;;48682:18;;48772:131;48682:18;48772:131;;48920:407;49111:2;49125:47;;;49096:18;;49186:131;49096:18;49186:131;;49334:407;49525:2;49539:47;;;49510:18;;49600:131;49510:18;49600:131;;49748:407;49939:2;49953:47;;;49924:18;;50014:131;49924:18;50014:131;;50162:407;50353:2;50367:47;;;50338:18;;50428:131;50338:18;50428:131;;50576:407;50767:2;50781:47;;;50752:18;;50842:131;50752:18;50842:131;;50990:407;51181:2;51195:47;;;51166:18;;51256:131;51166:18;51256:131;;51404:342;51586:3;51571:19;;51601:135;51575:9;51709:6;51601:135;;51753:213;51871:2;51856:18;;51885:71;51860:9;51929:6;51885:71;;51973:324;52119:2;52104:18;;52133:71;52108:9;52177:6;52133:71;;52304:435;52478:2;52463:18;;52492:71;52467:9;52536:6;52492:71;;52746:659;52976:3;52961:19;;52991:71;52965:9;53035:6;52991:71;;;53073:72;53141:2;53130:9;53126:18;53117:6;53073:72;;53412:771;53670:3;53655:19;;53685:71;53659:9;53729:6;53685:71;;;53767:72;53835:2;53824:9;53820:18;53811:6;53767:72;;;53850;53918:2;53907:9;53903:18;53894:6;53850:72;;;53933;54001:2;53990:9;53986:18;53977:6;53933:72;;;54016:73;54084:3;54073:9;54069:19;54060:6;54016:73;;;54100;54168:3;54157:9;54153:19;54144:6;54100:73;;;53641:542;;;;;;;;;;54190:179;54342:4;54333:14;;54290:79;54376:165;54507:12;;54478:63;55074:206;55220:19;;;55269:4;55260:14;;55213:67;55289:144;55424:3;55402:31;-1:-1;55402:31;55767:91;;55829:24;55847:5;55829:24;;55971:85;56037:13;56030:21;;56013:43;56063:72;56125:5;56108:27;56142:144;-1:-1;;;;;;56203:78;;56186:100;56293:121;-1:-1;;;;;56355:54;;56338:76;56500:104;-1:-1;;;;;56561:38;;56544:60;56611:155;;56707:54;56755:5;56707:54;;56906:268;56971:1;56978:101;56992:6;56989:1;56986:13;56978:101;;;57059:11;;;57053:18;57040:11;;;57033:39;57014:2;57007:10;56978:101;;;57094:6;57091:1;57088:13;57085:2;;;-1:-1;;57159:1;57141:16;;57134:27;56955:219;57182:95;;57246:26;57266:5;57394:89;57458:20;57472:5;57458:20;;57490:97;57578:2;57558:14;-1:-1;;57554:28;;57538:49;57595:94;57669:2;57665:14;;57637:52;57697:117;57766:24;57784:5;57766:24;;;57759:5;57756:35;57746:2;;57805:1;57802;57795:12;57821:111;57887:21;57902:5;57887:21;;57939:117;58008:24;58026:5;58008:24;;58063:115;58131:23;58148:5;58131:23;;58185:107;58267:1;58260:5;58257:12;58247:2;;58283:1;58280;58273:12
Swarm Source
bzzr://54acbafafa6908356df4b14019a2815a4f242caed603fbe98f637bc9471c488f
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.