Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
FeederLogic
Compiler Version
v0.8.2+commit.661d1103
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2021-03-31
*/
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.2;
interface IPlatformIntegration {
/**
* @dev Deposit the given bAsset to Lending platform
* @param _bAsset bAsset address
* @param _amount Amount to deposit
*/
function deposit(
address _bAsset,
uint256 _amount,
bool isTokenFeeCharged
) external returns (uint256 quantityDeposited);
/**
* @dev Withdraw given bAsset from Lending platform
*/
function withdraw(
address _receiver,
address _bAsset,
uint256 _amount,
bool _hasTxFee
) external;
/**
* @dev Withdraw given bAsset from Lending platform
*/
function withdraw(
address _receiver,
address _bAsset,
uint256 _amount,
uint256 _totalAmount,
bool _hasTxFee
) external;
/**
* @dev Withdraw given bAsset from the cache
*/
function withdrawRaw(
address _receiver,
address _bAsset,
uint256 _amount
) external;
/**
* @dev Returns the current balance of the given bAsset
*/
function checkBalance(address _bAsset) external returns (uint256 balance);
/**
* @dev Returns the pToken
*/
function bAssetToPToken(address _bAsset) external returns (address pToken);
}
struct BassetPersonal {
// Address of the bAsset
address addr;
// Address of the bAsset
address integrator;
// An ERC20 can charge transfer fee, for example USDT, DGX tokens.
bool hasTxFee; // takes a byte in storage
// Status of the bAsset
BassetStatus status;
}
struct BassetData {
// 1 Basset * ratio / ratioScale == x Masset (relative value)
// If ratio == 10e8 then 1 bAsset = 10 mAssets
// A ratio is divised as 10^(18-tokenDecimals) * measurementMultiple(relative value of 1 base unit)
uint128 ratio;
// Amount of the Basset that is held in Collateral
uint128 vaultBalance;
}
abstract contract IMasset {
// Mint
function mint(
address _input,
uint256 _inputQuantity,
uint256 _minOutputQuantity,
address _recipient
) external virtual returns (uint256 mintOutput);
function mintMulti(
address[] calldata _inputs,
uint256[] calldata _inputQuantities,
uint256 _minOutputQuantity,
address _recipient
) external virtual returns (uint256 mintOutput);
function getMintOutput(address _input, uint256 _inputQuantity)
external
view
virtual
returns (uint256 mintOutput);
function getMintMultiOutput(address[] calldata _inputs, uint256[] calldata _inputQuantities)
external
view
virtual
returns (uint256 mintOutput);
// Swaps
function swap(
address _input,
address _output,
uint256 _inputQuantity,
uint256 _minOutputQuantity,
address _recipient
) external virtual returns (uint256 swapOutput);
function getSwapOutput(
address _input,
address _output,
uint256 _inputQuantity
) external view virtual returns (uint256 swapOutput);
// Redemption
function redeem(
address _output,
uint256 _mAssetQuantity,
uint256 _minOutputQuantity,
address _recipient
) external virtual returns (uint256 outputQuantity);
function redeemMasset(
uint256 _mAssetQuantity,
uint256[] calldata _minOutputQuantities,
address _recipient
) external virtual returns (uint256[] memory outputQuantities);
function redeemExactBassets(
address[] calldata _outputs,
uint256[] calldata _outputQuantities,
uint256 _maxMassetQuantity,
address _recipient
) external virtual returns (uint256 mAssetRedeemed);
function getRedeemOutput(address _output, uint256 _mAssetQuantity)
external
view
virtual
returns (uint256 bAssetOutput);
function getRedeemExactBassetsOutput(
address[] calldata _outputs,
uint256[] calldata _outputQuantities
) external view virtual returns (uint256 mAssetAmount);
// Views
function getBasket() external view virtual returns (bool, bool);
function getBasset(address _token)
external
view
virtual
returns (BassetPersonal memory personal, BassetData memory data);
function getBassets()
external
view
virtual
returns (BassetPersonal[] memory personal, BassetData[] memory data);
function bAssetIndexes(address) external view virtual returns (uint8);
// SavingsManager
function collectInterest() external virtual returns (uint256 swapFeesGained, uint256 newSupply);
function collectPlatformInterest()
external
virtual
returns (uint256 mintAmount, uint256 newSupply);
// Admin
function setCacheSize(uint256 _cacheSize) external virtual;
function upgradeForgeValidator(address _newForgeValidator) external virtual;
function setFees(uint256 _swapFee, uint256 _redemptionFee) external virtual;
function setTransferFeesFlag(address _bAsset, bool _flag) external virtual;
function migrateBassets(address[] calldata _bAssets, address _newIntegration) external virtual;
}
// Status of the Basset - has it broken its peg?
enum BassetStatus {
Default,
Normal,
BrokenBelowPeg,
BrokenAbovePeg,
Blacklisted,
Liquidating,
Liquidated,
Failed
}
struct BasketState {
bool undergoingRecol;
bool failed;
}
struct InvariantConfig {
uint256 a;
WeightLimits limits;
}
struct WeightLimits {
uint128 min;
uint128 max;
}
struct FeederConfig {
uint256 supply;
uint256 a;
WeightLimits limits;
}
struct AmpData {
uint64 initialA;
uint64 targetA;
uint64 rampStartTime;
uint64 rampEndTime;
}
struct FeederData {
uint256 swapFee;
uint256 redemptionFee;
uint256 govFee;
uint256 pendingFees;
uint256 cacheSize;
BassetPersonal[] bAssetPersonal;
BassetData[] bAssetData;
AmpData ampData;
WeightLimits weightLimits;
}
struct AssetData {
uint8 idx;
uint256 amt;
BassetPersonal personal;
}
struct Asset {
uint8 idx;
address addr;
bool exists;
}
library Root {
/**
* @dev Returns the square root of a given number
* @param x Input
* @return y Square root of Input
*/
function sqrt(uint256 x) internal pure returns (uint256 y) {
if (x == 0) return 0;
else {
uint256 xx = x;
uint256 r = 1;
if (xx >= 0x100000000000000000000000000000000) {
xx >>= 128;
r <<= 64;
}
if (xx >= 0x10000000000000000) {
xx >>= 64;
r <<= 32;
}
if (xx >= 0x100000000) {
xx >>= 32;
r <<= 16;
}
if (xx >= 0x10000) {
xx >>= 16;
r <<= 8;
}
if (xx >= 0x100) {
xx >>= 8;
r <<= 4;
}
if (xx >= 0x10) {
xx >>= 4;
r <<= 2;
}
if (xx >= 0x8) {
r <<= 1;
}
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1; // Seven iterations should be enough
uint256 r1 = x / r;
return uint256(r < r1 ? r : r1);
}
}
}
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
/**
* @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) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @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].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
library SafeERC20 {
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));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
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) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_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. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "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");
}
}
}
library SafeCast {
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
require(value < 2**255, "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}
library MassetHelpers {
using SafeERC20 for IERC20;
function transferReturnBalance(
address _sender,
address _recipient,
address _bAsset,
uint256 _qty
) internal returns (uint256 receivedQty, uint256 recipientBalance) {
uint256 balBefore = IERC20(_bAsset).balanceOf(_recipient);
IERC20(_bAsset).safeTransferFrom(_sender, _recipient, _qty);
recipientBalance = IERC20(_bAsset).balanceOf(_recipient);
receivedQty = recipientBalance - balBefore;
}
function safeInfiniteApprove(address _asset, address _spender) internal {
IERC20(_asset).safeApprove(_spender, 0);
IERC20(_asset).safeApprove(_spender, 2**256 - 1);
}
}
library StableMath {
/**
* @dev Scaling unit for use in specific calculations,
* where 1 * 10**18, or 1e18 represents a unit '1'
*/
uint256 private constant FULL_SCALE = 1e18;
/**
* @dev Token Ratios are used when converting between units of bAsset, mAsset and MTA
* Reasoning: Takes into account token decimals, and difference in base unit (i.e. grams to Troy oz for gold)
* bAsset ratio unit for use in exact calculations,
* where (1 bAsset unit * bAsset.ratio) / ratioScale == x mAsset unit
*/
uint256 private constant RATIO_SCALE = 1e8;
/**
* @dev Provides an interface to the scaling unit
* @return Scaling unit (1e18 or 1 * 10**18)
*/
function getFullScale() internal pure returns (uint256) {
return FULL_SCALE;
}
/**
* @dev Provides an interface to the ratio unit
* @return Ratio scale unit (1e8 or 1 * 10**8)
*/
function getRatioScale() internal pure returns (uint256) {
return RATIO_SCALE;
}
/**
* @dev Scales a given integer to the power of the full scale.
* @param x Simple uint256 to scale
* @return Scaled value a to an exact number
*/
function scaleInteger(uint256 x) internal pure returns (uint256) {
return x * FULL_SCALE;
}
/***************************************
PRECISE ARITHMETIC
****************************************/
/**
* @dev Multiplies two precise units, and then truncates by the full scale
* @param x Left hand input to multiplication
* @param y Right hand input to multiplication
* @return Result after multiplying the two inputs and then dividing by the shared
* scale unit
*/
function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {
return mulTruncateScale(x, y, FULL_SCALE);
}
/**
* @dev Multiplies two precise units, and then truncates by the given scale. For example,
* when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18
* @param x Left hand input to multiplication
* @param y Right hand input to multiplication
* @param scale Scale unit
* @return Result after multiplying the two inputs and then dividing by the shared
* scale unit
*/
function mulTruncateScale(
uint256 x,
uint256 y,
uint256 scale
) internal pure returns (uint256) {
// e.g. assume scale = fullScale
// z = 10e18 * 9e17 = 9e36
// return 9e38 / 1e18 = 9e18
return (x * y) / scale;
}
/**
* @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result
* @param x Left hand input to multiplication
* @param y Right hand input to multiplication
* @return Result after multiplying the two inputs and then dividing by the shared
* scale unit, rounded up to the closest base unit.
*/
function mulTruncateCeil(uint256 x, uint256 y) internal pure returns (uint256) {
// e.g. 8e17 * 17268172638 = 138145381104e17
uint256 scaled = x * y;
// e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17
uint256 ceil = scaled + FULL_SCALE - 1;
// e.g. 13814538111.399...e18 / 1e18 = 13814538111
return ceil / FULL_SCALE;
}
/**
* @dev Precisely divides two units, by first scaling the left hand operand. Useful
* for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)
* @param x Left hand input to division
* @param y Right hand input to division
* @return Result after multiplying the left operand by the scale, and
* executing the division on the right hand input.
*/
function divPrecisely(uint256 x, uint256 y) internal pure returns (uint256) {
// e.g. 8e18 * 1e18 = 8e36
// e.g. 8e36 / 10e18 = 8e17
return (x * FULL_SCALE) / y;
}
/***************************************
RATIO FUNCS
****************************************/
/**
* @dev Multiplies and truncates a token ratio, essentially flooring the result
* i.e. How much mAsset is this bAsset worth?
* @param x Left hand operand to multiplication (i.e Exact quantity)
* @param ratio bAsset ratio
* @return c Result after multiplying the two inputs and then dividing by the ratio scale
*/
function mulRatioTruncate(uint256 x, uint256 ratio) internal pure returns (uint256 c) {
return mulTruncateScale(x, ratio, RATIO_SCALE);
}
/**
* @dev Multiplies and truncates a token ratio, rounding up the result
* i.e. How much mAsset is this bAsset worth?
* @param x Left hand input to multiplication (i.e Exact quantity)
* @param ratio bAsset ratio
* @return Result after multiplying the two inputs and then dividing by the shared
* ratio scale, rounded up to the closest base unit.
*/
function mulRatioTruncateCeil(uint256 x, uint256 ratio) internal pure returns (uint256) {
// e.g. How much mAsset should I burn for this bAsset (x)?
// 1e18 * 1e8 = 1e26
uint256 scaled = x * ratio;
// 1e26 + 9.99e7 = 100..00.999e8
uint256 ceil = scaled + RATIO_SCALE - 1;
// return 100..00.999e8 / 1e8 = 1e18
return ceil / RATIO_SCALE;
}
/**
* @dev Precisely divides two ratioed units, by first scaling the left hand operand
* i.e. How much bAsset is this mAsset worth?
* @param x Left hand operand in division
* @param ratio bAsset ratio
* @return c Result after multiplying the left operand by the scale, and
* executing the division on the right hand input.
*/
function divRatioPrecisely(uint256 x, uint256 ratio) internal pure returns (uint256 c) {
// e.g. 1e14 * 1e8 = 1e22
// return 1e22 / 1e12 = 1e10
return (x * RATIO_SCALE) / ratio;
}
/***************************************
HELPERS
****************************************/
/**
* @dev Calculates minimum of two numbers
* @param x Left hand input
* @param y Right hand input
* @return Minimum of the two inputs
*/
function min(uint256 x, uint256 y) internal pure returns (uint256) {
return x > y ? y : x;
}
/**
* @dev Calculated maximum of two numbers
* @param x Left hand input
* @param y Right hand input
* @return Maximum of the two inputs
*/
function max(uint256 x, uint256 y) internal pure returns (uint256) {
return x > y ? x : y;
}
/**
* @dev Clamps a value to an upper bound
* @param x Left hand input
* @param upperBound Maximum possible value to return
* @return Input x clamped to a maximum value, upperBound
*/
function clamp(uint256 x, uint256 upperBound) internal pure returns (uint256) {
return x > upperBound ? upperBound : x;
}
}
// External
// Internal
// Libs
/**
* @title FeederLogic
* @author mStable
* @notice Logic contract for feeder pools that calculates trade output and updates core state.
* Includes modular invariant application code applying the StableSwap invariant first designed
* by Curve Finance and derived for mStable application in MIP-8 (https://mips.mstable.org/MIPS/mip-8)
* @dev VERSION: 1.0
* DATE: 2021-03-01
*/
library FeederLogic {
using StableMath for uint256;
using SafeERC20 for IERC20;
uint256 internal constant A_PRECISION = 100;
/***************************************
MINT
****************************************/
/**
* @notice Transfers token in, updates internal balances and computes the fpToken output
* @param _data Feeder pool storage state
* @param _config Core config for use in the invariant validator
* @param _input Data on the bAsset to deposit for the minted fpToken.
* @param _inputQuantity Quantity in input token units.
* @param _minOutputQuantity Minimum fpToken quantity to be minted. This protects against slippage.
* @return mintOutput Quantity of fpToken minted from the deposited bAsset.
*/
function mint(
FeederData storage _data,
FeederConfig calldata _config,
Asset calldata _input,
uint256 _inputQuantity,
uint256 _minOutputQuantity
) external returns (uint256 mintOutput) {
BassetData[] memory cachedBassetData = _data.bAssetData;
AssetData memory inputData =
_transferIn(_data, _config, cachedBassetData, _input, _inputQuantity);
// Validation should be after token transfer, as real input amt is unknown before
mintOutput = computeMint(cachedBassetData, inputData.idx, inputData.amt, _config);
require(mintOutput >= _minOutputQuantity, "Mint quantity < min qty");
}
/**
* @notice Transfers tokens in, updates internal balances and computes the fpToken output.
* Only fAsset & mAsset are supported in this path.
* @param _data Feeder pool storage state
* @param _config Core config for use in the invariant validator
* @param _indices Non-duplicate addresses of the bAssets to deposit for the minted fpToken.
* @param _inputQuantities Quantity of each input in input token units.
* @param _minOutputQuantity Minimum fpToken quantity to be minted. This protects against slippage.
* @return mintOutput Quantity of fpToken minted from the deposited bAsset.
*/
function mintMulti(
FeederData storage _data,
FeederConfig calldata _config,
uint8[] calldata _indices,
uint256[] calldata _inputQuantities,
uint256 _minOutputQuantity
) external returns (uint256 mintOutput) {
uint256 len = _indices.length;
uint256[] memory quantitiesDeposited = new uint256[](len);
// Load bAssets from storage into memory
BassetData[] memory allBassets = _data.bAssetData;
uint256 maxCache = _getCacheDetails(_data, _config.supply);
// Transfer the Bassets to the integrator & update storage
for (uint256 i = 0; i < len; i++) {
if (_inputQuantities[i] > 0) {
uint8 idx = _indices[i];
BassetData memory bData = allBassets[idx];
quantitiesDeposited[i] = _depositTokens(
_data.bAssetPersonal[idx],
bData.ratio,
_inputQuantities[i],
maxCache
);
_data.bAssetData[idx].vaultBalance =
bData.vaultBalance +
SafeCast.toUint128(quantitiesDeposited[i]);
}
}
// Validate the proposed mint, after token transfer
mintOutput = computeMintMulti(allBassets, _indices, quantitiesDeposited, _config);
require(mintOutput >= _minOutputQuantity, "Mint quantity < min qty");
require(mintOutput > 0, "Zero mAsset quantity");
}
/***************************************
SWAP
****************************************/
/**
* @notice Swaps two assets - either internally between fAsset<>mAsset, or between fAsset<>mpAsset by
* first routing through the mAsset pool.
* @param _data Feeder pool storage state
* @param _config Core config for use in the invariant validator
* @param _input Data on bAsset to deposit
* @param _output Data on bAsset to withdraw
* @param _inputQuantity Units of input bAsset to swap in
* @param _minOutputQuantity Minimum quantity of the swap output asset. This protects against slippage
* @param _recipient Address to transfer output asset to
* @return swapOutput Quantity of output asset returned from swap
* @return localFee Fee paid, in fpToken terms
*/
function swap(
FeederData storage _data,
FeederConfig calldata _config,
Asset calldata _input,
Asset calldata _output,
uint256 _inputQuantity,
uint256 _minOutputQuantity,
address _recipient
) external returns (uint256 swapOutput, uint256 localFee) {
BassetData[] memory cachedBassetData = _data.bAssetData;
AssetData memory inputData =
_transferIn(_data, _config, cachedBassetData, _input, _inputQuantity);
// 1. [f/mAsset ->][ f/mAsset] : Y - normal in, SWAP, normal out
// 3. [mpAsset -> mAsset][ -> fAsset] : Y - mint in , SWAP, normal out
if (_output.exists) {
(swapOutput, localFee) = _swapLocal(
_data,
_config,
cachedBassetData,
inputData,
_output,
_minOutputQuantity,
_recipient
);
}
// 2. [fAsset ->][ mAsset][ -> mpAsset] : Y - normal in, SWAP, mpOut
else {
address mAsset = _data.bAssetPersonal[0].addr;
(swapOutput, localFee) = _swapLocal(
_data,
_config,
cachedBassetData,
inputData,
Asset(0, mAsset, true),
0,
address(this)
);
swapOutput = IMasset(mAsset).redeem(
_output.addr,
swapOutput,
_minOutputQuantity,
_recipient
);
}
}
/***************************************
REDEEM
****************************************/
/**
* @notice Burns a specified quantity of the senders fpToken in return for a bAsset. The output amount is derived
* from the invariant. Supports redemption into either the fAsset, mAsset or assets in the mAsset basket.
* @param _data Feeder pool storage state
* @param _config Core config for use in the invariant validator
* @param _output Data on bAsset to withdraw
* @param _fpTokenQuantity Quantity of fpToken to burn
* @param _minOutputQuantity Minimum bAsset quantity to receive for the burnt fpToken. This protects against slippage.
* @param _recipient Address to transfer the withdrawn bAssets to.
* @return outputQuantity Quanity of bAsset units received for the burnt fpToken
* @return localFee Fee paid, in fpToken terms
*/
function redeem(
FeederData storage _data,
FeederConfig calldata _config,
Asset calldata _output,
uint256 _fpTokenQuantity,
uint256 _minOutputQuantity,
address _recipient
) external returns (uint256 outputQuantity, uint256 localFee) {
if (_output.exists) {
(outputQuantity, localFee) = _redeemLocal(
_data,
_config,
_output,
_fpTokenQuantity,
_minOutputQuantity,
_recipient
);
} else {
address mAsset = _data.bAssetPersonal[0].addr;
(outputQuantity, localFee) = _redeemLocal(
_data,
_config,
Asset(0, mAsset, true),
_fpTokenQuantity,
0,
address(this)
);
outputQuantity = IMasset(mAsset).redeem(
_output.addr,
outputQuantity,
_minOutputQuantity,
_recipient
);
}
}
/**
* @dev Credits a recipient with a proportionate amount of bAssets, relative to current vault
* balance levels and desired fpToken quantity. Burns the fpToken as payment. Only fAsset & mAsset are supported in this path.
* @param _data Feeder pool storage state
* @param _config Core config for use in the invariant validator
* @param _inputQuantity Quantity of fpToken to redeem
* @param _minOutputQuantities Min units of output to receive
* @param _recipient Address to credit the withdrawn bAssets
* @return scaledFee Fee collected in fpToken terms
* @return outputs Array of output asset addresses
* @return outputQuantities Array of output asset quantities
*/
function redeemProportionately(
FeederData storage _data,
FeederConfig calldata _config,
uint256 _inputQuantity,
uint256[] calldata _minOutputQuantities,
address _recipient
)
external
returns (
uint256 scaledFee,
address[] memory outputs,
uint256[] memory outputQuantities
)
{
// Calculate mAsset redemption quantities
scaledFee = _inputQuantity.mulTruncate(_data.redemptionFee);
// cache = (config.supply - inputQuantity) * 0.2
uint256 maxCache = _getCacheDetails(_data, _config.supply - _inputQuantity);
// Load the bAsset data from storage into memory
BassetData[] memory allBassets = _data.bAssetData;
uint256 len = allBassets.length;
outputs = new address[](len);
outputQuantities = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
// Get amount out, proportionate to redemption quantity
uint256 amountOut =
(allBassets[i].vaultBalance * (_inputQuantity - scaledFee)) / _config.supply;
require(amountOut > 1, "Output == 0");
amountOut -= 1;
require(amountOut >= _minOutputQuantities[i], "bAsset qty < min qty");
// Set output in array
(outputQuantities[i], outputs[i]) = (amountOut, _data.bAssetPersonal[i].addr);
// Transfer the bAsset to the recipient
_withdrawTokens(
amountOut,
_data.bAssetPersonal[i],
allBassets[i],
_recipient,
maxCache
);
// Reduce vaultBalance
_data.bAssetData[i].vaultBalance =
allBassets[i].vaultBalance -
SafeCast.toUint128(amountOut);
}
}
/**
* @dev Credits a recipient with a certain quantity of selected bAssets, in exchange for burning the
* relative fpToken quantity from the sender. Only fAsset & mAsset (0,1) are supported in this path.
* @param _data Feeder pool storage state
* @param _config Core config for use in the invariant validator
* @param _indices Indices of the bAssets to receive
* @param _outputQuantities Units of the bAssets to receive
* @param _maxInputQuantity Maximum fpToken quantity to burn for the received bAssets. This protects against slippage.
* @param _recipient Address to receive the withdrawn bAssets
* @return fpTokenQuantity Quantity of fpToken units to burn as payment
* @return localFee Fee collected, in fpToken terms
*/
function redeemExactBassets(
FeederData storage _data,
FeederConfig memory _config,
uint8[] calldata _indices,
uint256[] calldata _outputQuantities,
uint256 _maxInputQuantity,
address _recipient
) external returns (uint256 fpTokenQuantity, uint256 localFee) {
// Load bAsset data from storage to memory
BassetData[] memory allBassets = _data.bAssetData;
// Validate redemption
uint256 fpTokenRequired =
computeRedeemExact(allBassets, _indices, _outputQuantities, _config);
fpTokenQuantity = fpTokenRequired.divPrecisely(1e18 - _data.redemptionFee);
localFee = fpTokenQuantity - fpTokenRequired;
require(fpTokenQuantity > 0, "Must redeem some mAssets");
fpTokenQuantity += 1;
require(fpTokenQuantity <= _maxInputQuantity, "Redeem mAsset qty > max quantity");
// Burn the full amount of Masset
uint256 maxCache = _getCacheDetails(_data, _config.supply - fpTokenQuantity);
// Transfer the Bassets to the recipient
for (uint256 i = 0; i < _outputQuantities.length; i++) {
_withdrawTokens(
_outputQuantities[i],
_data.bAssetPersonal[_indices[i]],
allBassets[_indices[i]],
_recipient,
maxCache
);
_data.bAssetData[_indices[i]].vaultBalance =
allBassets[_indices[i]].vaultBalance -
SafeCast.toUint128(_outputQuantities[i]);
}
}
/***************************************
FORGING - INTERNAL
****************************************/
/**
* @dev Transfers an asset in and updates vault balance. Supports fAsset, mAsset and mpAsset.
* Transferring an mpAsset requires first a mint in the main pool, and consequent depositing of
* the mAsset.
*/
function _transferIn(
FeederData storage _data,
FeederConfig memory _config,
BassetData[] memory _cachedBassetData,
Asset memory _input,
uint256 _inputQuantity
) internal returns (AssetData memory inputData) {
// fAsset / mAsset transfers
if (_input.exists) {
BassetPersonal memory personal = _data.bAssetPersonal[_input.idx];
uint256 amt =
_depositTokens(
personal,
_cachedBassetData[_input.idx].ratio,
_inputQuantity,
_getCacheDetails(_data, _config.supply)
);
inputData = AssetData(_input.idx, amt, personal);
}
// mpAsset transfers
else {
inputData = _mpMint(
_data,
_input,
_inputQuantity,
_getCacheDetails(_data, _config.supply)
);
require(inputData.amt > 0, "Must mint something from mp");
}
_data.bAssetData[inputData.idx].vaultBalance =
_cachedBassetData[inputData.idx].vaultBalance +
SafeCast.toUint128(inputData.amt);
}
/**
* @dev Mints an asset in the main mAsset pool. Input asset must be supported by the mAsset
* or else the call will revert. After minting, check if the balance exceeds the cache upper limit
* and consequently deposit if necessary.
*/
function _mpMint(
FeederData storage _data,
Asset memory _input,
uint256 _inputQuantity,
uint256 _maxCache
) internal returns (AssetData memory mAssetData) {
mAssetData = AssetData(0, 0, _data.bAssetPersonal[0]);
IERC20(_input.addr).safeTransferFrom(msg.sender, address(this), _inputQuantity);
address integrator =
mAssetData.personal.integrator == address(0)
? address(this)
: mAssetData.personal.integrator;
uint256 balBefore = IERC20(mAssetData.personal.addr).balanceOf(integrator);
// Mint will revert if the _input.addr is not whitelisted on that mAsset
IMasset(mAssetData.personal.addr).mint(_input.addr, _inputQuantity, 0, integrator);
uint256 balAfter = IERC20(mAssetData.personal.addr).balanceOf(integrator);
mAssetData.amt = balAfter - balBefore;
// Route the mAsset to platform integration
if (integrator != address(this)) {
if (balAfter > _maxCache) {
uint256 delta = balAfter - (_maxCache / 2);
IPlatformIntegration(integrator).deposit(mAssetData.personal.addr, delta, false);
}
}
}
/**
* @dev Performs a swap between fAsset and mAsset. If the output is an mAsset, do not
* charge the swap fee.
*/
function _swapLocal(
FeederData storage _data,
FeederConfig memory _config,
BassetData[] memory _cachedBassetData,
AssetData memory _inputData,
Asset memory _output,
uint256 _minOutputQuantity,
address _recipient
) internal returns (uint256 swapOutput, uint256 scaledFee) {
// Validate the swap
(swapOutput, scaledFee) = computeSwap(
_cachedBassetData,
_inputData.idx,
_output.idx,
_inputData.amt,
_output.idx == 0 ? 0 : _data.swapFee,
_config
);
require(swapOutput >= _minOutputQuantity, "Output qty < minimum qty");
require(swapOutput > 0, "Zero output quantity");
// Settle the swap
_withdrawTokens(
swapOutput,
_data.bAssetPersonal[_output.idx],
_cachedBassetData[_output.idx],
_recipient,
_getCacheDetails(_data, _config.supply)
);
// Decrease output bal
_data.bAssetData[_output.idx].vaultBalance =
_cachedBassetData[_output.idx].vaultBalance -
SafeCast.toUint128(swapOutput);
}
/**
* @dev Performs a local redemption into either fAsset or mAsset.
*/
function _redeemLocal(
FeederData storage _data,
FeederConfig memory _config,
Asset memory _output,
uint256 _fpTokenQuantity,
uint256 _minOutputQuantity,
address _recipient
) internal returns (uint256 outputQuantity, uint256 scaledFee) {
BassetData[] memory allBassets = _data.bAssetData;
// Subtract the redemption fee
scaledFee = _fpTokenQuantity.mulTruncate(_data.redemptionFee);
// Calculate redemption quantities
outputQuantity = computeRedeem(
allBassets,
_output.idx,
_fpTokenQuantity - scaledFee,
_config
);
require(outputQuantity >= _minOutputQuantity, "bAsset qty < min qty");
require(outputQuantity > 0, "Output == 0");
// Transfer the bAssets to the recipient
_withdrawTokens(
outputQuantity,
_data.bAssetPersonal[_output.idx],
allBassets[_output.idx],
_recipient,
_getCacheDetails(_data, _config.supply - _fpTokenQuantity)
);
// Set vault balance
_data.bAssetData[_output.idx].vaultBalance =
allBassets[_output.idx].vaultBalance -
SafeCast.toUint128(outputQuantity);
}
/**
* @dev Deposits a given asset to the system. If there is sufficient room for the asset
* in the cache, then just transfer, otherwise reset the cache to the desired mid level by
* depositing the delta in the platform
*/
function _depositTokens(
BassetPersonal memory _bAsset,
uint256 _bAssetRatio,
uint256 _quantity,
uint256 _maxCache
) internal returns (uint256 quantityDeposited) {
// 0. If integration is 0, short circuit
if (_bAsset.integrator == address(0)) {
(uint256 received, ) =
MassetHelpers.transferReturnBalance(
msg.sender,
address(this),
_bAsset.addr,
_quantity
);
return received;
}
// 1 - Send all to PI, using the opportunity to get the cache balance and net amount transferred
uint256 cacheBal;
(quantityDeposited, cacheBal) = MassetHelpers.transferReturnBalance(
msg.sender,
_bAsset.integrator,
_bAsset.addr,
_quantity
);
// 2 - Deposit X if necessary
// 2.1 - Deposit if xfer fees
if (_bAsset.hasTxFee) {
uint256 deposited =
IPlatformIntegration(_bAsset.integrator).deposit(
_bAsset.addr,
quantityDeposited,
true
);
return StableMath.min(deposited, quantityDeposited);
}
// 2.2 - Else Deposit X if Cache > %
// This check is in place to ensure that any token with a txFee is rejected
require(quantityDeposited == _quantity, "Asset not fully transferred");
uint256 relativeMaxCache = _maxCache.divRatioPrecisely(_bAssetRatio);
if (cacheBal > relativeMaxCache) {
uint256 delta = cacheBal - (relativeMaxCache / 2);
IPlatformIntegration(_bAsset.integrator).deposit(_bAsset.addr, delta, false);
}
}
/**
* @dev Withdraws a given asset from its platformIntegration. If there is sufficient liquidity
* in the cache, then withdraw from there, otherwise withdraw from the lending market and reset the
* cache to the mid level.
*/
function _withdrawTokens(
uint256 _quantity,
BassetPersonal memory _personal,
BassetData memory _data,
address _recipient,
uint256 _maxCache
) internal {
if (_quantity == 0) return;
// 1.0 If there is no integrator, send from here
if (_personal.integrator == address(0)) {
// If this is part of a cross-swap or cross-redeem, and there is no
// integrator.. then we don't need to transfer anywhere
if (_recipient == address(this)) return;
IERC20(_personal.addr).safeTransfer(_recipient, _quantity);
}
// 1.1 If txFee then short circuit - there is no cache
else if (_personal.hasTxFee) {
IPlatformIntegration(_personal.integrator).withdraw(
_recipient,
_personal.addr,
_quantity,
_quantity,
true
);
}
// 1.2. Else, withdraw from either cache or main vault
else {
uint256 cacheBal = IERC20(_personal.addr).balanceOf(_personal.integrator);
// 2.1 - If balance b in cache, simply withdraw
if (cacheBal >= _quantity) {
IPlatformIntegration(_personal.integrator).withdrawRaw(
_recipient,
_personal.addr,
_quantity
);
}
// 2.2 - Else reset the cache to X, or as far as possible
// - Withdraw X+b from platform
// - Send b to user
else {
uint256 relativeMidCache = _maxCache.divRatioPrecisely(_data.ratio) / 2;
uint256 totalWithdrawal =
StableMath.min(
relativeMidCache + _quantity - cacheBal,
_data.vaultBalance - SafeCast.toUint128(cacheBal)
);
IPlatformIntegration(_personal.integrator).withdraw(
_recipient,
_personal.addr,
_quantity,
totalWithdrawal,
false
);
}
}
}
/**
* @dev Gets the max cache size, given the supply of fpToken
* @return maxCache Max units of any given bAsset that should be held in the cache
*/
function _getCacheDetails(FeederData storage _data, uint256 _supply)
internal
view
returns (uint256 maxCache)
{
maxCache = (_supply * _data.cacheSize) / 1e18;
}
/***************************************
INVARIANT
****************************************/
/**
* @notice Compute the amount of fpToken received for minting
* with `quantity` amount of bAsset index `i`.
* @param _bAssets Array of all bAsset Data
* @param _i Index of bAsset with which to mint
* @param _rawInput Raw amount of bAsset to use in mint
* @param _config Generalised FeederConfig stored externally
* @return mintAmount Quantity of fpTokens minted
*/
function computeMint(
BassetData[] memory _bAssets,
uint8 _i,
uint256 _rawInput,
FeederConfig memory _config
) public pure returns (uint256 mintAmount) {
// 1. Get raw reserves
(uint256[] memory x, uint256 sum) = _getReserves(_bAssets);
// 2. Get value of reserves according to invariant
uint256 k0 = _invariant(x, sum, _config.a);
uint256 scaledInput = (_rawInput * _bAssets[_i].ratio) / 1e8;
require(scaledInput > 1e6, "Must add > 1e6 units");
// 3. Add deposit to x and sum
x[_i] += scaledInput;
sum += scaledInput;
// 4. Finalise mint
require(_inBounds(x, sum, _config.limits), "Exceeds weight limits");
mintAmount = _computeMintOutput(x, sum, k0, _config);
}
/**
* @notice Compute the amount of fpToken received for minting
* with the given array of inputs.
* @param _bAssets Array of all bAsset Data
* @param _indices Indexes of bAssets with which to mint
* @param _rawInputs Raw amounts of bAssets to use in mint
* @param _config Generalised FeederConfig stored externally
* @return mintAmount Quantity of fpTokens minted
*/
function computeMintMulti(
BassetData[] memory _bAssets,
uint8[] memory _indices,
uint256[] memory _rawInputs,
FeederConfig memory _config
) public pure returns (uint256 mintAmount) {
// 1. Get raw reserves
(uint256[] memory x, uint256 sum) = _getReserves(_bAssets);
// 2. Get value of reserves according to invariant
uint256 k0 = _invariant(x, sum, _config.a);
// 3. Add deposits to x and sum
uint256 len = _indices.length;
uint8 idx;
uint256 scaledInput;
for (uint256 i = 0; i < len; i++) {
idx = _indices[i];
scaledInput = (_rawInputs[i] * _bAssets[idx].ratio) / 1e8;
x[idx] += scaledInput;
sum += scaledInput;
}
// 4. Finalise mint
require(_inBounds(x, sum, _config.limits), "Exceeds weight limits");
mintAmount = _computeMintOutput(x, sum, k0, _config);
}
/**
* @notice Compute the amount of bAsset received for swapping
* `quantity` amount of index `input_idx` to index `output_idx`.
* @param _bAssets Array of all bAsset Data
* @param _i Index of bAsset to swap IN
* @param _o Index of bAsset to swap OUT
* @param _rawInput Raw amounts of input bAsset to input
* @param _feeRate Swap fee rate to apply to output
* @param _config Generalised FeederConfig stored externally
* @return bAssetOutputQuantity Raw bAsset output quantity
* @return scaledSwapFee Swap fee collected, in fpToken terms
*/
function computeSwap(
BassetData[] memory _bAssets,
uint8 _i,
uint8 _o,
uint256 _rawInput,
uint256 _feeRate,
FeederConfig memory _config
) public pure returns (uint256 bAssetOutputQuantity, uint256 scaledSwapFee) {
// 1. Get raw reserves
(uint256[] memory x, uint256 sum) = _getReserves(_bAssets);
// 2. Get value of reserves according to invariant
uint256 k0 = _invariant(x, sum, _config.a);
// 3. Add deposits to x and sum
uint256 scaledInput = (_rawInput * _bAssets[_i].ratio) / 1e8;
require(scaledInput > 1e6, "Must add > 1e6 units");
x[_i] += scaledInput;
sum += scaledInput;
// 4. Calc total fpToken q
uint256 k1 = _invariant(x, sum, _config.a);
scaledSwapFee = ((k1 - k0) * _feeRate) / 1e18;
// 5. Calc output bAsset
uint256 newOutputReserve = _solveInvariant(x, _config.a, _o, k0 + scaledSwapFee);
// Convert swap fee to fpToken terms
// fpFee = fee * s / k
scaledSwapFee = (scaledSwapFee * _config.supply) / k0;
uint256 output = x[_o] - newOutputReserve - 1;
bAssetOutputQuantity = (output * 1e8) / _bAssets[_o].ratio;
// 6. Check for bounds
x[_o] -= output;
sum -= output;
require(_inBounds(x, sum, _config.limits), "Exceeds weight limits");
}
/**
* @notice Compute the amount of bAsset index `i` received for
* redeeming `quantity` amount of fpToken.
* @param _bAssets Array of all bAsset Data
* @param _o Index of output bAsset
* @param _netRedeemInput Net amount of fpToken to redeem
* @param _config Generalised FeederConfig stored externally
* @return rawOutputUnits Raw bAsset output returned
*/
function computeRedeem(
BassetData[] memory _bAssets,
uint8 _o,
uint256 _netRedeemInput,
FeederConfig memory _config
) public pure returns (uint256 rawOutputUnits) {
require(_netRedeemInput > 1e6, "Must redeem > 1e6 units");
// 1. Get raw reserves
(uint256[] memory x, uint256 sum) = _getReserves(_bAssets);
// 2. Get value of reserves according to invariant
uint256 k0 = _invariant(x, sum, _config.a);
uint256 kFinal = (k0 * (_config.supply - _netRedeemInput)) / _config.supply + 1;
// 3. Compute bAsset output
uint256 newOutputReserve = _solveInvariant(x, _config.a, _o, kFinal);
uint256 output = x[_o] - newOutputReserve - 1;
rawOutputUnits = (output * 1e8) / _bAssets[_o].ratio;
// 4. Check for max weight
x[_o] -= output;
sum -= output;
require(_inBounds(x, sum, _config.limits), "Exceeds weight limits");
}
/**
* @notice Compute the amount of fpToken required to redeem
* a given selection of bAssets.
* @param _bAssets Array of all bAsset Data
* @param _indices Indexes of output bAssets
* @param _rawOutputs Desired raw bAsset outputs
* @param _config Generalised FeederConfig stored externally
* @return redeemInput Amount of fpToken required to redeem bAssets
*/
function computeRedeemExact(
BassetData[] memory _bAssets,
uint8[] memory _indices,
uint256[] memory _rawOutputs,
FeederConfig memory _config
) public pure returns (uint256 redeemInput) {
// 1. Get raw reserves
(uint256[] memory x, uint256 sum) = _getReserves(_bAssets);
// 2. Get value of reserves according to invariant
uint256 k0 = _invariant(x, sum, _config.a);
// 3. Sub deposits from x and sum
uint256 len = _indices.length;
uint256 ratioed;
for (uint256 i = 0; i < len; i++) {
ratioed = (_rawOutputs[i] * _bAssets[_indices[i]].ratio) / 1e8;
x[_indices[i]] -= ratioed;
sum -= ratioed;
}
require(_inBounds(x, sum, _config.limits), "Exceeds weight limits");
// 4. Get new value of reserves according to invariant
uint256 k1 = _invariant(x, sum, _config.a);
// 5. Total fpToken is the difference between values
redeemInput = (_config.supply * (k0 - k1)) / k0;
require(redeemInput > 1e6, "Must redeem > 1e6 units");
}
/**
* @notice Gets the price of the fpToken, and invariant value k
* @param _bAssets Array of all bAsset Data
* @param _config Generalised FeederConfig stored externally
* @return price Price of an fpToken
* @return k Total value of basket, k
*/
function computePrice(BassetData[] memory _bAssets, FeederConfig memory _config)
public
pure
returns (uint256 price, uint256 k)
{
(uint256[] memory x, uint256 sum) = _getReserves(_bAssets);
k = _invariant(x, sum, _config.a);
price = (1e18 * k) / _config.supply;
}
/***************************************
INTERNAL
****************************************/
/**
* @dev Computes the actual mint output after adding mint inputs
* to the vault balances
* @param _x Scaled vaultBalances
* @param _sum Sum of vaultBalances, to avoid another loop
* @param _k Previous value of invariant, k, before addition
* @param _config Generalised FeederConfig stored externally
* @return mintAmount Amount of value added to invariant, in fpToken terms
*/
function _computeMintOutput(
uint256[] memory _x,
uint256 _sum,
uint256 _k,
FeederConfig memory _config
) internal pure returns (uint256 mintAmount) {
// 1. Get value of reserves according to invariant
uint256 kFinal = _invariant(_x, _sum, _config.a);
// 2. Total minted is the difference between values, with respect to total supply
if (_config.supply == 0) {
mintAmount = kFinal - _k;
} else {
mintAmount = (_config.supply * (kFinal - _k)) / _k;
}
}
/**
* @dev Simply scaled raw reserve values and returns the sum
* @param _bAssets All bAssets
* @return x Scaled vault balances
* @return sum Sum of scaled vault balances
*/
function _getReserves(BassetData[] memory _bAssets)
internal
pure
returns (uint256[] memory x, uint256 sum)
{
uint256 len = _bAssets.length;
x = new uint256[](len);
uint256 r;
for (uint256 i = 0; i < len; i++) {
BassetData memory bAsset = _bAssets[i];
r = (bAsset.vaultBalance * bAsset.ratio) / 1e8;
x[i] = r;
sum += r;
}
}
/**
* @dev Checks that no bAsset reserves exceed max weight
* @param _x Scaled bAsset reserves
* @param _sum Sum of x, precomputed
* @param _limits Config object containing max and min weights
* @return inBounds Bool, true if all assets are within bounds
*/
function _inBounds(
uint256[] memory _x,
uint256 _sum,
WeightLimits memory _limits
) internal pure returns (bool inBounds) {
uint256 len = _x.length;
inBounds = true;
uint256 w;
for (uint256 i = 0; i < len; i++) {
w = (_x[i] * 1e18) / _sum;
if (w > _limits.max || w < _limits.min) return false;
}
}
/***************************************
INVARIANT
****************************************/
/**
* @dev Compute the invariant f(x) for a given array of supplies `x`.
* @param _x Scaled vault balances
* @param _sum Sum of scaled vault balances
* @param _a Precise amplification coefficient
* @return k Cumulative value of all assets according to the invariant
*/
function _invariant(
uint256[] memory _x,
uint256 _sum,
uint256 _a
) internal pure returns (uint256 k) {
if (_sum == 0) return 0;
uint256 var1 = _x[0] * _x[1];
uint256 var2 = (_a * var1) / (_x[0] + _x[1]) / A_PRECISION;
// result = 2 * (isqrt(var2**2 + (A + A_PRECISION) * var1 // A_PRECISION) - var2) + 1
k = 2 * (Root.sqrt((var2**2) + (((_a + A_PRECISION) * var1) / A_PRECISION)) - var2) + 1;
}
/**
* @dev Solves the invariant for _i with respect to target K, given an array of reserves.
* @param _x Scaled reserve balances
* @param _a Precise amplification coefficient
* @param _idx Index of asset for which to solve
* @param _targetK Target invariant value K
* @return y New reserve of _i
*/
function _solveInvariant(
uint256[] memory _x,
uint256 _a,
uint8 _idx,
uint256 _targetK
) internal pure returns (uint256 y) {
require(_idx == 0 || _idx == 1, "Invalid index");
uint256 x = _idx == 0 ? _x[1] : _x[0];
uint256 var1 = _a + A_PRECISION;
uint256 var2 = ((_targetK**2) * A_PRECISION) / var1;
// var3 = var2 // (4 * x) + k * _a // var1 - x
uint256 tmp = var2 / (4 * x) + ((_targetK * _a) / var1);
uint256 var3 = tmp >= x ? tmp - x : x - tmp;
// result = (sqrt(var3**2 + var2) + var3) // 2
y = ((Root.sqrt((var3**2) + var2) + tmp - x) / 2) + 1;
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"components":[{"internalType":"uint128","name":"ratio","type":"uint128"},{"internalType":"uint128","name":"vaultBalance","type":"uint128"}],"internalType":"struct BassetData[]","name":"_bAssets","type":"tuple[]"},{"internalType":"uint8","name":"_i","type":"uint8"},{"internalType":"uint256","name":"_rawInput","type":"uint256"},{"components":[{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"a","type":"uint256"},{"components":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"internalType":"struct WeightLimits","name":"limits","type":"tuple"}],"internalType":"struct FeederConfig","name":"_config","type":"tuple"}],"name":"computeMint","outputs":[{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"ratio","type":"uint128"},{"internalType":"uint128","name":"vaultBalance","type":"uint128"}],"internalType":"struct BassetData[]","name":"_bAssets","type":"tuple[]"},{"internalType":"uint8[]","name":"_indices","type":"uint8[]"},{"internalType":"uint256[]","name":"_rawInputs","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"a","type":"uint256"},{"components":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"internalType":"struct WeightLimits","name":"limits","type":"tuple"}],"internalType":"struct FeederConfig","name":"_config","type":"tuple"}],"name":"computeMintMulti","outputs":[{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"ratio","type":"uint128"},{"internalType":"uint128","name":"vaultBalance","type":"uint128"}],"internalType":"struct BassetData[]","name":"_bAssets","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"a","type":"uint256"},{"components":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"internalType":"struct WeightLimits","name":"limits","type":"tuple"}],"internalType":"struct FeederConfig","name":"_config","type":"tuple"}],"name":"computePrice","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"k","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"ratio","type":"uint128"},{"internalType":"uint128","name":"vaultBalance","type":"uint128"}],"internalType":"struct BassetData[]","name":"_bAssets","type":"tuple[]"},{"internalType":"uint8","name":"_o","type":"uint8"},{"internalType":"uint256","name":"_netRedeemInput","type":"uint256"},{"components":[{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"a","type":"uint256"},{"components":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"internalType":"struct WeightLimits","name":"limits","type":"tuple"}],"internalType":"struct FeederConfig","name":"_config","type":"tuple"}],"name":"computeRedeem","outputs":[{"internalType":"uint256","name":"rawOutputUnits","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"ratio","type":"uint128"},{"internalType":"uint128","name":"vaultBalance","type":"uint128"}],"internalType":"struct BassetData[]","name":"_bAssets","type":"tuple[]"},{"internalType":"uint8[]","name":"_indices","type":"uint8[]"},{"internalType":"uint256[]","name":"_rawOutputs","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"a","type":"uint256"},{"components":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"internalType":"struct WeightLimits","name":"limits","type":"tuple"}],"internalType":"struct FeederConfig","name":"_config","type":"tuple"}],"name":"computeRedeemExact","outputs":[{"internalType":"uint256","name":"redeemInput","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"ratio","type":"uint128"},{"internalType":"uint128","name":"vaultBalance","type":"uint128"}],"internalType":"struct BassetData[]","name":"_bAssets","type":"tuple[]"},{"internalType":"uint8","name":"_i","type":"uint8"},{"internalType":"uint8","name":"_o","type":"uint8"},{"internalType":"uint256","name":"_rawInput","type":"uint256"},{"internalType":"uint256","name":"_feeRate","type":"uint256"},{"components":[{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"uint256","name":"a","type":"uint256"},{"components":[{"internalType":"uint128","name":"min","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"internalType":"struct WeightLimits","name":"limits","type":"tuple"}],"internalType":"struct FeederConfig","name":"_config","type":"tuple"}],"name":"computeSwap","outputs":[{"internalType":"uint256","name":"bAssetOutputQuantity","type":"uint256"},{"internalType":"uint256","name":"scaledSwapFee","type":"uint256"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
61466061003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100be5760003560e01c80638c913b941161007b5780638c913b94146101935780639e60b1c5146101b3578063b4ff6eae146101c6578063d1be5528146101e6578063dce9bf6a146101f9578063f134c4fb1461020c576100be565b80635c1ba5f0146100c35780635dd72f5d146100fd5780636089efbc146101105780636fdc2ea21461013e5780637116e8181461016d5780637cdc8e4014610180575b600080fd5b8180156100cf57600080fd5b506100e36100de366004613f8f565b61022c565b604080519283526020830191909152015b60405180910390f35b6100e361010b366004613d33565b610451565b81801561011c57600080fd5b5061013061012b366004614007565b61049f565b6040519081526020016100f4565b81801561014a57600080fd5b5061015e6101593660046140b1565b6105bf565b6040516100f493929190614298565b61013061017b366004613c42565b610a7d565b61013061018e366004613c42565b610bf7565b81801561019f57600080fd5b506100e36101ae36600461411b565b610e09565b6101306101c1366004613d7f565b6112cb565b8180156101d257600080fd5b506101306101e1366004613efe565b61148d565b6101306101f4366004613d7f565b6118d4565b6100e3610207366004613dda565b611a23565b81801561021857600080fd5b506100e3610227366004614059565b611cc4565b600080600089600601805480602002602001604051908101604052809291908181526020016000905b8282101561029e57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101610255565b50505050905060006102d18b8b8036038101906102bb9190613ee3565b846102cb368e90038e018e613e92565b8b611e40565b90506102e36060890160408a01613e5a565b1561031d576103138b6102fb368d90038d018d613ee3565b848461030c368e90038e018e613e92565b8b8b6120b0565b9094509250610443565b60008b60050160008154811061034357634e487b7160e01b600052603260045260246000fd5b60009182526020909120600290910201546001600160a01b031690506103a78c610372368e90038e018e613ee3565b85856040518060600160405280600060ff168152602001876001600160a01b03168152602001600115158152506000306120b0565b90955093506001600160a01b0381166343bcfab66103cb60408c0160208d01613c28565b878a8a6040518563ffffffff1660e01b81526004016103ed949392919061420b565b602060405180830381600087803b15801561040757600080fd5b505af115801561041b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043f91906141bd565b9450505b505097509795505050505050565b6000806000806104608661232f565b9150915061047382828760200151612443565b855190935061048a84670de0b6b3a7640000614532565b61049491906143e1565b935050509250929050565b60008086600601805480602002602001604051908101604052809291908181526020016000905b8282101561050f57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b90910416818301528252600190920191016104c6565b5050505090506000610542888880360381019061052c9190613ee3565b8461053c368b90038b018b613e92565b89611e40565b905061056382826000015183602001518a8036038101906101f49190613ee3565b9250838310156105b45760405162461bcd60e51b81526020600482015260176024820152764d696e74207175616e74697479203c206d696e2071747960481b60448201526064015b60405180910390fd5b505095945050505050565b60006060806105db89600101548861259d90919063ffffffff16565b925060006105f38a6105ee8a8c35614579565b6125b2565b905060008a600601805480602002602001604051908101604052809291908181526020016000905b8282101561066457600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b909104168183015282526001909201910161061b565b50508251929350829150506001600160401b0381111561069457634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156106bd578160200160208202803683370190505b509450806001600160401b038111156106e657634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561070f578160200160208202803683370190505b50935060005b81811015610a6d5760008c3561072b898e614579565b85848151811061074b57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516001600160801b031661076a9190614532565b61077491906143e1565b9050600181116107b45760405162461bcd60e51b815260206004820152600b60248201526a04f7574707574203d3d20360ac1b60448201526064016105ab565b6107bf600182614579565b90508a8a838181106107e157634e487b7160e01b600052603260045260246000fd5b9050602002013581101561082e5760405162461bcd60e51b815260206004820152601460248201527362417373657420717479203c206d696e2071747960601b60448201526064016105ab565b808e600501838154811061085257634e487b7160e01b600052603260045260246000fd5b600091825260209091206002909102015487516001600160a01b039091169088908590811061089157634e487b7160e01b600052603260045260246000fd5b602002602001018985815181106108b857634e487b7160e01b600052603260045260246000fd5b60200260200101826001600160a01b03166001600160a01b03168152508281525050506109d2818f600501848154811061090257634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b90910416600781111561098057634e487b7160e01b600052602160045260246000fd5b600781111561099f57634e487b7160e01b600052602160045260246000fd5b815250508685815181106109c357634e487b7160e01b600052603260045260246000fd5b60200260200101518c896125d7565b6109db816128ab565b8483815181106109fb57634e487b7160e01b600052603260045260246000fd5b602002602001015160200151610a119190614551565b8e6006018381548110610a3457634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790555080610a65816145bc565b915050610715565b5050505096509650969350505050565b6000806000610a8b8761232f565b915091506000610aa083838760200151612443565b8751909150600080805b83811015610bb0578a8181518110610ad257634e487b7160e01b600052603260045260246000fd5b602002602001015192506305f5e1008c8460ff1681518110610b0457634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b03168b8381518110610b3957634e487b7160e01b600052603260045260246000fd5b6020026020010151610b4b9190614532565b610b5591906143e1565b915081878460ff1681518110610b7b57634e487b7160e01b600052603260045260246000fd5b60200260200101818151610b8f91906143a3565b905250610b9c82876143a3565b955080610ba8816145bc565b915050610aaa565b50610bc086868a60400151612918565b610bdc5760405162461bcd60e51b81526004016105ab90614269565b610be88686868b6129c2565b9b9a5050505050505050505050565b6000806000610c058761232f565b915091506000610c1a83838760200151612443565b87519091506000805b82811015610d4d576305f5e1008b8b8381518110610c5157634e487b7160e01b600052603260045260246000fd5b602002602001015160ff1681518110610c7a57634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b03168a8381518110610caf57634e487b7160e01b600052603260045260246000fd5b6020026020010151610cc19190614532565b610ccb91906143e1565b915081868b8381518110610cef57634e487b7160e01b600052603260045260246000fd5b602002602001015160ff1681518110610d1857634e487b7160e01b600052603260045260246000fd5b60200260200101818151610d2c9190614579565b905250610d398286614579565b945080610d45816145bc565b915050610c23565b50610d5d85858960400151612918565b610d795760405162461bcd60e51b81526004016105ab90614269565b6000610d8a86868a60200151612443565b905083610d978282614579565b8951610da39190614532565b610dad91906143e1565b9650620f42408711610dfb5760405162461bcd60e51b81526020600482015260176024820152764d7573742072656465656d203e2031653620756e69747360481b60448201526064016105ab565b505050505050949350505050565b60008060008a600601805480602002602001604051908101604052809291908181526020016000905b82821015610e7b57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101610e32565b5050505090506000610f00828b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d918291850190849080828437600081840152601f19601f820116905080830192505050505050508e610bf7565b9050610f248c60010154670de0b6b3a7640000610f1d9190614579565b8290612a1b565b9350610f308185614579565b925060008411610f825760405162461bcd60e51b815260206004820152601860248201527f4d7573742072656465656d20736f6d65206d417373657473000000000000000060448201526064016105ab565b610f8d6001856143a3565b935085841115610fdf5760405162461bcd60e51b815260206004820181905260248201527f52656465656d206d417373657420717479203e206d6178207175616e7469747960448201526064016105ab565b6000610ff58d868e600001516105ee9190614579565b905060005b888110156112ba5761118c8a8a8381811061102557634e487b7160e01b600052603260045260246000fd5b905060200201358f6005018e8e8581811061105057634e487b7160e01b600052603260045260246000fd5b905060200201602081019061106591906141d5565b60ff168154811061108657634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b90910416600781111561110457634e487b7160e01b600052602160045260246000fd5b600781111561112357634e487b7160e01b600052602160045260246000fd5b905250868f8f8681811061114757634e487b7160e01b600052603260045260246000fd5b905060200201602081019061115c91906141d5565b60ff168151811061117d57634e487b7160e01b600052603260045260246000fd5b60200260200101518a866125d7565b6111bb8a8a838181106111af57634e487b7160e01b600052603260045260246000fd5b905060200201356128ab565b848d8d848181106111dc57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906111f191906141d5565b60ff168151811061121257634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516112289190614551565b8e6006018d8d8481811061124c57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061126191906141d5565b60ff168154811061128257634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055806112b2816145bc565b915050610ffa565b505050509850989650505050505050565b6000620f424083116113195760405162461bcd60e51b81526020600482015260176024820152764d7573742072656465656d203e2031653620756e69747360481b60448201526064016105ab565b6000806113258761232f565b91509150600061133a83838760200151612443565b855190915060009061134c8882614579565b6113569084614532565b61136091906143e1565b61136b9060016143a3565b9050600061137f8588602001518b85612a30565b90506000600182878c60ff16815181106113a957634e487b7160e01b600052603260045260246000fd5b60200260200101516113bb9190614579565b6113c59190614579565b90508a8a60ff16815181106113ea57634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b0316816305f5e10061140f9190614532565b61141991906143e1565b965080868b60ff168151811061143f57634e487b7160e01b600052603260045260246000fd5b602002602001018181516114539190614579565b9052506114608186614579565b945061147186868a60400151612918565b610dfb5760405162461bcd60e51b81526004016105ab90614269565b60008481816001600160401b038111156114b757634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156114e0578160200160208202803683370190505b50905060008a600601805480602002602001604051908101604052809291908181526020016000905b8282101561155257600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101611509565b50505050905060006115688c8c600001356125b2565b905060005b848110156117d957600089898381811061159757634e487b7160e01b600052603260045260246000fd5b9050602002013511156117c75760008b8b838181106115c657634e487b7160e01b600052603260045260246000fd5b90506020020160208101906115db91906141d5565b90506000848260ff168151811061160257634e487b7160e01b600052603260045260246000fd5b6020026020010151905061170d8f6005018360ff168154811061163557634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b9091041660078111156116b357634e487b7160e01b600052602160045260246000fd5b60078111156116d257634e487b7160e01b600052602160045260246000fd5b90525082516001600160801b03168d8d8781811061170057634e487b7160e01b600052603260045260246000fd5b9050602002013587612bc1565b86848151811061172d57634e487b7160e01b600052603260045260246000fd5b60200260200101818152505061176986848151811061175c57634e487b7160e01b600052603260045260246000fd5b60200260200101516128ab565b81602001516117789190614378565b8f6006018360ff168154811061179e57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b02921691909117905550505b806117d1816145bc565b91505061156d565b50611832828b8b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050858e80360381019061017b9190613ee3565b94508585101561187e5760405162461bcd60e51b81526020600482015260176024820152764d696e74207175616e74697479203c206d696e2071747960481b60448201526064016105ab565b600085116118c55760405162461bcd60e51b81526020600482015260146024820152735a65726f206d4173736574207175616e7469747960601b60448201526064016105ab565b50505050979650505050505050565b60008060006118e28761232f565b9150915060006118f783838760200151612443565b905060006305f5e100898960ff168151811061192357634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b0316886119439190614532565b61194d91906143e1565b9050620f424081116119985760405162461bcd60e51b81526020600482015260146024820152734d75737420616464203e2031653620756e69747360601b60448201526064016105ab565b80848960ff16815181106119bc57634e487b7160e01b600052603260045260246000fd5b602002602001018181516119d091906143a3565b9052506119dd81846143a3565b92506119ee84848860400151612918565b611a0a5760405162461bcd60e51b81526004016105ab90614269565b611a16848484896129c2565b9998505050505050505050565b600080600080611a328a61232f565b915091506000611a4783838860200151612443565b905060006305f5e1008c8c60ff1681518110611a7357634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b03168a611a939190614532565b611a9d91906143e1565b9050620f42408111611ae85760405162461bcd60e51b81526020600482015260146024820152734d75737420616464203e2031653620756e69747360601b60448201526064016105ab565b80848c60ff1681518110611b0c57634e487b7160e01b600052603260045260246000fd5b60200260200101818151611b2091906143a3565b905250611b2d81846143a3565b92506000611b4085858a60200151612443565b9050670de0b6b3a764000089611b568584614579565b611b609190614532565b611b6a91906143e1565b95506000611b89868a602001518e8a88611b8491906143a3565b612a30565b89519091508490611b9a9089614532565b611ba491906143e1565b96506000600182888f60ff1681518110611bce57634e487b7160e01b600052603260045260246000fd5b6020026020010151611be09190614579565b611bea9190614579565b90508e8d60ff1681518110611c0f57634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b0316816305f5e100611c349190614532565b611c3e91906143e1565b985080878e60ff1681518110611c6457634e487b7160e01b600052603260045260246000fd5b60200260200101818151611c789190614579565b905250611c858187614579565b9550611c9687878c60400151612918565b611cb25760405162461bcd60e51b81526004016105ab90614269565b50505050505050965096945050505050565b600080611cd76060870160408801613e5a565b15611d1057611d0688611cef368a90038a018a613ee3565b611cfe368a90038a018a613e92565b888888612ddd565b9092509050611e35565b600088600501600081548110611d3657634e487b7160e01b600052603260045260246000fd5b60009182526020909120600290910201546001600160a01b03169050611d9989611d65368b90038b018b613ee3565b6040518060600160405280600060ff168152602001856001600160a01b031681526020016001151581525089600030612ddd565b90935091506001600160a01b0381166343bcfab6611dbd60408a0160208b01613c28565b8588886040518563ffffffff1660e01b8152600401611ddf949392919061420b565b602060405180830381600087803b158015611df957600080fd5b505af1158015611e0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3191906141bd565b9250505b965096945050505050565b611e486139d4565b826040015115611f9e57600086600501846000015160ff1681548110611e7e57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115611efc57634e487b7160e01b600052602160045260246000fd5b6007811115611f1b57634e487b7160e01b600052602160045260246000fd5b8152505090506000611f778287876000015160ff1681518110611f4e57634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b031686611f728c8c600001516125b2565b612bc1565b60408051606081018252875160ff168152602081019290925281019290925250905061200d565b611fb7868484611fb28a8a600001516125b2565b6130c3565b9050600081602001511161200d5760405162461bcd60e51b815260206004820152601b60248201527f4d757374206d696e7420736f6d657468696e672066726f6d206d70000000000060448201526064016105ab565b61201a81602001516128ab565b84826000015160ff168151811061204157634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516120579190614378565b86600601826000015160ff168154811061208157634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b02921691909117905595945050505050565b83518351602086015160009283926120df928a92919060ff8216156120d6578d546120d9565b60005b8d611a23565b9092509050838210156121345760405162461bcd60e51b815260206004820152601860248201527f4f757470757420717479203c206d696e696d756d20717479000000000000000060448201526064016105ab565b6000821161217b5760405162461bcd60e51b81526020600482015260146024820152735a65726f206f7574707574207175616e7469747960601b60448201526064016105ab565b61228b828a600501876000015160ff16815481106121a957634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b90910416600781111561222757634e487b7160e01b600052602160045260246000fd5b600781111561224657634e487b7160e01b600052602160045260246000fd5b90525087518a518b9160ff1690811061226f57634e487b7160e01b600052603260045260246000fd5b6020026020010151866122868e8e600001516125b2565b6125d7565b612294826128ab565b87866000015160ff16815181106122bb57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516122d19190614551565b89600601866000015160ff16815481106122fb57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055909890975095505050505050565b8051606090600090806001600160401b0381111561235d57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612386578160200160208202803683370190505b5092506000805b8281101561243b5760008682815181106123b757634e487b7160e01b600052603260045260246000fd5b602002602001015190506305f5e100816000015182602001516123da919061450c565b6123e491906143bb565b6001600160801b031692508286838151811061241057634e487b7160e01b600052603260045260246000fd5b602090810291909101015261242583866143a3565b9450508080612433906145bc565b91505061238d565b505050915091565b60008261245257506000612596565b60008460018151811061247557634e487b7160e01b600052603260045260246000fd5b60200260200101518560008151811061249e57634e487b7160e01b600052603260045260246000fd5b60200260200101516124b09190614532565b905060006064866001815181106124d757634e487b7160e01b600052603260045260246000fd5b60200260200101518760008151811061250057634e487b7160e01b600052603260045260246000fd5b602002602001015161251291906143a3565b61251c8487614532565b61252691906143e1565b61253091906143e1565b90508061257160648461254382896143a3565b61254d9190614532565b61255791906143e1565b61256260028561443b565b61256c91906143a3565b61346c565b61257b9190614579565b612586906002614532565b6125919060016143a3565b925050505b9392505050565b60006125968383670de0b6b3a76400006135eb565b6000670de0b6b3a76400008360040154836125cd9190614532565b61259691906143e1565b846125e1576128a4565b60208401516001600160a01b0316612624576001600160a01b038216301415612609576128a4565b835161261f906001600160a01b03168387613602565b6128a4565b8360400151156126b2576020840151845160405163c89fc72f60e01b81526001600160a01b038581166004830152918216602482015260448101889052606481018890526001608482015291169063c89fc72f9060a401600060405180830381600087803b15801561269557600080fd5b505af11580156126a9573d6000803e3d6000fd5b505050506128a4565b835160208501516040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a082319060240160206040518083038186803b1580156126ff57600080fd5b505afa158015612713573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273791906141bd565b90508581106127b6576020850151855160405163a4e2859560e01b81526001600160a01b03868116600483015291821660248201526044810189905291169063a4e2859590606401600060405180830381600087803b15801561279957600080fd5b505af11580156127ad573d6000803e3d6000fd5b505050506128a2565b83516000906002906127d29085906001600160801b031661366a565b6127dc91906143e1565b9050600061281e836127ee8a856143a3565b6127f89190614579565b612801856128ab565b88602001516128109190614551565b6001600160801b031661367b565b6020880151885160405163c89fc72f60e01b81526001600160a01b0389811660048301529182166024820152604481018c90526064810184905260006084820152929350169063c89fc72f9060a401600060405180830381600087803b15801561288757600080fd5b505af115801561289b573d6000803e3d6000fd5b5050505050505b505b5050505050565b6000600160801b82106129105760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b60648201526084016105ab565b50805b919050565b82516001906000805b828110156129b8578587828151811061294a57634e487b7160e01b600052603260045260246000fd5b6020026020010151670de0b6b3a76400006129659190614532565b61296f91906143e1565b915084602001516001600160801b0316821180612995575084516001600160801b031682105b156129a65760009350505050612596565b806129b0816145bc565b915050612921565b5050509392505050565b6000806129d486868560200151612443565b83519091506129ee576129e78482614579565b9150612a12565b836129f98183614579565b8451612a059190614532565b612a0f91906143e1565b91505b50949350505050565b6000816125cd670de0b6b3a764000085614532565b600060ff83161580612a4557508260ff166001145b612a815760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b60448201526064016105ab565b600060ff841615612aba5785600081518110612aad57634e487b7160e01b600052603260045260246000fd5b6020026020010151612ae4565b85600181518110612adb57634e487b7160e01b600052603260045260246000fd5b60200260200101515b90506000612af36064876143a3565b90506000816064612b0560028861443b565b612b0f9190614532565b612b1991906143e1565b9050600082612b288988614532565b612b3291906143e1565b612b3d856004614532565b612b4790846143e1565b612b5191906143a3565b9050600084821015612b6c57612b678286614579565b612b76565b612b768583614579565b905060028583612b8a86612562858761443b565b612b9491906143a3565b612b9e9190614579565b612ba891906143e1565b612bb39060016143a3565b9a9950505050505050505050565b60208401516000906001600160a01b0316612bf2576000612be83330886000015187613690565b509150612dd59050565b6000612c08338760200151886000015187613690565b6040880151919350915015612cc157602086015186516040516307dba22560e31b81526001600160a01b03918216600482015260248101859052600160448201526000929190911690633edd112890606401602060405180830381600087803b158015612c7457600080fd5b505af1158015612c88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cac91906141bd565b9050612cb8818461367b565b92505050612dd5565b838214612d105760405162461bcd60e51b815260206004820152601b60248201527f4173736574206e6f742066756c6c79207472616e73666572726564000000000060448201526064016105ab565b6000612d1c848761366a565b905080821115612dd2576000612d336002836143e1565b612d3d9084614579565b602089015189516040516307dba22560e31b81526001600160a01b03918216600482015260248101849052600060448201529293501690633edd112890606401602060405180830381600087803b158015612d9757600080fd5b505af1158015612dab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dcf91906141bd565b50505b50505b949350505050565b600080600088600601805480602002602001604051908101604052809291908181526020016000905b82821015612e4f57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101612e06565b505050509050612e6c89600101548761259d90919063ffffffff16565b8751909250612e87908290612e81858a614579565b8b6112cb565b925084831015612ed05760405162461bcd60e51b815260206004820152601460248201527362417373657420717479203c206d696e2071747960601b60448201526064016105ab565b60008311612f0e5760405162461bcd60e51b815260206004820152600b60248201526a04f7574707574203d3d20360ac1b60448201526064016105ab565b61301f838a600501896000015160ff1681548110612f3c57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115612fba57634e487b7160e01b600052602160045260246000fd5b6007811115612fd957634e487b7160e01b600052602160045260246000fd5b90525089518451859160ff1690811061300257634e487b7160e01b600052603260045260246000fd5b6020026020010151876122868e8c8f600001516105ee9190614579565b613028836128ab565b81886000015160ff168151811061304f57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516130659190614551565b89600601886000015160ff168154811061308f57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055509097909650945050505050565b6130cb6139d4565b6040518060600160405280600060ff168152602001600081526020018660050160008154811061310b57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b90910416600781111561318957634e487b7160e01b600052602160045260246000fd5b60078111156131a857634e487b7160e01b600052602160045260246000fd5b905250905260208501519091506131ca906001600160a01b03163330866137b9565b6040810151602001516000906001600160a01b0316156131f2578160400151602001516131f4565b305b6040808401515190516370a0823160e01b81526001600160a01b038084166004830152929350600092909116906370a082319060240160206040518083038186803b15801561324257600080fd5b505afa158015613256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327a91906141bd565b6040808501515160208901519151637ba5ff4760e11b81529293506001600160a01b03169163f74bfe8e916132b8918990600090889060040161420b565b602060405180830381600087803b1580156132d257600080fd5b505af11580156132e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330a91906141bd565b506040838101515190516370a0823160e01b81526001600160a01b03848116600483015260009216906370a082319060240160206040518083038186803b15801561335457600080fd5b505afa158015613368573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061338c91906141bd565b90506133988282614579565b60208501526001600160a01b038316301461346157848111156134615760006133c26002876143e1565b6133cc9083614579565b6040868101515190516307dba22560e31b81526001600160a01b0391821660048201526024810183905260006044820152919250851690633edd112890606401602060405180830381600087803b15801561342657600080fd5b505af115801561343a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061345e91906141bd565b50505b505050949350505050565b60008161347b57506000612913565b816001600160801b82106134945760809190911c9060401b5b6801000000000000000082106134af5760409190911c9060201b5b64010000000082106134c65760209190911c9060101b5b6201000082106134db5760109190911c9060081b5b61010082106134ef5760089190911c9060041b5b601082106135025760049190911c9060021b5b6008821061350e5760011b5b600161351a82866143e1565b61352490836143a3565b901c9050600161353482866143e1565b61353e90836143a3565b901c9050600161354e82866143e1565b61355890836143a3565b901c9050600161356882866143e1565b61357290836143a3565b901c9050600161358282866143e1565b61358c90836143a3565b901c9050600161359c82866143e1565b6135a690836143a3565b901c905060016135b682866143e1565b6135c090836143a3565b901c905060006135d082866143e1565b90508082106135df57806135e1565b815b9350505050612913565b6000816135f88486614532565b612dd591906143e1565b6040516001600160a01b03831660248201526044810182905261366590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526137f7565b505050565b6000816125cd6305f5e10085614532565b600081831161368a5782612596565b50919050565b6040516370a0823160e01b81526001600160a01b03848116600483015260009182918291908616906370a082319060240160206040518083038186803b1580156136d957600080fd5b505afa1580156136ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371191906141bd565b90506137286001600160a01b0386168888876137b9565b6040516370a0823160e01b81526001600160a01b0387811660048301528616906370a082319060240160206040518083038186803b15801561376957600080fd5b505afa15801561377d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137a191906141bd565b91506137ad8183614579565b92505094509492505050565b6040516001600160a01b03808516602483015283166044820152606481018290526137f19085906323b872dd60e01b9060840161362e565b50505050565b600061384c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166138c99092919063ffffffff16565b805190915015613665578080602001905181019061386a9190613e76565b6136655760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016105ab565b6060612dd5848460008585843b6139225760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105ab565b600080866001600160a01b0316858760405161393e91906141ef565b60006040518083038185875af1925050503d806000811461397b576040519150601f19603f3d011682016040523d82523d6000602084013e613980565b606091505b509150915061399082828661399b565b979650505050505050565b606083156139aa575081612596565b8251156139ba5782518084602001fd5b8160405162461bcd60e51b81526004016105ab9190614236565b60408051606081018252600080825260208201529081016139f36139f8565b905290565b604080516080810182526000808252602082018190529181018290529060608201906139f3565b80356001600160a01b038116811461291357600080fd5b600082601f830112613a46578081fd5b81356020613a5b613a5683614355565b614325565b82815281810190858301604080860288018501891015613a79578687fd5b865b86811015613a9f57613a8d8a84613b6d565b85529385019391810191600101613a7b565b509198975050505050505050565b60008083601f840112613abe578182fd5b5081356001600160401b03811115613ad4578182fd5b6020830191508360208083028501011115613aee57600080fd5b9250929050565b600082601f830112613b05578081fd5b81356020613b15613a5683614355565b8281528181019085830183850287018401881015613b31578586fd5b855b85811015613b4f57813584529284019290840190600101613b33565b5090979650505050505050565b60006060828403121561368a578081fd5b600060408284031215613b7e578081fd5b613b886040614325565b9050613b9382613c00565b8152613ba160208301613c00565b602082015292915050565b60006080828403121561368a578081fd5b600060808284031215613bce578081fd5b613bd86060614325565b90508135815260208201356020820152613bf58360408401613b6d565b604082015292915050565b80356001600160801b038116811461291357600080fd5b803560ff8116811461291357600080fd5b600060208284031215613c39578081fd5b61259682613a1f565b60008060008060e08587031215613c57578283fd5b84356001600160401b0380821115613c6d578485fd5b613c7988838901613a36565b9550602091508187013581811115613c8f578586fd5b8701601f81018913613c9f578586fd5b8035613cad613a5682614355565b81815284810190838601868402850187018d1015613cc957898afd5b8994505b83851015613cf257613cde81613c17565b835260019490940193918601918601613ccd565b5097505050506040870135915080821115613d0b578384fd5b50613d1887828801613af5565b925050613d288660608701613bbd565b905092959194509250565b60008060a08385031215613d45578182fd5b82356001600160401b03811115613d5a578283fd5b613d6685828601613a36565b925050613d768460208501613bbd565b90509250929050565b60008060008060e08587031215613d94578182fd5b84356001600160401b03811115613da9578283fd5b613db587828801613a36565b945050613dc460208601613c17565b925060408501359150613d288660608701613bbd565b6000806000806000806101208789031215613df3578384fd5b86356001600160401b03811115613e08578485fd5b613e1489828a01613a36565b965050613e2360208801613c17565b9450613e3160408801613c17565b93506060870135925060808701359150613e4e8860a08901613bbd565b90509295509295509295565b600060208284031215613e6b578081fd5b813561259681614619565b600060208284031215613e87578081fd5b815161259681614619565b600060608284031215613ea3578081fd5b613ead6060614325565b613eb683613c17565b8152613ec460208401613a1f565b60208201526040830135613ed781614619565b60408201529392505050565b600060808284031215613ef4578081fd5b6125968383613bbd565b6000806000806000806000610100888a031215613f19578485fd5b87359650613f2a8960208a01613bac565b955060a08801356001600160401b0380821115613f45578687fd5b613f518b838c01613aad565b909750955060c08a0135915080821115613f69578283fd5b50613f768a828b01613aad565b989b979a5095989497959660e090950135949350505050565b60008060008060008060006101c0888a031215613faa578081fd5b87359650613fbb8960208a01613bac565b9550613fca8960a08a01613b5c565b9450613fda896101008a01613b5c565b935061016088013592506101808801359150613ff96101a08901613a1f565b905092959891949750929550565b6000806000806000610140868803121561401f578283fd5b853594506140308760208801613bac565b935061403f8760a08801613b5c565b949793965093946101008101359450610120013592915050565b6000806000806000806101608789031215614072578384fd5b863595506140838860208901613bac565b94506140928860a08901613b5c565b935061010087013592506101208701359150613e4e6101408801613a1f565b60008060008060008061010087890312156140ca578384fd5b863595506140db8860208901613bac565b945060a0870135935060c08701356001600160401b038111156140fc578283fd5b61410889828a01613aad565b9094509250613e4e905060e08801613a1f565b600080600080600080600080610120898b031215614137578182fd5b883597506141488a60208b01613bbd565b965060a08901356001600160401b0380821115614163578384fd5b61416f8c838d01613aad565b909850965060c08b0135915080821115614187578384fd5b506141948b828c01613aad565b90955093505060e089013591506141ae6101008a01613a1f565b90509295985092959890939650565b6000602082840312156141ce578081fd5b5051919050565b6000602082840312156141e6578081fd5b61259682613c17565b60008251614201818460208701614590565b9190910192915050565b6001600160a01b03948516815260208101939093526040830191909152909116606082015260800190565b6000602082528251806020840152614255816040850160208701614590565b601f01601f19169190910160400192915050565b6020808252601590820152744578636565647320776569676874206c696d69747360581b604082015260600190565b60006060820185835260206060818501528186518084526080860191508288019350845b818110156142e15784516001600160a01b0316835293830193918301916001016142bc565b505084810360408601528551808252908201925081860190845b81811015614317578251855293830193918301916001016142fb565b509298975050505050505050565b604051601f8201601f191681016001600160401b038111828210171561434d5761434d614603565b604052919050565b60006001600160401b0382111561436e5761436e614603565b5060209081020190565b60006001600160801b0380831681851680830382111561439a5761439a6145d7565b01949350505050565b600082198211156143b6576143b66145d7565b500190565b60006001600160801b03808416806143d5576143d56145ed565b92169190910492915050565b6000826143f0576143f06145ed565b500490565b80825b60018086116144075750614432565b818704821115614419576144196145d7565b8086161561442657918102915b9490941c9380026143f8565b94509492505050565b600061259660001960ff85168460008261445757506001612596565b8161446457506000612596565b816001811461447a5760028114614484576144b1565b6001915050612596565b60ff841115614495576144956145d7565b6001841b9150848211156144ab576144ab6145d7565b50612596565b5060208310610133831016604e8410600b84101617156144e4575081810a838111156144df576144df6145d7565b612596565b6144f184848460016143f5565b808604821115614503576145036145d7565b02949350505050565b60006001600160801b0380831681851681830481118215151615614503576145036145d7565b600081600019048311821515161561454c5761454c6145d7565b500290565b60006001600160801b0383811690831681811015614571576145716145d7565b039392505050565b60008282101561458b5761458b6145d7565b500390565b60005b838110156145ab578181015183820152602001614593565b838111156137f15750506000910152565b60006000198214156145d0576145d06145d7565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461462757600080fd5b5056fea2646970667358221220e7ba85f0b708b8abff3092672d9a78fa4f5bfad0b48efb112edf3021161eae9a64736f6c63430008020033
Deployed Bytecode
0x732837c77527c37d61d9763f53005211dacb4125de30146080604052600436106100be5760003560e01c80638c913b941161007b5780638c913b94146101935780639e60b1c5146101b3578063b4ff6eae146101c6578063d1be5528146101e6578063dce9bf6a146101f9578063f134c4fb1461020c576100be565b80635c1ba5f0146100c35780635dd72f5d146100fd5780636089efbc146101105780636fdc2ea21461013e5780637116e8181461016d5780637cdc8e4014610180575b600080fd5b8180156100cf57600080fd5b506100e36100de366004613f8f565b61022c565b604080519283526020830191909152015b60405180910390f35b6100e361010b366004613d33565b610451565b81801561011c57600080fd5b5061013061012b366004614007565b61049f565b6040519081526020016100f4565b81801561014a57600080fd5b5061015e6101593660046140b1565b6105bf565b6040516100f493929190614298565b61013061017b366004613c42565b610a7d565b61013061018e366004613c42565b610bf7565b81801561019f57600080fd5b506100e36101ae36600461411b565b610e09565b6101306101c1366004613d7f565b6112cb565b8180156101d257600080fd5b506101306101e1366004613efe565b61148d565b6101306101f4366004613d7f565b6118d4565b6100e3610207366004613dda565b611a23565b81801561021857600080fd5b506100e3610227366004614059565b611cc4565b600080600089600601805480602002602001604051908101604052809291908181526020016000905b8282101561029e57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101610255565b50505050905060006102d18b8b8036038101906102bb9190613ee3565b846102cb368e90038e018e613e92565b8b611e40565b90506102e36060890160408a01613e5a565b1561031d576103138b6102fb368d90038d018d613ee3565b848461030c368e90038e018e613e92565b8b8b6120b0565b9094509250610443565b60008b60050160008154811061034357634e487b7160e01b600052603260045260246000fd5b60009182526020909120600290910201546001600160a01b031690506103a78c610372368e90038e018e613ee3565b85856040518060600160405280600060ff168152602001876001600160a01b03168152602001600115158152506000306120b0565b90955093506001600160a01b0381166343bcfab66103cb60408c0160208d01613c28565b878a8a6040518563ffffffff1660e01b81526004016103ed949392919061420b565b602060405180830381600087803b15801561040757600080fd5b505af115801561041b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043f91906141bd565b9450505b505097509795505050505050565b6000806000806104608661232f565b9150915061047382828760200151612443565b855190935061048a84670de0b6b3a7640000614532565b61049491906143e1565b935050509250929050565b60008086600601805480602002602001604051908101604052809291908181526020016000905b8282101561050f57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b90910416818301528252600190920191016104c6565b5050505090506000610542888880360381019061052c9190613ee3565b8461053c368b90038b018b613e92565b89611e40565b905061056382826000015183602001518a8036038101906101f49190613ee3565b9250838310156105b45760405162461bcd60e51b81526020600482015260176024820152764d696e74207175616e74697479203c206d696e2071747960481b60448201526064015b60405180910390fd5b505095945050505050565b60006060806105db89600101548861259d90919063ffffffff16565b925060006105f38a6105ee8a8c35614579565b6125b2565b905060008a600601805480602002602001604051908101604052809291908181526020016000905b8282101561066457600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b909104168183015282526001909201910161061b565b50508251929350829150506001600160401b0381111561069457634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156106bd578160200160208202803683370190505b509450806001600160401b038111156106e657634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561070f578160200160208202803683370190505b50935060005b81811015610a6d5760008c3561072b898e614579565b85848151811061074b57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516001600160801b031661076a9190614532565b61077491906143e1565b9050600181116107b45760405162461bcd60e51b815260206004820152600b60248201526a04f7574707574203d3d20360ac1b60448201526064016105ab565b6107bf600182614579565b90508a8a838181106107e157634e487b7160e01b600052603260045260246000fd5b9050602002013581101561082e5760405162461bcd60e51b815260206004820152601460248201527362417373657420717479203c206d696e2071747960601b60448201526064016105ab565b808e600501838154811061085257634e487b7160e01b600052603260045260246000fd5b600091825260209091206002909102015487516001600160a01b039091169088908590811061089157634e487b7160e01b600052603260045260246000fd5b602002602001018985815181106108b857634e487b7160e01b600052603260045260246000fd5b60200260200101826001600160a01b03166001600160a01b03168152508281525050506109d2818f600501848154811061090257634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b90910416600781111561098057634e487b7160e01b600052602160045260246000fd5b600781111561099f57634e487b7160e01b600052602160045260246000fd5b815250508685815181106109c357634e487b7160e01b600052603260045260246000fd5b60200260200101518c896125d7565b6109db816128ab565b8483815181106109fb57634e487b7160e01b600052603260045260246000fd5b602002602001015160200151610a119190614551565b8e6006018381548110610a3457634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b0292169190911790555080610a65816145bc565b915050610715565b5050505096509650969350505050565b6000806000610a8b8761232f565b915091506000610aa083838760200151612443565b8751909150600080805b83811015610bb0578a8181518110610ad257634e487b7160e01b600052603260045260246000fd5b602002602001015192506305f5e1008c8460ff1681518110610b0457634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b03168b8381518110610b3957634e487b7160e01b600052603260045260246000fd5b6020026020010151610b4b9190614532565b610b5591906143e1565b915081878460ff1681518110610b7b57634e487b7160e01b600052603260045260246000fd5b60200260200101818151610b8f91906143a3565b905250610b9c82876143a3565b955080610ba8816145bc565b915050610aaa565b50610bc086868a60400151612918565b610bdc5760405162461bcd60e51b81526004016105ab90614269565b610be88686868b6129c2565b9b9a5050505050505050505050565b6000806000610c058761232f565b915091506000610c1a83838760200151612443565b87519091506000805b82811015610d4d576305f5e1008b8b8381518110610c5157634e487b7160e01b600052603260045260246000fd5b602002602001015160ff1681518110610c7a57634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b03168a8381518110610caf57634e487b7160e01b600052603260045260246000fd5b6020026020010151610cc19190614532565b610ccb91906143e1565b915081868b8381518110610cef57634e487b7160e01b600052603260045260246000fd5b602002602001015160ff1681518110610d1857634e487b7160e01b600052603260045260246000fd5b60200260200101818151610d2c9190614579565b905250610d398286614579565b945080610d45816145bc565b915050610c23565b50610d5d85858960400151612918565b610d795760405162461bcd60e51b81526004016105ab90614269565b6000610d8a86868a60200151612443565b905083610d978282614579565b8951610da39190614532565b610dad91906143e1565b9650620f42408711610dfb5760405162461bcd60e51b81526020600482015260176024820152764d7573742072656465656d203e2031653620756e69747360481b60448201526064016105ab565b505050505050949350505050565b60008060008a600601805480602002602001604051908101604052809291908181526020016000905b82821015610e7b57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101610e32565b5050505090506000610f00828b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d918291850190849080828437600081840152601f19601f820116905080830192505050505050508e610bf7565b9050610f248c60010154670de0b6b3a7640000610f1d9190614579565b8290612a1b565b9350610f308185614579565b925060008411610f825760405162461bcd60e51b815260206004820152601860248201527f4d7573742072656465656d20736f6d65206d417373657473000000000000000060448201526064016105ab565b610f8d6001856143a3565b935085841115610fdf5760405162461bcd60e51b815260206004820181905260248201527f52656465656d206d417373657420717479203e206d6178207175616e7469747960448201526064016105ab565b6000610ff58d868e600001516105ee9190614579565b905060005b888110156112ba5761118c8a8a8381811061102557634e487b7160e01b600052603260045260246000fd5b905060200201358f6005018e8e8581811061105057634e487b7160e01b600052603260045260246000fd5b905060200201602081019061106591906141d5565b60ff168154811061108657634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b90910416600781111561110457634e487b7160e01b600052602160045260246000fd5b600781111561112357634e487b7160e01b600052602160045260246000fd5b905250868f8f8681811061114757634e487b7160e01b600052603260045260246000fd5b905060200201602081019061115c91906141d5565b60ff168151811061117d57634e487b7160e01b600052603260045260246000fd5b60200260200101518a866125d7565b6111bb8a8a838181106111af57634e487b7160e01b600052603260045260246000fd5b905060200201356128ab565b848d8d848181106111dc57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906111f191906141d5565b60ff168151811061121257634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516112289190614551565b8e6006018d8d8481811061124c57634e487b7160e01b600052603260045260246000fd5b905060200201602081019061126191906141d5565b60ff168154811061128257634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055806112b2816145bc565b915050610ffa565b505050509850989650505050505050565b6000620f424083116113195760405162461bcd60e51b81526020600482015260176024820152764d7573742072656465656d203e2031653620756e69747360481b60448201526064016105ab565b6000806113258761232f565b91509150600061133a83838760200151612443565b855190915060009061134c8882614579565b6113569084614532565b61136091906143e1565b61136b9060016143a3565b9050600061137f8588602001518b85612a30565b90506000600182878c60ff16815181106113a957634e487b7160e01b600052603260045260246000fd5b60200260200101516113bb9190614579565b6113c59190614579565b90508a8a60ff16815181106113ea57634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b0316816305f5e10061140f9190614532565b61141991906143e1565b965080868b60ff168151811061143f57634e487b7160e01b600052603260045260246000fd5b602002602001018181516114539190614579565b9052506114608186614579565b945061147186868a60400151612918565b610dfb5760405162461bcd60e51b81526004016105ab90614269565b60008481816001600160401b038111156114b757634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156114e0578160200160208202803683370190505b50905060008a600601805480602002602001604051908101604052809291908181526020016000905b8282101561155257600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101611509565b50505050905060006115688c8c600001356125b2565b905060005b848110156117d957600089898381811061159757634e487b7160e01b600052603260045260246000fd5b9050602002013511156117c75760008b8b838181106115c657634e487b7160e01b600052603260045260246000fd5b90506020020160208101906115db91906141d5565b90506000848260ff168151811061160257634e487b7160e01b600052603260045260246000fd5b6020026020010151905061170d8f6005018360ff168154811061163557634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b9091041660078111156116b357634e487b7160e01b600052602160045260246000fd5b60078111156116d257634e487b7160e01b600052602160045260246000fd5b90525082516001600160801b03168d8d8781811061170057634e487b7160e01b600052603260045260246000fd5b9050602002013587612bc1565b86848151811061172d57634e487b7160e01b600052603260045260246000fd5b60200260200101818152505061176986848151811061175c57634e487b7160e01b600052603260045260246000fd5b60200260200101516128ab565b81602001516117789190614378565b8f6006018360ff168154811061179e57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b02921691909117905550505b806117d1816145bc565b91505061156d565b50611832828b8b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050858e80360381019061017b9190613ee3565b94508585101561187e5760405162461bcd60e51b81526020600482015260176024820152764d696e74207175616e74697479203c206d696e2071747960481b60448201526064016105ab565b600085116118c55760405162461bcd60e51b81526020600482015260146024820152735a65726f206d4173736574207175616e7469747960601b60448201526064016105ab565b50505050979650505050505050565b60008060006118e28761232f565b9150915060006118f783838760200151612443565b905060006305f5e100898960ff168151811061192357634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b0316886119439190614532565b61194d91906143e1565b9050620f424081116119985760405162461bcd60e51b81526020600482015260146024820152734d75737420616464203e2031653620756e69747360601b60448201526064016105ab565b80848960ff16815181106119bc57634e487b7160e01b600052603260045260246000fd5b602002602001018181516119d091906143a3565b9052506119dd81846143a3565b92506119ee84848860400151612918565b611a0a5760405162461bcd60e51b81526004016105ab90614269565b611a16848484896129c2565b9998505050505050505050565b600080600080611a328a61232f565b915091506000611a4783838860200151612443565b905060006305f5e1008c8c60ff1681518110611a7357634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b03168a611a939190614532565b611a9d91906143e1565b9050620f42408111611ae85760405162461bcd60e51b81526020600482015260146024820152734d75737420616464203e2031653620756e69747360601b60448201526064016105ab565b80848c60ff1681518110611b0c57634e487b7160e01b600052603260045260246000fd5b60200260200101818151611b2091906143a3565b905250611b2d81846143a3565b92506000611b4085858a60200151612443565b9050670de0b6b3a764000089611b568584614579565b611b609190614532565b611b6a91906143e1565b95506000611b89868a602001518e8a88611b8491906143a3565b612a30565b89519091508490611b9a9089614532565b611ba491906143e1565b96506000600182888f60ff1681518110611bce57634e487b7160e01b600052603260045260246000fd5b6020026020010151611be09190614579565b611bea9190614579565b90508e8d60ff1681518110611c0f57634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b0316816305f5e100611c349190614532565b611c3e91906143e1565b985080878e60ff1681518110611c6457634e487b7160e01b600052603260045260246000fd5b60200260200101818151611c789190614579565b905250611c858187614579565b9550611c9687878c60400151612918565b611cb25760405162461bcd60e51b81526004016105ab90614269565b50505050505050965096945050505050565b600080611cd76060870160408801613e5a565b15611d1057611d0688611cef368a90038a018a613ee3565b611cfe368a90038a018a613e92565b888888612ddd565b9092509050611e35565b600088600501600081548110611d3657634e487b7160e01b600052603260045260246000fd5b60009182526020909120600290910201546001600160a01b03169050611d9989611d65368b90038b018b613ee3565b6040518060600160405280600060ff168152602001856001600160a01b031681526020016001151581525089600030612ddd565b90935091506001600160a01b0381166343bcfab6611dbd60408a0160208b01613c28565b8588886040518563ffffffff1660e01b8152600401611ddf949392919061420b565b602060405180830381600087803b158015611df957600080fd5b505af1158015611e0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3191906141bd565b9250505b965096945050505050565b611e486139d4565b826040015115611f9e57600086600501846000015160ff1681548110611e7e57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115611efc57634e487b7160e01b600052602160045260246000fd5b6007811115611f1b57634e487b7160e01b600052602160045260246000fd5b8152505090506000611f778287876000015160ff1681518110611f4e57634e487b7160e01b600052603260045260246000fd5b6020026020010151600001516001600160801b031686611f728c8c600001516125b2565b612bc1565b60408051606081018252875160ff168152602081019290925281019290925250905061200d565b611fb7868484611fb28a8a600001516125b2565b6130c3565b9050600081602001511161200d5760405162461bcd60e51b815260206004820152601b60248201527f4d757374206d696e7420736f6d657468696e672066726f6d206d70000000000060448201526064016105ab565b61201a81602001516128ab565b84826000015160ff168151811061204157634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516120579190614378565b86600601826000015160ff168154811061208157634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b02921691909117905595945050505050565b83518351602086015160009283926120df928a92919060ff8216156120d6578d546120d9565b60005b8d611a23565b9092509050838210156121345760405162461bcd60e51b815260206004820152601860248201527f4f757470757420717479203c206d696e696d756d20717479000000000000000060448201526064016105ab565b6000821161217b5760405162461bcd60e51b81526020600482015260146024820152735a65726f206f7574707574207175616e7469747960601b60448201526064016105ab565b61228b828a600501876000015160ff16815481106121a957634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b90910416600781111561222757634e487b7160e01b600052602160045260246000fd5b600781111561224657634e487b7160e01b600052602160045260246000fd5b90525087518a518b9160ff1690811061226f57634e487b7160e01b600052603260045260246000fd5b6020026020010151866122868e8e600001516125b2565b6125d7565b612294826128ab565b87866000015160ff16815181106122bb57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516122d19190614551565b89600601866000015160ff16815481106122fb57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055909890975095505050505050565b8051606090600090806001600160401b0381111561235d57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612386578160200160208202803683370190505b5092506000805b8281101561243b5760008682815181106123b757634e487b7160e01b600052603260045260246000fd5b602002602001015190506305f5e100816000015182602001516123da919061450c565b6123e491906143bb565b6001600160801b031692508286838151811061241057634e487b7160e01b600052603260045260246000fd5b602090810291909101015261242583866143a3565b9450508080612433906145bc565b91505061238d565b505050915091565b60008261245257506000612596565b60008460018151811061247557634e487b7160e01b600052603260045260246000fd5b60200260200101518560008151811061249e57634e487b7160e01b600052603260045260246000fd5b60200260200101516124b09190614532565b905060006064866001815181106124d757634e487b7160e01b600052603260045260246000fd5b60200260200101518760008151811061250057634e487b7160e01b600052603260045260246000fd5b602002602001015161251291906143a3565b61251c8487614532565b61252691906143e1565b61253091906143e1565b90508061257160648461254382896143a3565b61254d9190614532565b61255791906143e1565b61256260028561443b565b61256c91906143a3565b61346c565b61257b9190614579565b612586906002614532565b6125919060016143a3565b925050505b9392505050565b60006125968383670de0b6b3a76400006135eb565b6000670de0b6b3a76400008360040154836125cd9190614532565b61259691906143e1565b846125e1576128a4565b60208401516001600160a01b0316612624576001600160a01b038216301415612609576128a4565b835161261f906001600160a01b03168387613602565b6128a4565b8360400151156126b2576020840151845160405163c89fc72f60e01b81526001600160a01b038581166004830152918216602482015260448101889052606481018890526001608482015291169063c89fc72f9060a401600060405180830381600087803b15801561269557600080fd5b505af11580156126a9573d6000803e3d6000fd5b505050506128a4565b835160208501516040516370a0823160e01b81526001600160a01b03918216600482015260009291909116906370a082319060240160206040518083038186803b1580156126ff57600080fd5b505afa158015612713573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273791906141bd565b90508581106127b6576020850151855160405163a4e2859560e01b81526001600160a01b03868116600483015291821660248201526044810189905291169063a4e2859590606401600060405180830381600087803b15801561279957600080fd5b505af11580156127ad573d6000803e3d6000fd5b505050506128a2565b83516000906002906127d29085906001600160801b031661366a565b6127dc91906143e1565b9050600061281e836127ee8a856143a3565b6127f89190614579565b612801856128ab565b88602001516128109190614551565b6001600160801b031661367b565b6020880151885160405163c89fc72f60e01b81526001600160a01b0389811660048301529182166024820152604481018c90526064810184905260006084820152929350169063c89fc72f9060a401600060405180830381600087803b15801561288757600080fd5b505af115801561289b573d6000803e3d6000fd5b5050505050505b505b5050505050565b6000600160801b82106129105760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b60648201526084016105ab565b50805b919050565b82516001906000805b828110156129b8578587828151811061294a57634e487b7160e01b600052603260045260246000fd5b6020026020010151670de0b6b3a76400006129659190614532565b61296f91906143e1565b915084602001516001600160801b0316821180612995575084516001600160801b031682105b156129a65760009350505050612596565b806129b0816145bc565b915050612921565b5050509392505050565b6000806129d486868560200151612443565b83519091506129ee576129e78482614579565b9150612a12565b836129f98183614579565b8451612a059190614532565b612a0f91906143e1565b91505b50949350505050565b6000816125cd670de0b6b3a764000085614532565b600060ff83161580612a4557508260ff166001145b612a815760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b60448201526064016105ab565b600060ff841615612aba5785600081518110612aad57634e487b7160e01b600052603260045260246000fd5b6020026020010151612ae4565b85600181518110612adb57634e487b7160e01b600052603260045260246000fd5b60200260200101515b90506000612af36064876143a3565b90506000816064612b0560028861443b565b612b0f9190614532565b612b1991906143e1565b9050600082612b288988614532565b612b3291906143e1565b612b3d856004614532565b612b4790846143e1565b612b5191906143a3565b9050600084821015612b6c57612b678286614579565b612b76565b612b768583614579565b905060028583612b8a86612562858761443b565b612b9491906143a3565b612b9e9190614579565b612ba891906143e1565b612bb39060016143a3565b9a9950505050505050505050565b60208401516000906001600160a01b0316612bf2576000612be83330886000015187613690565b509150612dd59050565b6000612c08338760200151886000015187613690565b6040880151919350915015612cc157602086015186516040516307dba22560e31b81526001600160a01b03918216600482015260248101859052600160448201526000929190911690633edd112890606401602060405180830381600087803b158015612c7457600080fd5b505af1158015612c88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cac91906141bd565b9050612cb8818461367b565b92505050612dd5565b838214612d105760405162461bcd60e51b815260206004820152601b60248201527f4173736574206e6f742066756c6c79207472616e73666572726564000000000060448201526064016105ab565b6000612d1c848761366a565b905080821115612dd2576000612d336002836143e1565b612d3d9084614579565b602089015189516040516307dba22560e31b81526001600160a01b03918216600482015260248101849052600060448201529293501690633edd112890606401602060405180830381600087803b158015612d9757600080fd5b505af1158015612dab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dcf91906141bd565b50505b50505b949350505050565b600080600088600601805480602002602001604051908101604052809291908181526020016000905b82821015612e4f57600084815260209081902060408051808201909152908401546001600160801b038082168352600160801b9091041681830152825260019092019101612e06565b505050509050612e6c89600101548761259d90919063ffffffff16565b8751909250612e87908290612e81858a614579565b8b6112cb565b925084831015612ed05760405162461bcd60e51b815260206004820152601460248201527362417373657420717479203c206d696e2071747960601b60448201526064016105ab565b60008311612f0e5760405162461bcd60e51b815260206004820152600b60248201526a04f7574707574203d3d20360ac1b60448201526064016105ab565b61301f838a600501896000015160ff1681548110612f3c57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b909104166007811115612fba57634e487b7160e01b600052602160045260246000fd5b6007811115612fd957634e487b7160e01b600052602160045260246000fd5b90525089518451859160ff1690811061300257634e487b7160e01b600052603260045260246000fd5b6020026020010151876122868e8c8f600001516105ee9190614579565b613028836128ab565b81886000015160ff168151811061304f57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516130659190614551565b89600601886000015160ff168154811061308f57634e487b7160e01b600052603260045260246000fd5b600091825260209091200180546001600160801b03928316600160801b029216919091179055509097909650945050505050565b6130cb6139d4565b6040518060600160405280600060ff168152602001600081526020018660050160008154811061310b57634e487b7160e01b600052603260045260246000fd5b600091825260209182902060408051608081018252600290930290910180546001600160a01b03908116845260018201549081169484019490945260ff600160a01b8504811615159284019290925291926060840191600160a81b90910416600781111561318957634e487b7160e01b600052602160045260246000fd5b60078111156131a857634e487b7160e01b600052602160045260246000fd5b905250905260208501519091506131ca906001600160a01b03163330866137b9565b6040810151602001516000906001600160a01b0316156131f2578160400151602001516131f4565b305b6040808401515190516370a0823160e01b81526001600160a01b038084166004830152929350600092909116906370a082319060240160206040518083038186803b15801561324257600080fd5b505afa158015613256573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327a91906141bd565b6040808501515160208901519151637ba5ff4760e11b81529293506001600160a01b03169163f74bfe8e916132b8918990600090889060040161420b565b602060405180830381600087803b1580156132d257600080fd5b505af11580156132e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330a91906141bd565b506040838101515190516370a0823160e01b81526001600160a01b03848116600483015260009216906370a082319060240160206040518083038186803b15801561335457600080fd5b505afa158015613368573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061338c91906141bd565b90506133988282614579565b60208501526001600160a01b038316301461346157848111156134615760006133c26002876143e1565b6133cc9083614579565b6040868101515190516307dba22560e31b81526001600160a01b0391821660048201526024810183905260006044820152919250851690633edd112890606401602060405180830381600087803b15801561342657600080fd5b505af115801561343a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061345e91906141bd565b50505b505050949350505050565b60008161347b57506000612913565b816001600160801b82106134945760809190911c9060401b5b6801000000000000000082106134af5760409190911c9060201b5b64010000000082106134c65760209190911c9060101b5b6201000082106134db5760109190911c9060081b5b61010082106134ef5760089190911c9060041b5b601082106135025760049190911c9060021b5b6008821061350e5760011b5b600161351a82866143e1565b61352490836143a3565b901c9050600161353482866143e1565b61353e90836143a3565b901c9050600161354e82866143e1565b61355890836143a3565b901c9050600161356882866143e1565b61357290836143a3565b901c9050600161358282866143e1565b61358c90836143a3565b901c9050600161359c82866143e1565b6135a690836143a3565b901c905060016135b682866143e1565b6135c090836143a3565b901c905060006135d082866143e1565b90508082106135df57806135e1565b815b9350505050612913565b6000816135f88486614532565b612dd591906143e1565b6040516001600160a01b03831660248201526044810182905261366590849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526137f7565b505050565b6000816125cd6305f5e10085614532565b600081831161368a5782612596565b50919050565b6040516370a0823160e01b81526001600160a01b03848116600483015260009182918291908616906370a082319060240160206040518083038186803b1580156136d957600080fd5b505afa1580156136ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371191906141bd565b90506137286001600160a01b0386168888876137b9565b6040516370a0823160e01b81526001600160a01b0387811660048301528616906370a082319060240160206040518083038186803b15801561376957600080fd5b505afa15801561377d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137a191906141bd565b91506137ad8183614579565b92505094509492505050565b6040516001600160a01b03808516602483015283166044820152606481018290526137f19085906323b872dd60e01b9060840161362e565b50505050565b600061384c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166138c99092919063ffffffff16565b805190915015613665578080602001905181019061386a9190613e76565b6136655760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016105ab565b6060612dd5848460008585843b6139225760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105ab565b600080866001600160a01b0316858760405161393e91906141ef565b60006040518083038185875af1925050503d806000811461397b576040519150601f19603f3d011682016040523d82523d6000602084013e613980565b606091505b509150915061399082828661399b565b979650505050505050565b606083156139aa575081612596565b8251156139ba5782518084602001fd5b8160405162461bcd60e51b81526004016105ab9190614236565b60408051606081018252600080825260208201529081016139f36139f8565b905290565b604080516080810182526000808252602082018190529181018290529060608201906139f3565b80356001600160a01b038116811461291357600080fd5b600082601f830112613a46578081fd5b81356020613a5b613a5683614355565b614325565b82815281810190858301604080860288018501891015613a79578687fd5b865b86811015613a9f57613a8d8a84613b6d565b85529385019391810191600101613a7b565b509198975050505050505050565b60008083601f840112613abe578182fd5b5081356001600160401b03811115613ad4578182fd5b6020830191508360208083028501011115613aee57600080fd5b9250929050565b600082601f830112613b05578081fd5b81356020613b15613a5683614355565b8281528181019085830183850287018401881015613b31578586fd5b855b85811015613b4f57813584529284019290840190600101613b33565b5090979650505050505050565b60006060828403121561368a578081fd5b600060408284031215613b7e578081fd5b613b886040614325565b9050613b9382613c00565b8152613ba160208301613c00565b602082015292915050565b60006080828403121561368a578081fd5b600060808284031215613bce578081fd5b613bd86060614325565b90508135815260208201356020820152613bf58360408401613b6d565b604082015292915050565b80356001600160801b038116811461291357600080fd5b803560ff8116811461291357600080fd5b600060208284031215613c39578081fd5b61259682613a1f565b60008060008060e08587031215613c57578283fd5b84356001600160401b0380821115613c6d578485fd5b613c7988838901613a36565b9550602091508187013581811115613c8f578586fd5b8701601f81018913613c9f578586fd5b8035613cad613a5682614355565b81815284810190838601868402850187018d1015613cc957898afd5b8994505b83851015613cf257613cde81613c17565b835260019490940193918601918601613ccd565b5097505050506040870135915080821115613d0b578384fd5b50613d1887828801613af5565b925050613d288660608701613bbd565b905092959194509250565b60008060a08385031215613d45578182fd5b82356001600160401b03811115613d5a578283fd5b613d6685828601613a36565b925050613d768460208501613bbd565b90509250929050565b60008060008060e08587031215613d94578182fd5b84356001600160401b03811115613da9578283fd5b613db587828801613a36565b945050613dc460208601613c17565b925060408501359150613d288660608701613bbd565b6000806000806000806101208789031215613df3578384fd5b86356001600160401b03811115613e08578485fd5b613e1489828a01613a36565b965050613e2360208801613c17565b9450613e3160408801613c17565b93506060870135925060808701359150613e4e8860a08901613bbd565b90509295509295509295565b600060208284031215613e6b578081fd5b813561259681614619565b600060208284031215613e87578081fd5b815161259681614619565b600060608284031215613ea3578081fd5b613ead6060614325565b613eb683613c17565b8152613ec460208401613a1f565b60208201526040830135613ed781614619565b60408201529392505050565b600060808284031215613ef4578081fd5b6125968383613bbd565b6000806000806000806000610100888a031215613f19578485fd5b87359650613f2a8960208a01613bac565b955060a08801356001600160401b0380821115613f45578687fd5b613f518b838c01613aad565b909750955060c08a0135915080821115613f69578283fd5b50613f768a828b01613aad565b989b979a5095989497959660e090950135949350505050565b60008060008060008060006101c0888a031215613faa578081fd5b87359650613fbb8960208a01613bac565b9550613fca8960a08a01613b5c565b9450613fda896101008a01613b5c565b935061016088013592506101808801359150613ff96101a08901613a1f565b905092959891949750929550565b6000806000806000610140868803121561401f578283fd5b853594506140308760208801613bac565b935061403f8760a08801613b5c565b949793965093946101008101359450610120013592915050565b6000806000806000806101608789031215614072578384fd5b863595506140838860208901613bac565b94506140928860a08901613b5c565b935061010087013592506101208701359150613e4e6101408801613a1f565b60008060008060008061010087890312156140ca578384fd5b863595506140db8860208901613bac565b945060a0870135935060c08701356001600160401b038111156140fc578283fd5b61410889828a01613aad565b9094509250613e4e905060e08801613a1f565b600080600080600080600080610120898b031215614137578182fd5b883597506141488a60208b01613bbd565b965060a08901356001600160401b0380821115614163578384fd5b61416f8c838d01613aad565b909850965060c08b0135915080821115614187578384fd5b506141948b828c01613aad565b90955093505060e089013591506141ae6101008a01613a1f565b90509295985092959890939650565b6000602082840312156141ce578081fd5b5051919050565b6000602082840312156141e6578081fd5b61259682613c17565b60008251614201818460208701614590565b9190910192915050565b6001600160a01b03948516815260208101939093526040830191909152909116606082015260800190565b6000602082528251806020840152614255816040850160208701614590565b601f01601f19169190910160400192915050565b6020808252601590820152744578636565647320776569676874206c696d69747360581b604082015260600190565b60006060820185835260206060818501528186518084526080860191508288019350845b818110156142e15784516001600160a01b0316835293830193918301916001016142bc565b505084810360408601528551808252908201925081860190845b81811015614317578251855293830193918301916001016142fb565b509298975050505050505050565b604051601f8201601f191681016001600160401b038111828210171561434d5761434d614603565b604052919050565b60006001600160401b0382111561436e5761436e614603565b5060209081020190565b60006001600160801b0380831681851680830382111561439a5761439a6145d7565b01949350505050565b600082198211156143b6576143b66145d7565b500190565b60006001600160801b03808416806143d5576143d56145ed565b92169190910492915050565b6000826143f0576143f06145ed565b500490565b80825b60018086116144075750614432565b818704821115614419576144196145d7565b8086161561442657918102915b9490941c9380026143f8565b94509492505050565b600061259660001960ff85168460008261445757506001612596565b8161446457506000612596565b816001811461447a5760028114614484576144b1565b6001915050612596565b60ff841115614495576144956145d7565b6001841b9150848211156144ab576144ab6145d7565b50612596565b5060208310610133831016604e8410600b84101617156144e4575081810a838111156144df576144df6145d7565b612596565b6144f184848460016143f5565b808604821115614503576145036145d7565b02949350505050565b60006001600160801b0380831681851681830481118215151615614503576145036145d7565b600081600019048311821515161561454c5761454c6145d7565b500290565b60006001600160801b0383811690831681811015614571576145716145d7565b039392505050565b60008282101561458b5761458b6145d7565b500390565b60005b838110156145ab578181015183820152602001614593565b838111156137f15750506000910152565b60006000198214156145d0576145d06145d7565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461462757600080fd5b5056fea2646970667358221220e7ba85f0b708b8abff3092672d9a78fa4f5bfad0b48efb112edf3021161eae9a64736f6c63430008020033
Deployed Bytecode Sourcemap
36452:37885:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41221:1634;;;;;;;;;;-1:-1:-1;41221:1634:0;;;;;:::i;:::-;;:::i;:::-;;;;25678:25:1;;;25734:2;25719:18;;25712:34;;;;25651:18;41221:1634:0;;;;;;;;69381:327;;;;;;:::i;:::-;;:::i;37339:694::-;;;;;;;;;;-1:-1:-1;37339:694:0;;;;;:::i;:::-;;:::i;:::-;;;24193:25:1;;;24181:2;24166:18;37339:694:0;24148:76:1;45791:1898:0;;;;;;;;;;-1:-1:-1;45791:1898:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;62942:975::-;;;;;;:::i;:::-;;:::i;67934:1139::-;;;;;;:::i;:::-;;:::i;48576:1585::-;;;;;;;;;;-1:-1:-1;48576:1585:0;;;;;:::i;:::-;;:::i;66490:984::-;;;;;;:::i;:::-;;:::i;38751:1523::-;;;;;;;;;;-1:-1:-1;38751:1523:0;;;;;:::i;:::-;;:::i;61675:817::-;;;;;;:::i;:::-;;:::i;64589:1424::-;;;;;;:::i;:::-;;:::i;43852:1116::-;;;;;;;;;;-1:-1:-1;43852:1116:0;;;;;:::i;:::-;;:::i;41221:1634::-;41499:18;41519:16;41548:36;41587:5;:16;;41548:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;41548:55:0;;;;;-1:-1:-1;;;41548:55:0;;;;;;;;;;;;;;;;;;;;;;;;;41616:26;41658:69;41670:5;41677:7;41658:69;;;;;;;;;;:::i;:::-;41686:16;41658:69;;;;;;;41704:6;41658:69;:::i;:::-;41712:14;41658:11;:69::i;:::-;41616:111;-1:-1:-1;41918:14:0;;;;;;;;:::i;:::-;41914:934;;;41974:230;42003:5;41974:230;;;;;;;42027:7;41974:230;:::i;:::-;42053:16;42088:9;41974:230;;;;;;;42116:7;41974:230;:::i;:::-;42142:18;42179:10;41974;:230::i;:::-;41949:255;;-1:-1:-1;41949:255:0;-1:-1:-1;41914:934:0;;;42329:14;42346:5;:20;;42367:1;42346:23;;;;;;-1:-1:-1;;;42346:23:0;;;;;;;;;;;;;;;;;;;;;;:28;-1:-1:-1;;;;;42346:28:0;;-1:-1:-1;42414:231:0;42443:5;42414:231;;;;;;;42467:7;42414:231;:::i;:::-;42493:16;42528:9;42556:22;;;;;;;;42562:1;42556:22;;;;;;42565:6;-1:-1:-1;;;;;42556:22:0;;;;;42573:4;42556:22;;;;;42597:1;42625:4;42414:10;:231::i;:::-;42389:256;;-1:-1:-1;42389:256:0;-1:-1:-1;;;;;;42673:22:0;;;42714:12;;;;;;;;:::i;:::-;42745:10;42774:18;42811:10;42673:163;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;42660:176;;41914:934;;41221:1634;;;;;;;;;;;;:::o;69381:327::-;69510:13;69525:9;69553:18;69573:11;69588:22;69601:8;69588:12;:22::i;:::-;69552:58;;;;69625:29;69636:1;69639:3;69644:7;:9;;;69625:10;:29::i;:::-;69686:14;;69621:33;;-1:-1:-1;69674:8:0;69621:33;69674:4;:8;:::i;:::-;69673:27;;;;:::i;:::-;69665:35;;69381:327;;;;;;;:::o;37339:694::-;37555:18;37586:36;37625:5;:16;;37586:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;37586:55:0;;;;;-1:-1:-1;;;37586:55:0;;;;;;;;;;;;;;;;;;;;;;;;;37652:26;37694:69;37706:5;37713:7;37694:69;;;;;;;;;;:::i;:::-;37722:16;37694:69;;;;;;;37740:6;37694:69;:::i;:::-;37748:14;37694:11;:69::i;:::-;37652:111;;37878:68;37890:16;37908:9;:13;;;37923:9;:13;;;37938:7;37878:68;;;;;;;;;;:::i;:::-;37865:81;;37979:18;37965:10;:32;;37957:68;;;;-1:-1:-1;;;37957:68:0;;17746:2:1;37957:68:0;;;17728:21:1;17785:2;17765:18;;;17758:30;-1:-1:-1;;;17804:18:1;;;17797:53;17867:18;;37957:68:0;;;;;;;;;37339:694;;;;;;;;;:::o;45791:1898::-;46066:17;46098:24;46137:33;46261:47;46288:5;:19;;;46261:14;:26;;:47;;;;:::i;:::-;46249:59;-1:-1:-1;46377:16:0;46396:56;46413:5;46420:31;46437:14;46420;;:31;:::i;:::-;46396:16;:56::i;:::-;46377:75;;46523:30;46556:5;:16;;46523:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;46523:49:0;;;;;-1:-1:-1;;;46523:49:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;46597:17:0;;46523:49;;-1:-1:-1;46597:17:0;;-1:-1:-1;;;;;;;46635:18:0;;;;;-1:-1:-1;;;46635:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46635:18:0;;46625:28;;46697:3;-1:-1:-1;;;;;46683:18:0;;;;;-1:-1:-1;;;46683:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46683:18:0;;46664:37;;46717:9;46712:970;46736:3;46732:1;:7;46712:970;;;46830:17;46929:14;;46898:26;46915:9;46898:14;:26;:::i;:::-;46868:10;46879:1;46868:13;;;;;;-1:-1:-1;;;46868:13:0;;;;;;;;;;;;;;;:26;;;-1:-1:-1;;;;;46868:57:0;;;;;:::i;:::-;46867:76;;;;:::i;:::-;46830:113;;46978:1;46966:9;:13;46958:37;;;;-1:-1:-1;;;46958:37:0;;20313:2:1;46958:37:0;;;20295:21:1;20352:2;20332:18;;;20325:30;-1:-1:-1;;;20371:18:1;;;20364:41;20422:18;;46958:37:0;20285:161:1;46958:37:0;47010:14;47023:1;47010:14;;:::i;:::-;;;47060:20;;47081:1;47060:23;;;;;-1:-1:-1;;;47060:23:0;;;;;;;;;;;;;;;47047:9;:36;;47039:69;;;;-1:-1:-1;;;47039:69:0;;18440:2:1;47039:69:0;;;18422:21:1;18479:2;18459:18;;;18452:30;-1:-1:-1;;;18498:18:1;;;18491:50;18558:18;;47039:69:0;18412:170:1;47039:69:0;47196:9;47207:5;:20;;47228:1;47207:23;;;;;;-1:-1:-1;;;47207:23:0;;;;;;;;;;;;;;;;;;;;;;:28;47160:19;;-1:-1:-1;;;;;47207:28:0;;;;47160:16;;47177:1;;47160:19;;;;-1:-1:-1;;;47160:19:0;;;;;;;;;;;;;;47181:7;47189:1;47181:10;;;;;;-1:-1:-1;;;47181:10:0;;;;;;;;;;;;;;47159:77;-1:-1:-1;;;;;47159:77:0;-1:-1:-1;;;;;47159:77:0;;;;;;;;;;47304:188;47338:9;47366:5;:20;;47387:1;47366:23;;;;;;-1:-1:-1;;;47366:23:0;;;;;;;;;;;;;;;;;;47304:188;;;;;;;;47366:23;;;;;;;47304:188;;-1:-1:-1;;;;;47304:188:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;47304:188:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;47304:188:0;;;;;;;;;;-1:-1:-1;;;47304:188:0;;;;;;;;;;;;;;;-1:-1:-1;;;47304:188:0;;;;;;;;;;;;;47408:10;47419:1;47408:13;;;;;;-1:-1:-1;;;47408:13:0;;;;;;;;;;;;;;;47440:10;47469:8;47304:15;:188::i;:::-;47641:29;47660:9;47641:18;:29::i;:::-;47595:10;47606:1;47595:13;;;;;;-1:-1:-1;;;47595:13:0;;;;;;;;;;;;;;;:26;;;:75;;;;:::i;:::-;47543:5;:16;;47560:1;47543:19;;;;;;-1:-1:-1;;;47543:19:0;;;;;;;;;;;;;;;;;;:127;;-1:-1:-1;;;;;47543:127:0;;;-1:-1:-1;;;47543:127:0;;;;;;;;;-1:-1:-1;46741:3:0;;;;:::i;:::-;;;;46712:970;;;;45791:1898;;;;;;;;;;;;;:::o;62942:975::-;63145:18;63209;63229:11;63244:22;63257:8;63244:12;:22::i;:::-;63208:58;;;;63337:10;63350:29;63361:1;63364:3;63369:7;:9;;;63350:10;:29::i;:::-;63445:15;;63337:42;;-1:-1:-1;63431:11:0;;;63521:219;63545:3;63541:1;:7;63521:219;;;63576:8;63585:1;63576:11;;;;;;-1:-1:-1;;;63576:11:0;;;;;;;;;;;;;;;63570:17;;63656:3;63633:8;63642:3;63633:13;;;;;;;;-1:-1:-1;;;63633:13:0;;;;;;;;;;;;;;;:19;;;-1:-1:-1;;;;;63617:35:0;:10;63628:1;63617:13;;;;;;-1:-1:-1;;;63617:13:0;;;;;;;;;;;;;;;:35;;;;:::i;:::-;63616:43;;;;:::i;:::-;63602:57;;63684:11;63674:1;63676:3;63674:6;;;;;;;;-1:-1:-1;;;63674:6:0;;;;;;;;;;;;;;:21;;;;;;;:::i;:::-;;;-1:-1:-1;63710:18:0;63717:11;63710:18;;:::i;:::-;;-1:-1:-1;63550:3:0;;;;:::i;:::-;;;;63521:219;;;;63787:33;63797:1;63800:3;63805:7;:14;;;63787:9;:33::i;:::-;63779:67;;;;-1:-1:-1;;;63779:67:0;;;;;;;:::i;:::-;63870:39;63889:1;63892:3;63897:2;63901:7;63870:18;:39::i;:::-;63857:52;62942:975;-1:-1:-1;;;;;;;;;;;62942:975:0:o;67934:1139::-;68140:19;68205:18;68225:11;68240:22;68253:8;68240:12;:22::i;:::-;68204:58;;;;68333:10;68346:29;68357:1;68360:3;68365:7;:9;;;68346:10;:29::i;:::-;68443:15;;68333:42;;-1:-1:-1;68429:11:0;;68495:192;68519:3;68515:1;:7;68495:192;;;68603:3;68572:8;68581;68590:1;68581:11;;;;;;-1:-1:-1;;;68581:11:0;;;;;;;;;;;;;;;68572:21;;;;;;;;-1:-1:-1;;;68572:21:0;;;;;;;;;;;;;;;:27;;;-1:-1:-1;;;;;68555:44:0;:11;68567:1;68555:14;;;;;;-1:-1:-1;;;68555:14:0;;;;;;;;;;;;;;;:44;;;;:::i;:::-;68554:52;;;;:::i;:::-;68544:62;;68639:7;68621:1;68623:8;68632:1;68623:11;;;;;;-1:-1:-1;;;68623:11:0;;;;;;;;;;;;;;;68621:14;;;;;;;;-1:-1:-1;;;68621:14:0;;;;;;;;;;;;;;:25;;;;;;;:::i;:::-;;;-1:-1:-1;68661:14:0;68668:7;68661:14;;:::i;:::-;;-1:-1:-1;68524:3:0;;;;:::i;:::-;;;;68495:192;;;;68705:33;68715:1;68718:3;68723:7;:14;;;68705:9;:33::i;:::-;68697:67;;;;-1:-1:-1;;;68697:67:0;;;;;;;:::i;:::-;68839:10;68852:29;68863:1;68866:3;68871:7;:9;;;68852:10;:29::i;:::-;68839:42;-1:-1:-1;68999:2:0;68987:7;68839:42;68999:2;68987:7;:::i;:::-;68969:14;;:26;;;;:::i;:::-;68968:33;;;;:::i;:::-;68954:47;;69034:3;69020:11;:17;69012:53;;;;-1:-1:-1;;;69012:53:0;;20653:2:1;69012:53:0;;;20635:21:1;20692:2;20672:18;;;20665:30;-1:-1:-1;;;20711:18:1;;;20704:53;20774:18;;69012:53:0;20625:173:1;69012:53:0;67934:1139;;;;;;;;;;;;:::o;48576:1585::-;48850:23;48875:16;48956:30;48989:5;:16;;48956:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;48956:49:0;;;;;-1:-1:-1;;;48956:49:0;;;;;;;;;;;;;;;;;;;;;;;;;49050:23;49089:68;49108:10;49120:8;;49089:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;49089:68:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49130:17:0;;-1:-1:-1;49130:17:0;;;;49089:68;;;49130:17;;49089:68;49130:17;49089:68;;;;;;;;;;;;;;;;;;;;;;;;;;49149:7;49089:18;:68::i;:::-;49050:107;;49186:56;49222:5;:19;;;49215:4;:26;;;;:::i;:::-;49186:15;;:28;:56::i;:::-;49168:74;-1:-1:-1;49264:33:0;49282:15;49168:74;49264:33;:::i;:::-;49253:44;;49334:1;49316:15;:19;49308:56;;;;-1:-1:-1;;;49308:56:0;;23178:2:1;49308:56:0;;;23160:21:1;23217:2;23197:18;;;23190:30;23256:26;23236:18;;;23229:54;23300:18;;49308:56:0;23150:174:1;49308:56:0;49375:20;49394:1;49375:20;;:::i;:::-;;;49433:17;49414:15;:36;;49406:81;;;;-1:-1:-1;;;49406:81:0;;23880:2:1;49406:81:0;;;23862:21:1;;;23899:18;;;23892:30;23958:34;23938:18;;;23931:62;24010:18;;49406:81:0;23852:182:1;49406:81:0;49543:16;49562:57;49579:5;49603:15;49586:7;:14;;;:32;;;;:::i;49562:57::-;49543:76;;49685:9;49680:474;49700:28;;;49680:474;;;49750:219;49784:17;;49802:1;49784:20;;;;;-1:-1:-1;;;49784:20:0;;;;;;;;;;;;;;;49823:5;:20;;49844:8;;49853:1;49844:11;;;;;-1:-1:-1;;;49844:11:0;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49823:33;;;;;;;;-1:-1:-1;;;49823:33:0;;;;;;;;;;;;;;;;;;49750:219;;;;;;;;49823:33;;;;;;;49750:219;;-1:-1:-1;;;;;49750:219:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;49750:219:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;49750:219:0;;;;;;;;;;-1:-1:-1;;;49750:219:0;;;;;;;;;;;;;;;-1:-1:-1;;;49750:219:0;;;;;;;;;;;-1:-1:-1;49875:10:0;49886:8;;49895:1;49886:11;;;;;-1:-1:-1;;;49886:11:0;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49875:23;;;;;;;;-1:-1:-1;;;49875:23:0;;;;;;;;;;;;;;;49917:10;49946:8;49750:15;:219::i;:::-;50102:40;50121:17;;50139:1;50121:20;;;;;-1:-1:-1;;;50121:20:0;;;;;;;;;;;;;;;50102:18;:40::i;:::-;50046:10;50057:8;;50066:1;50057:11;;;;;-1:-1:-1;;;50057:11:0;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;50046:23;;;;;;;;-1:-1:-1;;;50046:23:0;;;;;;;;;;;;;;;:36;;;:96;;;;:::i;:::-;49984:5;:16;;50001:8;;50010:1;50001:11;;;;;-1:-1:-1;;;50001:11:0;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;49984:29;;;;;;;;-1:-1:-1;;;49984:29:0;;;;;;;;;;;;;;;;;;:158;;-1:-1:-1;;;;;49984:158:0;;;-1:-1:-1;;;49984:158:0;;;;;;;;;49730:3;;;;:::i;:::-;;;;49680:474;;;;48576:1585;;;;;;;;;;;;;;:::o;66490:984::-;66671:22;66732:3;66714:15;:21;66706:57;;;;-1:-1:-1;;;66706:57:0;;20653:2:1;66706:57:0;;;20635:21:1;20692:2;20672:18;;;20665:30;-1:-1:-1;;;20711:18:1;;;20704:53;20774:18;;66706:57:0;20625:173:1;66706:57:0;66807:18;66827:11;66842:22;66855:8;66842:12;:22::i;:::-;66806:58;;;;66935:10;66948:29;66959:1;66962:3;66967:7;:9;;;66948:10;:29::i;:::-;67049:14;;66935:42;;-1:-1:-1;66988:14:0;;67012:32;67029:15;67049:14;67012:32;:::i;:::-;67006:39;;:2;:39;:::i;:::-;67005:58;;;;:::i;:::-;:62;;67066:1;67005:62;:::i;:::-;66988:79;;67115:24;67142:41;67158:1;67161:7;:9;;;67172:2;67176:6;67142:15;:41::i;:::-;67115:68;;67194:14;67238:1;67219:16;67211:1;67213:2;67211:5;;;;;;;;-1:-1:-1;;;67211:5:0;;;;;;;;;;;;;;;:24;;;;:::i;:::-;:28;;;;:::i;:::-;67194:45;;67284:8;67293:2;67284:12;;;;;;;;-1:-1:-1;;;67284:12:0;;;;;;;;;;;;;;;:18;;;-1:-1:-1;;;;;67267:35:0;67268:6;67277:3;67268:12;;;;:::i;:::-;67267:35;;;;:::i;:::-;67250:52;;67358:6;67349:1;67351:2;67349:5;;;;;;;;-1:-1:-1;;;67349:5:0;;;;;;;;;;;;;;:15;;;;;;;:::i;:::-;;;-1:-1:-1;67375:13:0;67382:6;67375:13;;:::i;:::-;;;67407:33;67417:1;67420:3;67425:7;:14;;;67407:9;:33::i;:::-;67399:67;;;;-1:-1:-1;;;67399:67:0;;;;;;;:::i;38751:1523::-;38989:18;39034:8;38989:18;39034:8;-1:-1:-1;;;;;39099:18:0;;;;;-1:-1:-1;;;39099:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;39099:18:0;;39060:57;;39178:30;39211:5;:16;;39178:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;39178:49:0;;;;;-1:-1:-1;;;39178:49:0;;;;;;;;;;;;;;;;;;;;;;;;;39238:16;39257:39;39274:5;39281:7;:14;;;39257:16;:39::i;:::-;39238:58;;39380:9;39375:602;39399:3;39395:1;:7;39375:602;;;39450:1;39428:16;;39445:1;39428:19;;;;;-1:-1:-1;;;39428:19:0;;;;;;;;;;;;;;;:23;39424:542;;;39472:9;39484:8;;39493:1;39484:11;;;;;-1:-1:-1;;;39484:11:0;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;39472:23;;39514;39540:10;39551:3;39540:15;;;;;;;;-1:-1:-1;;;39540:15:0;;;;;;;;;;;;;;;39514:41;;39599:188;39636:5;:20;;39657:3;39636:25;;;;;;;;-1:-1:-1;;;39636:25:0;;;;;;;;;;;;;;;;;;39599:188;;;;;;;;39636:25;;;;;;;39599:188;;-1:-1:-1;;;;;39599:188:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;39599:188:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;39599:188:0;;;;;;;;;;-1:-1:-1;;;39599:188:0;;;;;;;;;;;;;;;-1:-1:-1;;;39599:188:0;;;;;;;;;;;-1:-1:-1;39684:11:0;;-1:-1:-1;;;;;39599:188:0;39718:16;;39735:1;39718:19;;;;;-1:-1:-1;;;39718:19:0;;;;;;;;;;;;;;;39760:8;39599:14;:188::i;:::-;39574:19;39594:1;39574:22;;;;;;-1:-1:-1;;;39574:22:0;;;;;;;;;;;;;;:213;;;;;39908:42;39927:19;39947:1;39927:22;;;;;;-1:-1:-1;;;39927:22:0;;;;;;;;;;;;;;;39908:18;:42::i;:::-;39866:5;:18;;;:84;;;;:::i;:::-;39808:5;:16;;39825:3;39808:21;;;;;;;;-1:-1:-1;;;39808:21:0;;;;;;;;;;;;;;;;;;:142;;-1:-1:-1;;;;;39808:142:0;;;-1:-1:-1;;;39808:142:0;;;;;;;;;-1:-1:-1;;39424:542:0;39404:3;;;;:::i;:::-;;;;39375:602;;;;40061:68;40078:10;40090:8;;40061:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40100:19;40121:7;40061:68;;;;;;;;;;:::i;:::-;40048:81;;40162:18;40148:10;:32;;40140:68;;;;-1:-1:-1;;;40140:68:0;;17746:2:1;40140:68:0;;;17728:21:1;17785:2;17765:18;;;17758:30;-1:-1:-1;;;17804:18:1;;;17797:53;17867:18;;40140:68:0;17718:173:1;40140:68:0;40240:1;40227:10;:14;40219:47;;;;-1:-1:-1;;;40219:47:0;;21005:2:1;40219:47:0;;;20987:21:1;21044:2;21024:18;;;21017:30;-1:-1:-1;;;21063:18:1;;;21056:50;21123:18;;40219:47:0;20977:170:1;40219:47:0;38751:1523;;;;;;;;;;;;;:::o;61675:817::-;61848:18;61912;61932:11;61947:22;61960:8;61947:12;:22::i;:::-;61911:58;;;;62040:10;62053:29;62064:1;62067:3;62072:7;:9;;;62053:10;:29::i;:::-;62040:42;;62093:19;62150:3;62128:8;62137:2;62128:12;;;;;;;;-1:-1:-1;;;62128:12:0;;;;;;;;;;;;;;;:18;;;-1:-1:-1;;;;;62116:30:0;:9;:30;;;;:::i;:::-;62115:38;;;;:::i;:::-;62093:60;;62186:3;62172:11;:17;62164:50;;;;-1:-1:-1;;;62164:50:0;;23531:2:1;62164:50:0;;;23513:21:1;23570:2;23550:18;;;23543:30;-1:-1:-1;;;23589:18:1;;;23582:50;23649:18;;62164:50:0;23503:170:1;62164:50:0;62274:11;62265:1;62267:2;62265:5;;;;;;;;-1:-1:-1;;;62265:5:0;;;;;;;;;;;;;;:20;;;;;;;:::i;:::-;;;-1:-1:-1;62296:18:0;62303:11;62296:18;;:::i;:::-;;;62362:33;62372:1;62375:3;62380:7;:14;;;62362:9;:33::i;:::-;62354:67;;;;-1:-1:-1;;;62354:67:0;;;;;;;:::i;:::-;62445:39;62464:1;62467:3;62472:2;62476:7;62445:18;:39::i;:::-;62432:52;61675:817;-1:-1:-1;;;;;;;;;61675:817:0:o;64589:1424::-;64808:28;64838:21;64905:18;64925:11;64940:22;64953:8;64940:12;:22::i;:::-;64904:58;;;;65033:10;65046:29;65057:1;65060:3;65065:7;:9;;;65046:10;:29::i;:::-;65033:42;;65127:19;65184:3;65162:8;65171:2;65162:12;;;;;;;;-1:-1:-1;;;65162:12:0;;;;;;;;;;;;;;;:18;;;-1:-1:-1;;;;;65150:30:0;:9;:30;;;;:::i;:::-;65149:38;;;;:::i;:::-;65127:60;;65220:3;65206:11;:17;65198:50;;;;-1:-1:-1;;;65198:50:0;;23531:2:1;65198:50:0;;;23513:21:1;23570:2;23550:18;;;23543:30;-1:-1:-1;;;23589:18:1;;;23582:50;23649:18;;65198:50:0;23503:170:1;65198:50:0;65268:11;65259:1;65261:2;65259:5;;;;;;;;-1:-1:-1;;;65259:5:0;;;;;;;;;;;;;;:20;;;;;;;:::i;:::-;;;-1:-1:-1;65290:18:0;65297:11;65290:18;;:::i;:::-;;;65355:10;65368:29;65379:1;65382:3;65387:7;:9;;;65368:10;:29::i;:::-;65355:42;-1:-1:-1;65449:4:0;65437:8;65426:7;65431:2;65355:42;65426:7;:::i;:::-;65425:20;;;;:::i;:::-;65424:29;;;;:::i;:::-;65408:45;;65498:24;65525:53;65541:1;65544:7;:9;;;65555:2;65564:13;65559:2;:18;;;;:::i;:::-;65525:15;:53::i;:::-;65700:14;;65498:80;;-1:-1:-1;65718:2:0;;65684:30;;:13;:30;:::i;:::-;65683:37;;;;:::i;:::-;65667:53;;65731:14;65775:1;65756:16;65748:1;65750:2;65748:5;;;;;;;;-1:-1:-1;;;65748:5:0;;;;;;;;;;;;;;;:24;;;;:::i;:::-;:28;;;;:::i;:::-;65731:45;;65827:8;65836:2;65827:12;;;;;;;;-1:-1:-1;;;65827:12:0;;;;;;;;;;;;;;;:18;;;-1:-1:-1;;;;;65810:35:0;65811:6;65820:3;65811:12;;;;:::i;:::-;65810:35;;;;:::i;:::-;65787:58;;65897:6;65888:1;65890:2;65888:5;;;;;;;;-1:-1:-1;;;65888:5:0;;;;;;;;;;;;;;:15;;;;;;;:::i;:::-;;;-1:-1:-1;65914:13:0;65921:6;65914:13;;:::i;:::-;;;65946:33;65956:1;65959:3;65964:7;:14;;;65946:9;:33::i;:::-;65938:67;;;;-1:-1:-1;;;65938:67:0;;;;;;;:::i;:::-;64589:1424;;;;;;;;;;;;;;;;:::o;43852:1116::-;44102:22;;44159:14;;;;;;;;:::i;:::-;44155:806;;;44219:204;44250:5;44219:204;;;;;;;44274:7;44219:204;:::i;:::-;;;;;;;;44300:7;44219:204;:::i;:::-;44326:16;44361:18;44398:10;44219:12;:204::i;:::-;44190:233;;-1:-1:-1;44190:233:0;-1:-1:-1;44155:806:0;;;44456:14;44473:5;:20;;44494:1;44473:23;;;;;;-1:-1:-1;;;44473:23:0;;;;;;;;;;;;;;;;;;;;;;:28;-1:-1:-1;;;;;44473:28:0;;-1:-1:-1;44545:205:0;44576:5;44545:205;;;;;;;44600:7;44545:205;:::i;:::-;44626:22;;;;;;;;44632:1;44626:22;;;;;;44635:6;-1:-1:-1;;;;;44626:22:0;;;;;44643:4;44626:22;;;;;44667:16;44702:1;44730:4;44545:12;:205::i;:::-;44516:234;;-1:-1:-1;44516:234:0;-1:-1:-1;;;;;;44782:22:0;;;44823:12;;;;;;;;:::i;:::-;44854:14;44887:18;44924:10;44782:167;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;44765:184;;44155:806;;43852:1116;;;;;;;;;:::o;50538:1238::-;50768:26;;:::i;:::-;50849:6;:13;;;50845:759;;;50879:30;50912:5;:20;;50933:6;:10;;;50912:32;;;;;;;;-1:-1:-1;;;50912:32:0;;;;;;;;;;;;;;;;;;50879:65;;;;;;;;50912:32;;;;;;;50879:65;;-1:-1:-1;;;;;50879:65:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;50879:65:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;50879:65:0;;;;;;;;;;-1:-1:-1;;;50879:65:0;;;;;;;;;;;;;;;-1:-1:-1;;;50879:65:0;;;;;;;;;;;;;;;50959:11;50990:221;51027:8;51058:17;51076:6;:10;;;51058:29;;;;;;;;-1:-1:-1;;;51058:29:0;;;;;;;;;;;;;;;:35;;;-1:-1:-1;;;;;50990:221:0;51116:14;51153:39;51170:5;51177:7;:14;;;51153:16;:39::i;:::-;50990:14;:221::i;:::-;51238:36;;;;;;;;51248:10;;51238:36;;;;;;;;;;;;;;;;;-1:-1:-1;51238:36:0;-1:-1:-1;50845:759:0;;;51358:162;51384:5;51408:6;51433:14;51466:39;51483:5;51490:7;:14;;;51466:16;:39::i;:::-;51358:7;:162::i;:::-;51346:174;;51559:1;51543:9;:13;;;:17;51535:57;;;;-1:-1:-1;;;51535:57:0;;21704:2:1;51535:57:0;;;21686:21:1;21743:2;21723:18;;;21716:30;21782:29;21762:18;;;21755:57;21829:18;;51535:57:0;21676:177:1;51535:57:0;51735:33;51754:9;:13;;;51735:18;:33::i;:::-;51674:17;51692:9;:13;;;51674:32;;;;;;;;-1:-1:-1;;;51674:32:0;;;;;;;;;;;;;;;:45;;;:94;;;;:::i;:::-;51614:5;:16;;51631:9;:13;;;51614:31;;;;;;;;-1:-1:-1;;;51614:31:0;;;;;;;;;;;;;;;;;;:154;;-1:-1:-1;;;;;51614:154:0;;;-1:-1:-1;;;51614:154:0;;;;;;;;;50538:1238;;-1:-1:-1;;;;;50538:1238:0:o;53449:1216::-;53914:14;;53943:11;;53969:14;;;;53750:18;;;;53856:211;;53882:17;;53914:14;53943:11;53998:16;;;;:36;;54021:13;;53998:36;;;54017:1;53998:36;54049:7;53856:11;:211::i;:::-;53830:237;;-1:-1:-1;53830:237:0;-1:-1:-1;54086:32:0;;;;54078:69;;;;-1:-1:-1;;;54078:69:0;;19197:2:1;54078:69:0;;;19179:21:1;19236:2;19216:18;;;19209:30;19275:26;19255:18;;;19248:54;19319:18;;54078:69:0;19169:174:1;54078:69:0;54179:1;54166:10;:14;54158:47;;;;-1:-1:-1;;;54158:47:0;;22829:2:1;54158:47:0;;;22811:21:1;22868:2;22848:18;;;22841:30;-1:-1:-1;;;22887:18:1;;;22880:50;22947:18;;54158:47:0;22801:170:1;54158:47:0;54244:223;54274:10;54299:5;:20;;54320:7;:11;;;54299:33;;;;;;;;-1:-1:-1;;;54299:33:0;;;;;;;;;;;;;;;;;;54244:223;;;;;;;;54299:33;;;;;;;54244:223;;-1:-1:-1;;;;;54244:223:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;54244:223:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;54244:223:0;;;;;;;;;;-1:-1:-1;;;54244:223:0;;;;;;;;;;;;;;;-1:-1:-1;;;54244:223:0;;;;;;;;;;;-1:-1:-1;54365:11:0;;54347:30;;:17;;:30;;;;;;;-1:-1:-1;;;54347:30:0;;;;;;;;;;;;;;;54392:10;54417:39;54434:5;54441:7;:14;;;54417:16;:39::i;:::-;54244:15;:223::i;:::-;54627:30;54646:10;54627:18;:30::i;:::-;54568:17;54586:7;:11;;;54568:30;;;;;;;;-1:-1:-1;;;54568:30:0;;;;;;;;;;;;;;;:43;;;:89;;;;:::i;:::-;54510:5;:16;;54527:7;:11;;;54510:29;;;;;;;;-1:-1:-1;;;54510:29:0;;;;;;;;;;;;;;;;;;:147;;-1:-1:-1;;;;;54510:147:0;;;-1:-1:-1;;;54510:147:0;;;;;;;;;53449:1216;;;;-1:-1:-1;53449:1216:0;-1:-1:-1;;;;;;53449:1216:0:o;71120:457::-;71285:15;;71222:18;;71242:11;;71285:15;-1:-1:-1;;;;;71315:18:0;;;;;-1:-1:-1;;;71315:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;71315:18:0;-1:-1:-1;71311:22:0;-1:-1:-1;71344:9:0;;71364:206;71388:3;71384:1;:7;71364:206;;;71413:24;71440:8;71449:1;71440:11;;;;;;-1:-1:-1;;;71440:11:0;;;;;;;;;;;;;;;71413:38;;71509:3;71493:6;:12;;;71471:6;:19;;;:34;;;;:::i;:::-;71470:42;;;;:::i;:::-;-1:-1:-1;;;;;71466:46:0;;;71534:1;71527;71529;71527:4;;;;;;-1:-1:-1;;;71527:4:0;;;;;;;;;;;;;;;;;;:8;71550;71557:1;71550:8;;:::i;:::-;;;71364:206;71393:3;;;;;:::i;:::-;;;;71364:206;;;;71120:457;;;;;:::o;72790:480::-;72914:9;72940;72936:23;;-1:-1:-1;72958:1:0;72951:8;;72936:23;72972:12;72995:2;72998:1;72995:5;;;;;;-1:-1:-1;;;72995:5:0;;;;;;;;;;;;;;;72987:2;72990:1;72987:5;;;;;;-1:-1:-1;;;72987:5:0;;;;;;;;;;;;;;;:13;;;;:::i;:::-;72972:28;;73011:12;36589:3;73049:2;73052:1;73049:5;;;;;;-1:-1:-1;;;73049:5:0;;;;;;;;;;;;;;;73041:2;73044:1;73041:5;;;;;;-1:-1:-1;;;73041:5:0;;;;;;;;;;;;;;;:13;;;;:::i;:::-;73027:9;73032:4;73027:2;:9;:::i;:::-;73026:29;;;;:::i;:::-;:43;;;;:::i;:::-;73011:58;-1:-1:-1;73011:58:0;73184:66;36589:3;73229:4;73209:16;36589:3;73209:2;:16;:::i;:::-;73208:25;;;;:::i;:::-;73207:41;;;;:::i;:::-;73195:7;73201:1;73195:4;:7;:::i;:::-;73194:55;;;;:::i;:::-;73184:9;:66::i;:::-;:73;;;;:::i;:::-;73179:79;;:1;:79;:::i;:::-;:83;;73261:1;73179:83;:::i;:::-;73175:87;;72790:480;;;;;;;;:::o;30435:135::-;30501:7;30528:34;30545:1;30548;28809:4;30528:16;:34::i;60886:206::-;61005:16;61080:4;61061:5;:15;;;61051:7;:25;;;;:::i;:::-;61050:34;;;;:::i;58439:2264::-;58656:14;58652:27;;58672:7;;58652:27;58753:20;;;;-1:-1:-1;;;;;58753:34:0;58749:1947;;-1:-1:-1;;;;;58958:27:0;;58980:4;58958:27;58954:40;;;58987:7;;58954:40;59015:14;;59008:58;;-1:-1:-1;;;;;59008:35:0;59044:10;59056:9;59008:35;:58::i;:::-;58749:1947;;;59161:9;:18;;;59157:1539;;;59217:20;;;;59295:14;;59196:207;;-1:-1:-1;;;59196:207:0;;-1:-1:-1;;;;;15380:15:1;;;59196:207:0;;;15362:34:1;15432:15;;;15412:18;;;15405:43;15464:18;;;15457:34;;;15507:18;;;15500:34;;;59384:4:0;15550:19:1;;;15543:51;59196::0;;;;;15296:19:1;;59196:207:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59157:1539;;;59535:14;;59561:20;;;;59528:54;;-1:-1:-1;;;59528:54:0;;-1:-1:-1;;;;;14647:32:1;;;59528:54:0;;;14629:51:1;59509:16:0;;59528:32;;;;;;;14602:18:1;;59528:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;59509:73;;59674:9;59662:8;:21;59658:1027;;59725:20;;;;59814:14;;59704:175;;-1:-1:-1;;;59704:175:0;;-1:-1:-1;;;;;14949:15:1;;;59704:175:0;;;14931:34:1;15001:15;;;14981:18;;;14974:43;15033:18;;;15026:34;;;59704:54:0;;;;;14866:18:1;;59704:175:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59658:1027;;;60149:11;;60094:24;;60164:1;;60121:40;;:9;;-1:-1:-1;;;;;60121:40:0;:27;:40::i;:::-;:44;;;;:::i;:::-;60094:71;-1:-1:-1;60184:23:0;60231:179;60303:8;60272:28;60291:9;60094:71;60272:28;:::i;:::-;:39;;;;:::i;:::-;60359:28;60378:8;60359:18;:28::i;:::-;60338:5;:18;;;:49;;;;:::i;:::-;-1:-1:-1;;;;;60231:179:0;:14;:179::i;:::-;60452:20;;;;60538:14;;60431:238;;-1:-1:-1;;;60431:238:0;;-1:-1:-1;;;;;15380:15:1;;;60431:238:0;;;15362:34:1;15432:15;;;15412:18;;;15405:43;15464:18;;;15457:34;;;15507:18;;;15500:34;;;60538:14:0;15550:19:1;;;15543:51;60184:226:0;;-1:-1:-1;60431:51:0;;;;15296:19:1;;60431:238:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59658:1027;;;59157:1539;;58439:2264;;;;;:::o;22232:184::-;22289:7;-1:-1:-1;;;22317:5:0;:14;22309:67;;;;-1:-1:-1;;;22309:67:0;;18789:2:1;22309:67:0;;;18771:21:1;18828:2;18808:18;;;18801:30;18867:34;18847:18;;;18840:62;-1:-1:-1;;;18918:18:1;;;18911:37;18965:19;;22309:67:0;18761:229:1;22309:67:0;-1:-1:-1;22402:5:0;22232:184;;;;:::o;71914:406::-;72094:9;;72125:4;;72054:13;;72160:153;72184:3;72180:1;:7;72160:153;;;72230:4;72214:2;72217:1;72214:5;;;;;;-1:-1:-1;;;72214:5:0;;;;;;;;;;;;;;;72222:4;72214:12;;;;:::i;:::-;72213:21;;;;:::i;:::-;72209:25;;72257:7;:11;;;-1:-1:-1;;;;;72253:15:0;:1;:15;:34;;;-1:-1:-1;72276:11:0;;-1:-1:-1;;;;;72272:15:0;;;72253:34;72249:52;;;72296:5;72289:12;;;;;;;72249:52;72189:3;;;;:::i;:::-;;;;72160:153;;;;71914:406;;;;;;;:::o;70313:577::-;70483:18;70574:14;70591:31;70602:2;70606:4;70612:7;:9;;;70591:10;:31::i;:::-;70728:14;;70574:48;;-1:-1:-1;70724:159:0;;70777:11;70786:2;70777:6;:11;:::i;:::-;70764:24;;70724:159;;;70869:2;70853:11;70869:2;70853:6;:11;:::i;:::-;70835:14;;:30;;;;:::i;:::-;70834:37;;;;:::i;:::-;70821:50;;70724:159;70313:577;;;;;;;:::o;32565:195::-;32632:7;32751:1;32733:14;28809:4;32733:1;:14;:::i;73651:683::-;73805:9;73835;;;;;:22;;;73848:4;:9;;73856:1;73848:9;73835:22;73827:48;;;;-1:-1:-1;;;73827:48:0;;18098:2:1;73827:48:0;;;18080:21:1;18137:2;18117:18;;;18110:30;-1:-1:-1;;;18156:18:1;;;18149:43;18209:18;;73827:48:0;18070:163:1;73827:48:0;73888:9;73900;;;;:25;;73920:2;73923:1;73920:5;;;;;;-1:-1:-1;;;73920:5:0;;;;;;;;;;;;;;;73900:25;;;73912:2;73915:1;73912:5;;;;;;-1:-1:-1;;;73912:5:0;;;;;;;;;;;;;;;73900:25;73888:37;-1:-1:-1;73936:12:0;73951:16;36589:3;73951:2;:16;:::i;:::-;73936:31;-1:-1:-1;73978:12:0;73936:31;36589:3;73995:11;74005:1;73995:8;:11;:::i;:::-;73994:27;;;;:::i;:::-;73993:36;;;;:::i;:::-;73978:51;-1:-1:-1;74096:11:0;74146:4;74129:13;74140:2;74129:8;:13;:::i;:::-;74128:22;;;;:::i;:::-;74118:5;74122:1;74118;:5;:::i;:::-;74110:14;;:4;:14;:::i;:::-;:41;;;;:::i;:::-;74096:55;;74162:12;74184:1;74177:3;:8;;:28;;74198:7;74202:3;74198:1;:7;:::i;:::-;74177:28;;;74188:7;74194:1;74188:3;:7;:::i;:::-;74162:43;-1:-1:-1;74320:1:0;74315;74309:3;74279:27;74301:4;74290:7;74320:1;74162:43;74290:7;:::i;74279:27::-;:33;;;;:::i;:::-;:37;;;;:::i;:::-;74278:43;;;;:::i;:::-;74277:49;;74325:1;74277:49;:::i;:::-;74273:53;73651:683;-1:-1:-1;;;;;;;;;;73651:683:0:o;56329:1847::-;56597:18;;;;56505:25;;-1:-1:-1;;;;;56597:32:0;56593:325;;56647:16;56686:190;56744:10;56785:4;56813:7;:12;;;56848:9;56686:35;:190::i;:::-;-1:-1:-1;56646:230:0;-1:-1:-1;56891:15:0;;-1:-1:-1;56891:15:0;56593:325;57036:16;57095:155;57145:10;57170:7;:18;;;57203:7;:12;;;57230:9;57095:35;:155::i;:::-;57345:16;;;;57063:187;;-1:-1:-1;57063:187:0;-1:-1:-1;57341:323:0;;;57436:18;;;;57486:12;;57415:169;;-1:-1:-1;;;57415:169:0;;-1:-1:-1;;;;;16098:32:1;;;57415:169:0;;;16080:51:1;16147:18;;;16140:34;;;57561:4:0;16190:18:1;;;16183:50;57378:17:0;;57415:48;;;;;;;16053:18:1;;57415:169:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;57378:206;;57608:44;57623:9;57634:17;57608:14;:44::i;:::-;57601:51;;;;;;57341:323;57834:9;57813:17;:30;57805:70;;;;-1:-1:-1;;;57805:70:0;;19957:2:1;57805:70:0;;;19939:21:1;19996:2;19976:18;;;19969:30;20035:29;20015:18;;;20008:57;20082:18;;57805:70:0;19929:177:1;57805:70:0;57888:24;57915:41;:9;57943:12;57915:27;:41::i;:::-;57888:68;;57984:16;57973:8;:27;57969:200;;;58017:13;58045:20;58064:1;58045:16;:20;:::i;:::-;58033:33;;:8;:33;:::i;:::-;58102:18;;;;58130:12;;58081:76;;-1:-1:-1;;;58081:76:0;;-1:-1:-1;;;;;16098:32:1;;;58081:76:0;;;16080:51:1;16147:18;;;16140:34;;;58130:12:0;16190:18:1;;;16183:50;58017:49:0;;-1:-1:-1;58081:48:0;;;;16053:18:1;;58081:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;57969:200;;56329:1847;;;;;;;;;:::o;54762:1307::-;55014:22;55038:17;55068:30;55101:5;:16;;55068:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;55068:49:0;;;;;-1:-1:-1;;;55068:49:0;;;;;;;;;;;;;;;;;;;;;;;;;55180;55209:5;:19;;;55180:16;:28;;:49;;;;:::i;:::-;55354:11;;55168:61;;-1:-1:-1;55301:140:0;;55329:10;;55380:28;55168:61;55380:16;:28;:::i;:::-;55423:7;55301:13;:140::i;:::-;55284:157;;55478:18;55460:14;:36;;55452:69;;;;-1:-1:-1;;;55452:69:0;;18440:2:1;55452:69:0;;;18422:21:1;18479:2;18459:18;;;18452:30;-1:-1:-1;;;18498:18:1;;;18491:50;18558:18;;55452:69:0;18412:170:1;55452:69:0;55557:1;55540:14;:18;55532:42;;;;-1:-1:-1;;;55532:42:0;;20313:2:1;55532:42:0;;;20295:21:1;20352:2;20332:18;;;20325:30;-1:-1:-1;;;20371:18:1;;;20364:41;20422:18;;55532:42:0;20285:161:1;55532:42:0;55637:239;55667:14;55696:5;:20;;55717:7;:11;;;55696:33;;;;;;;;-1:-1:-1;;;55696:33:0;;;;;;;;;;;;;;;;;;55637:239;;;;;;;;55696:33;;;;;;;55637:239;;-1:-1:-1;;;;;55637:239:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55637:239:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;55637:239:0;;;;;;;;;;-1:-1:-1;;;55637:239:0;;;;;;;;;;;;;;;-1:-1:-1;;;55637:239:0;;;;;;;;;;;-1:-1:-1;55755:11:0;;55744:23;;:10;;:23;;;;;;;-1:-1:-1;;;55744:23:0;;;;;;;;;;;;;;;55782:10;55807:58;55824:5;55848:16;55831:7;:14;;;:33;;;;:::i;55637:239::-;56027:34;56046:14;56027:18;:34::i;:::-;55975:10;55986:7;:11;;;55975:23;;;;;;;;-1:-1:-1;;;55975:23:0;;;;;;;;;;;;;;;:36;;;:86;;;;:::i;:::-;55917:5;:16;;55934:7;:11;;;55917:29;;;;;;;;-1:-1:-1;;;55917:29:0;;;;;;;;;;;;;;;;;;:144;;-1:-1:-1;;;;;55917:144:0;;;-1:-1:-1;;;55917:144:0;;;;;;;;;-1:-1:-1;54762:1307:0;;;;-1:-1:-1;54762:1307:0;-1:-1:-1;;;;;54762:1307:0:o;52050:1253::-;52218:27;;:::i;:::-;52271:40;;;;;;;;52281:1;52271:40;;;;;;52284:1;52271:40;;;;52287:5;:20;;52308:1;52287:23;;;;;;-1:-1:-1;;;52287:23:0;;;;;;;;;;;;;;;;;;52271:40;;;;;;;;52287:23;;;;;;;52271:40;;-1:-1:-1;;;;;52271:40:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;52271:40:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;52271:40:0;;;;;;;;;;-1:-1:-1;;;52271:40:0;;;;;;;;;;;;;;;-1:-1:-1;;;52271:40:0;;;;;;;;;;;-1:-1:-1;52271:40:0;;52329:11;;;;52258:53;;-1:-1:-1;52322:79:0;;-1:-1:-1;;;;;52322:36:0;52359:10;52379:4;52386:14;52322:36;:79::i;:::-;52448:19;;;;:30;;;52414:18;;-1:-1:-1;;;;;52448:44:0;;:127;;52545:10;:19;;;:30;;;52448:127;;;52520:4;52448:127;52615:19;;;;;:24;52608:54;;-1:-1:-1;;;52608:54:0;;-1:-1:-1;;;;;14647:32:1;;;52608:54:0;;;14629:51:1;52414:161:0;;-1:-1:-1;52588:17:0;;52608:42;;;;;;14602:18:1;;52608:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;52763:19;;;;;:24;52794:11;;;;52755:82;;-1:-1:-1;;;52755:82:0;;52588:74;;-1:-1:-1;;;;;;52755:38:0;;;;:82;;52807:14;;52763:24;;52826:10;;52755:82;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;52874:19:0;;;;;:24;52867:54;;-1:-1:-1;;;52867:54:0;;-1:-1:-1;;;;;14647:32:1;;;52867:54:0;;;14629:51:1;52848:16:0;;52867:42;;;;14602:18:1;;52867:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;52848:73;-1:-1:-1;52949:20:0;52960:9;52848:73;52949:20;:::i;:::-;52932:14;;;:37;-1:-1:-1;;;;;53039:27:0;;53061:4;53039:27;53035:261;;53098:9;53087:8;:20;53083:202;;;53128:13;53156;53168:1;53156:9;:13;:::i;:::-;53144:26;;:8;:26;:::i;:::-;53230:19;;;;;:24;53189:80;;-1:-1:-1;;;53189:80:0;;-1:-1:-1;;;;;16098:32:1;;;53189:80:0;;;16080:51:1;16147:18;;;16140:34;;;53230:24:0;16190:18:1;;;16183:50;53128:42:0;;-1:-1:-1;53189:40:0;;;;;16053:18:1;;53189:80:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;53083:202;;52050:1253;;;;;;;;;:::o;6717:1273::-;6765:9;6791:6;6787:1196;;-1:-1:-1;6806:1:0;6799:8;;6787:1196;6851:1;6879;-1:-1:-1;;;6899:41:0;;6895:119;;6968:3;6961:10;;;;;6996:2;6990:8;6895:119;7038:19;7032:2;:25;7028:102;;7085:2;7078:9;;;;;7112:2;7106:8;7028:102;7154:11;7148:2;:17;7144:94;;7193:2;7186:9;;;;;7220:2;7214:8;7144:94;7262:7;7256:2;:13;7252:89;;7297:2;7290:9;;;;;7324:1;7318:7;7252:89;7365:5;7359:2;:11;7355:86;;7398:1;7391:8;;;;;7424:1;7418:7;7355:86;7465:4;7459:2;:10;7455:85;;7497:1;7490:8;;;;;7523:1;7517:7;7455:85;7564:3;7558:2;:9;7554:57;;7594:1;7588:7;7554:57;7644:1;7634:5;7638:1;7634;:5;:::i;:::-;7630:9;;:1;:9;:::i;:::-;7629:16;;;-1:-1:-1;7679:1:0;7669:5;7629:16;7669:1;:5;:::i;:::-;7665:9;;:1;:9;:::i;:::-;7664:16;;;-1:-1:-1;7714:1:0;7704:5;7664:16;7704:1;:5;:::i;:::-;7700:9;;:1;:9;:::i;:::-;7699:16;;;-1:-1:-1;7749:1:0;7739:5;7699:16;7739:1;:5;:::i;:::-;7735:9;;:1;:9;:::i;:::-;7734:16;;;-1:-1:-1;7784:1:0;7774:5;7734:16;7774:1;:5;:::i;:::-;7770:9;;:1;:9;:::i;:::-;7769:16;;;-1:-1:-1;7819:1:0;7809:5;7769:16;7809:1;:5;:::i;:::-;7805:9;;:1;:9;:::i;:::-;7804:16;;;-1:-1:-1;7854:1:0;7844:5;7804:16;7844:1;:5;:::i;:::-;7840:9;;:1;:9;:::i;:::-;7839:16;;;-1:-1:-1;7907:10:0;7920:5;7839:16;7920:1;:5;:::i;:::-;7907:18;;7959:2;7955:1;:6;:15;;7968:2;7955:15;;;7964:1;7955:15;7940:31;;;;;;;31043:286;31163:7;31316:5;31307;31311:1;31307;:5;:::i;:::-;31306:15;;;;:::i;18711:177::-;18821:58;;-1:-1:-1;;;;;15797:32:1;;18821:58:0;;;15779:51:1;15846:18;;;15839:34;;;18794:86:0;;18814:5;;-1:-1:-1;;;18844:23:0;15752:18:1;;18821:58:0;;;;-1:-1:-1;;18821:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;18821:58:0;-1:-1:-1;;;;;;18821:58:0;;;;;;;;;;18794:19;:86::i;:::-;18711:177;;;:::o;34657:211::-;34733:9;34855:5;34836:15;29217:3;34836:1;:15;:::i;35187:106::-;35245:7;35276:1;35272;:5;:13;;35284:1;35272:13;;;-1:-1:-1;35280:1:0;35187:106;-1:-1:-1;35187:106:0:o;27934:473::-;28172:37;;-1:-1:-1;;;28172:37:0;;-1:-1:-1;;;;;14647:32:1;;;28172:37:0;;;14629:51:1;28094:19:0;;;;;;28172:25;;;;;;14602:18:1;;28172:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;28152:57;-1:-1:-1;28220:59:0;-1:-1:-1;;;;;28220:32:0;;28253:7;28262:10;28274:4;28220:32;:59::i;:::-;28309:37;;-1:-1:-1;;;28309:37:0;;-1:-1:-1;;;;;14647:32:1;;;28309:37:0;;;14629:51:1;28309:25:0;;;;;14602:18:1;;28309:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;28290:56;-1:-1:-1;28371:28:0;28390:9;28290:56;28371:28;:::i;:::-;28357:42;;27934:473;;;;;;;;:::o;18896:205::-;19024:68;;-1:-1:-1;;;;;14949:15:1;;;19024:68:0;;;14931:34:1;15001:15;;14981:18;;;14974:43;15033:18;;;15026:34;;;18997:96:0;;19017:5;;-1:-1:-1;;;19047:27:0;14866:18:1;;19024:68:0;14848:218:1;18997:96:0;18896:205;;;;:::o;21145:761::-;21569:23;21595:69;21623:4;21595:69;;;;;;;;;;;;;;;;;21603:5;-1:-1:-1;;;;;21595:27:0;;;:69;;;;;:::i;:::-;21679:17;;21569:95;;-1:-1:-1;21679:21:0;21675:224;;21821:10;21810:30;;;;;;;;;;;;:::i;:::-;21802:85;;;;-1:-1:-1;;;21802:85:0;;22418:2:1;21802:85:0;;;22400:21:1;22457:2;22437:18;;;22430:30;22496:34;22476:18;;;22469:62;-1:-1:-1;;;22547:18:1;;;22540:40;22597:19;;21802:85:0;22390:232:1;14311:195:0;14414:12;14446:52;14468:6;14476:4;14482:1;14485:12;14414;11760:20;;15607:60;;;;-1:-1:-1;;;15607:60:0;;22060:2:1;15607:60:0;;;22042:21:1;22099:2;22079:18;;;22072:30;22138:31;22118:18;;;22111:59;22187:18;;15607:60:0;22032:179:1;15607:60:0;15741:12;15755:23;15782:6;-1:-1:-1;;;;;15782:11:0;15802:5;15810:4;15782:33;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15740:75;;;;15833:52;15851:7;15860:10;15872:12;15833:17;:52::i;:::-;15826:59;15363:530;-1:-1:-1;;;;;;;15363:530:0:o;17903:742::-;18018:12;18047:7;18043:595;;;-1:-1:-1;18078:10:0;18071:17;;18043:595;18192:17;;:21;18188:439;;18455:10;18449:17;18516:15;18503:10;18499:2;18495:19;18488:44;18403:148;18598:12;18591:20;;-1:-1:-1;;;18591:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14:173:1;82:20;;-1:-1:-1;;;;;131:31:1;;121:42;;111:2;;177:1;174;167:12;192:758;;309:3;302:4;294:6;290:17;286:27;276:2;;331:5;324;317:20;276:2;371:6;358:20;397:4;421:70;437:53;487:2;437:53;:::i;:::-;421:70;:::i;:::-;525:15;;;556:12;;;;588:15;;;622:4;657:11;;;645:24;;641:33;;638:42;-1:-1:-1;635:2:1;;;697:5;690;683:20;635:2;723:5;737:184;751:2;748:1;745:9;737:184;;;808:38;842:3;837;808:38;:::i;:::-;796:51;;867:12;;;;899;;;;769:1;762:9;737:184;;;-1:-1:-1;939:5:1;;266:684;-1:-1:-1;;;;;;;;266:684:1:o;955:398::-;;;1082:3;1075:4;1067:6;1063:17;1059:27;1049:2;;1107:8;1097;1090:26;1049:2;-1:-1:-1;1137:20:1;;-1:-1:-1;;;;;1169:30:1;;1166:2;;;1219:8;1209;1202:26;1166:2;1263:4;1255:6;1251:17;1239:29;;1326:3;1319:4;1311;1303:6;1299:17;1291:6;1287:30;1283:41;1280:50;1277:2;;;1343:1;1340;1333:12;1277:2;1039:314;;;;;:::o;1358:704::-;;1465:3;1458:4;1450:6;1446:17;1442:27;1432:2;;1487:5;1480;1473:20;1432:2;1527:6;1514:20;1553:4;1577:70;1593:53;1643:2;1593:53;:::i;1577:70::-;1681:15;;;1712:12;;;;1744:15;;;1790:11;;;1778:24;;1774:33;;1771:42;-1:-1:-1;1768:2:1;;;1830:5;1823;1816:20;1768:2;1856:5;1870:163;1884:2;1881:1;1878:9;1870:163;;;1941:17;;1929:30;;1979:12;;;;2011;;;;1902:1;1895:9;1870:163;;;-1:-1:-1;2051:5:1;;1422:640;-1:-1:-1;;;;;;;1422:640:1:o;2067:161::-;;2170:2;2161:6;2156:3;2152:16;2148:25;2145:2;;;2190:5;2183;2176:20;2233:304;;2338:4;2326:9;2321:3;2317:19;2313:30;2310:2;;;2360:5;2353;2346:20;2310:2;2386:21;2402:4;2386:21;:::i;:::-;2377:30;;2430:29;2449:9;2430:29;:::i;:::-;2423:5;2416:44;2492:38;2526:2;2515:9;2511:18;2492:38;:::i;:::-;2487:2;2480:5;2476:14;2469:62;2300:237;;;;:::o;2542:169::-;;2652:3;2643:6;2638:3;2634:16;2630:26;2627:2;;;2673:5;2666;2659:20;2716:380;;2823:4;2811:9;2806:3;2802:19;2798:30;2795:2;;;2845:5;2838;2831:20;2795:2;2871:21;2887:4;2871:21;:::i;:::-;2862:30;;2928:9;2915:23;2908:5;2901:38;2999:2;2988:9;2984:18;2971:32;2966:2;2959:5;2955:14;2948:56;3036:53;3085:3;3080:2;3069:9;3065:18;3036:53;:::i;:::-;3031:2;3024:5;3020:14;3013:77;2785:311;;;;:::o;3101:188::-;3169:20;;-1:-1:-1;;;;;3218:46:1;;3208:57;;3198:2;;3279:1;3276;3269:12;3294:156;3360:20;;3420:4;3409:16;;3399:27;;3389:2;;3440:1;3437;3430:12;3455:196;;3567:2;3555:9;3546:7;3542:23;3538:32;3535:2;;;3588:6;3580;3573:22;3535:2;3616:29;3635:9;3616:29;:::i;3656:1614::-;;;;;3947:3;3935:9;3926:7;3922:23;3918:33;3915:2;;;3969:6;3961;3954:22;3915:2;4014:9;4001:23;-1:-1:-1;;;;;4084:2:1;4076:6;4073:14;4070:2;;;4105:6;4097;4090:22;4070:2;4133:71;4196:7;4187:6;4176:9;4172:22;4133:71;:::i;:::-;4123:81;;4223:2;4213:12;;4278:2;4267:9;4263:18;4250:32;4307:2;4297:8;4294:16;4291:2;;;4328:6;4320;4313:22;4291:2;4356:24;;4411:4;4403:13;;4399:27;-1:-1:-1;4389:2:1;;4445:6;4437;4430:22;4389:2;4486;4473:16;4509:70;4525:53;4575:2;4525:53;:::i;4509:70::-;4613:15;;;4644:12;;;;4676:11;;;4714;;;4706:20;;4702:29;;4699:42;-1:-1:-1;4696:2:1;;;4759:6;4751;4744:22;4696:2;4786:6;4777:15;;4801:167;4815:2;4812:1;4809:9;4801:167;;;4872:21;4889:3;4872:21;:::i;:::-;4860:34;;4833:1;4826:9;;;;;4914:12;;;;4946;;4801:167;;;-1:-1:-1;4987:5:1;-1:-1:-1;;;;5045:2:1;5030:18;;5017:32;;-1:-1:-1;5061:16:1;;;5058:2;;;5095:6;5087;5080:22;5058:2;;5123:63;5178:7;5167:8;5156:9;5152:24;5123:63;:::i;:::-;5113:73;;;5205:59;5256:7;5251:2;5240:9;5236:18;5205:59;:::i;:::-;5195:69;;3905:1365;;;;;;;:::o;5275:529::-;;;5484:3;5472:9;5463:7;5459:23;5455:33;5452:2;;;5506:6;5498;5491:22;5452:2;5551:9;5538:23;-1:-1:-1;;;;;5576:6:1;5573:30;5570:2;;;5621:6;5613;5606:22;5570:2;5649:71;5712:7;5703:6;5692:9;5688:22;5649:71;:::i;:::-;5639:81;;;5739:59;5790:7;5785:2;5774:9;5770:18;5739:59;:::i;:::-;5729:69;;5442:362;;;;;:::o;5809:667::-;;;;;6050:3;6038:9;6029:7;6025:23;6021:33;6018:2;;;6072:6;6064;6057:22;6018:2;6117:9;6104:23;-1:-1:-1;;;;;6142:6:1;6139:30;6136:2;;;6187:6;6179;6172:22;6136:2;6215:71;6278:7;6269:6;6258:9;6254:22;6215:71;:::i;:::-;6205:81;;;6305:36;6337:2;6326:9;6322:18;6305:36;:::i;:::-;6295:46;;6388:2;6377:9;6373:18;6360:32;6350:42;;6411:59;6462:7;6457:2;6446:9;6442:18;6411:59;:::i;6481:807::-;;;;;;;6754:3;6742:9;6733:7;6729:23;6725:33;6722:2;;;6776:6;6768;6761:22;6722:2;6821:9;6808:23;-1:-1:-1;;;;;6846:6:1;6843:30;6840:2;;;6891:6;6883;6876:22;6840:2;6919:71;6982:7;6973:6;6962:9;6958:22;6919:71;:::i;:::-;6909:81;;;7009:36;7041:2;7030:9;7026:18;7009:36;:::i;:::-;6999:46;;7064:36;7096:2;7085:9;7081:18;7064:36;:::i;:::-;7054:46;;7147:2;7136:9;7132:18;7119:32;7109:42;;7198:3;7187:9;7183:19;7170:33;7160:43;;7222:60;7274:7;7268:3;7257:9;7253:19;7222:60;:::i;:::-;7212:70;;6712:576;;;;;;;;:::o;7293:251::-;;7402:2;7390:9;7381:7;7377:23;7373:32;7370:2;;;7423:6;7415;7408:22;7370:2;7467:9;7454:23;7486:28;7508:5;7486:28;:::i;7549:255::-;;7669:2;7657:9;7648:7;7644:23;7640:32;7637:2;;;7690:6;7682;7675:22;7637:2;7727:9;7721:16;7746:28;7768:5;7746:28;:::i;7809:492::-;;7943:2;7931:9;7922:7;7918:23;7914:32;7911:2;;;7964:6;7956;7949:22;7911:2;7995:19;8011:2;7995:19;:::i;:::-;8037:27;8054:9;8037:27;:::i;:::-;8030:5;8023:42;8097:38;8131:2;8120:9;8116:18;8097:38;:::i;:::-;8092:2;8085:5;8081:14;8074:62;8188:2;8177:9;8173:18;8160:32;8201:30;8223:7;8201:30;:::i;:::-;8258:2;8247:14;;8240:31;8251:5;7901:400;-1:-1:-1;;;7901:400:1:o;8306:247::-;;8447:3;8435:9;8426:7;8422:23;8418:33;8415:2;;;8469:6;8461;8454:22;8415:2;8497:50;8539:7;8528:9;8497:50;:::i;8558:1104::-;;;;;;;;8865:3;8853:9;8844:7;8840:23;8836:33;8833:2;;;8887:6;8879;8872:22;8833:2;8928:9;8915:23;8905:33;;8957:68;9017:7;9012:2;9001:9;8997:18;8957:68;:::i;:::-;8947:78;;9076:3;9065:9;9061:19;9048:33;-1:-1:-1;;;;;9141:2:1;9133:6;9130:14;9127:2;;;9162:6;9154;9147:22;9127:2;9206:70;9268:7;9259:6;9248:9;9244:22;9206:70;:::i;:::-;9295:8;;-1:-1:-1;9180:96:1;-1:-1:-1;9383:3:1;9368:19;;9355:33;;-1:-1:-1;9400:16:1;;;9397:2;;;9434:6;9426;9419:22;9397:2;;9478:72;9542:7;9531:8;9520:9;9516:24;9478:72;:::i;:::-;8823:839;;;;-1:-1:-1;8823:839:1;;;;;;9651:3;9636:19;;;9623:33;;8823:839;-1:-1:-1;;;;8823:839:1:o;9667:811::-;;;;;;;;9988:3;9976:9;9967:7;9963:23;9959:33;9956:2;;;10010:6;10002;9995:22;9956:2;10051:9;10038:23;10028:33;;10080:68;10140:7;10135:2;10124:9;10120:18;10080:68;:::i;:::-;10070:78;;10167:62;10221:7;10215:3;10204:9;10200:19;10167:62;:::i;:::-;10157:72;;10248:62;10302:7;10296:3;10285:9;10281:19;10248:62;:::i;:::-;10238:72;;10357:3;10346:9;10342:19;10329:33;10319:43;;10409:3;10398:9;10394:19;10381:33;10371:43;;10433:39;10467:3;10456:9;10452:19;10433:39;:::i;:::-;10423:49;;9946:532;;;;;;;;;;:::o;10483:614::-;;;;;;10746:3;10734:9;10725:7;10721:23;10717:33;10714:2;;;10768:6;10760;10753:22;10714:2;10809:9;10796:23;10786:33;;10838:68;10898:7;10893:2;10882:9;10878:18;10838:68;:::i;:::-;10828:78;;10925:62;10979:7;10973:3;10962:9;10958:19;10925:62;:::i;:::-;10704:393;;;;-1:-1:-1;10915:72:1;;11034:3;11019:19;;11006:33;;-1:-1:-1;11086:3:1;11071:19;11058:33;;10704:393;-1:-1:-1;;10704:393:1:o;11102:689::-;;;;;;;11382:3;11370:9;11361:7;11357:23;11353:33;11350:2;;;11404:6;11396;11389:22;11350:2;11445:9;11432:23;11422:33;;11474:68;11534:7;11529:2;11518:9;11514:18;11474:68;:::i;:::-;11464:78;;11561:62;11615:7;11609:3;11598:9;11594:19;11561:62;:::i;:::-;11551:72;;11670:3;11659:9;11655:19;11642:33;11632:43;;11722:3;11711:9;11707:19;11694:33;11684:43;;11746:39;11780:3;11769:9;11765:19;11746:39;:::i;11796:834::-;;;;;;;12070:3;12058:9;12049:7;12045:23;12041:33;12038:2;;;12092:6;12084;12077:22;12038:2;12133:9;12120:23;12110:33;;12162:68;12222:7;12217:2;12206:9;12202:18;12162:68;:::i;:::-;12152:78;;12277:3;12266:9;12262:19;12249:33;12239:43;;12333:3;12322:9;12318:19;12305:33;-1:-1:-1;;;;;12353:6:1;12350:30;12347:2;;;12398:6;12390;12383:22;12347:2;12442:70;12504:7;12495:6;12484:9;12480:22;12442:70;:::i;:::-;12531:8;;-1:-1:-1;12416:96:1;-1:-1:-1;12585:39:1;;-1:-1:-1;12619:3:1;12604:19;;12585:39;:::i;12635:1168::-;;;;;;;;;12957:3;12945:9;12936:7;12932:23;12928:33;12925:2;;;12979:6;12971;12964:22;12925:2;13020:9;13007:23;12997:33;;13049:59;13100:7;13095:2;13084:9;13080:18;13049:59;:::i;:::-;13039:69;;13159:3;13148:9;13144:19;13131:33;-1:-1:-1;;;;;13224:2:1;13216:6;13213:14;13210:2;;;13245:6;13237;13230:22;13210:2;13289:70;13351:7;13342:6;13331:9;13327:22;13289:70;:::i;:::-;13378:8;;-1:-1:-1;13263:96:1;-1:-1:-1;13466:3:1;13451:19;;13438:33;;-1:-1:-1;13483:16:1;;;13480:2;;;13517:6;13509;13502:22;13480:2;;13561:72;13625:7;13614:8;13603:9;13599:24;13561:72;:::i;:::-;13652:8;;-1:-1:-1;13535:98:1;-1:-1:-1;;13734:3:1;13719:19;;13706:33;;-1:-1:-1;13758:39:1;13792:3;13777:19;;13758:39;:::i;:::-;13748:49;;12915:888;;;;;;;;;;;:::o;13808:194::-;;13931:2;13919:9;13910:7;13906:23;13902:32;13899:2;;;13952:6;13944;13937:22;13899:2;-1:-1:-1;13980:16:1;;13889:113;-1:-1:-1;13889:113:1:o;14007:192::-;;14117:2;14105:9;14096:7;14092:23;14088:32;14085:2;;;14138:6;14130;14123:22;14085:2;14166:27;14183:9;14166:27;:::i;14204:274::-;;14371:6;14365:13;14387:53;14433:6;14428:3;14421:4;14413:6;14409:17;14387:53;:::i;:::-;14456:16;;;;;14341:137;-1:-1:-1;;14341:137:1:o;16244:455::-;-1:-1:-1;;;;;16539:15:1;;;16521:34;;16586:2;16571:18;;16564:34;;;;16629:2;16614:18;;16607:34;;;;16677:15;;;16672:2;16657:18;;16650:43;16470:3;16455:19;;16437:262::o;17156:383::-;;17305:2;17294:9;17287:21;17337:6;17331:13;17380:6;17375:2;17364:9;17360:18;17353:34;17396:66;17455:6;17450:2;17439:9;17435:18;17430:2;17422:6;17418:15;17396:66;:::i;:::-;17523:2;17502:15;-1:-1:-1;;17498:29:1;17483:45;;;;17530:2;17479:54;;17277:262;-1:-1:-1;;17277:262:1:o;21152:345::-;21354:2;21336:21;;;21393:2;21373:18;;;21366:30;-1:-1:-1;;;21427:2:1;21412:18;;21405:51;21488:2;21473:18;;21326:171::o;24229:1262::-;;24533:2;24522:9;24518:18;24563:6;24552:9;24545:25;24589:2;24627;24622;24611:9;24607:18;24600:30;24650:6;24685;24679:13;24716:6;24708;24701:22;24754:3;24743:9;24739:19;24732:26;;24793:2;24785:6;24781:15;24767:29;;24814:4;24827:195;24841:6;24838:1;24835:13;24827:195;;;24906:13;;-1:-1:-1;;;;;24902:39:1;24890:52;;24997:15;;;;24962:12;;;;24938:1;24856:9;24827:195;;;-1:-1:-1;;25058:19:1;;;25053:2;25038:18;;25031:47;25128:13;;25150:21;;;25189:12;;;;-1:-1:-1;25226:15:1;;;;25261:4;25274:189;25290:8;25285:3;25282:17;25274:189;;;25359:15;;25345:30;;25397:14;;;;25436:17;;;;25318:1;25309:11;25274:189;;;-1:-1:-1;25480:5:1;;24494:997;-1:-1:-1;;;;;;;;24494:997:1:o;25757:275::-;25828:2;25822:9;25893:2;25874:13;;-1:-1:-1;;25870:27:1;25858:40;;-1:-1:-1;;;;;25913:34:1;;25949:22;;;25910:62;25907:2;;;25975:18;;:::i;:::-;26011:2;26004:22;25802:230;;-1:-1:-1;25802:230:1:o;26037:196::-;;-1:-1:-1;;;;;26132:6:1;26129:30;26126:2;;;26162:18;;:::i;:::-;-1:-1:-1;26222:4:1;26203:17;;;26199:28;;26116:117::o;26238:253::-;;-1:-1:-1;;;;;26367:2:1;26364:1;26360:10;26397:2;26394:1;26390:10;26428:3;26424:2;26420:12;26415:3;26412:21;26409:2;;;26436:18;;:::i;:::-;26472:13;;26286:205;-1:-1:-1;;;;26286:205:1:o;26496:128::-;;26567:1;26563:6;26560:1;26557:13;26554:2;;;26573:18;;:::i;:::-;-1:-1:-1;26609:9:1;;26544:80::o;26629:216::-;;-1:-1:-1;;;;;26756:2:1;26753:1;26749:10;26778:3;26768:2;;26785:18;;:::i;:::-;26823:10;;26819:20;;;;;26675:170;-1:-1:-1;;26675:170:1:o;26850:120::-;;26916:1;26906:2;;26921:18;;:::i;:::-;-1:-1:-1;26955:9:1;;26896:74::o;26975:453::-;27071:6;27094:5;27108:314;27157:1;27194:2;27184:8;27181:16;27171:2;;27201:5;;;27171:2;27242:4;27237:3;27233:14;27227:4;27224:24;27221:2;;;27251:18;;:::i;:::-;27301:2;27291:8;27287:17;27284:2;;;27316:16;;;;27284:2;27395:17;;;;;27355:15;;27108:314;;;27052:376;;;;;;;:::o;27433:148::-;;27520:55;-1:-1:-1;;27561:4:1;27547:19;;27541:4;27586:922;27670:8;27660:2;;-1:-1:-1;27711:1:1;27725:5;;27660:2;27759:4;27749:2;;-1:-1:-1;27796:1:1;27810:5;;27749:2;27841:4;27859:1;27854:59;;;;27927:1;27922:183;;;;27834:271;;27854:59;27884:1;27875:10;;27898:5;;;27922:183;27959:3;27949:8;27946:17;27943:2;;;27966:18;;:::i;:::-;28022:1;28012:8;28008:16;27999:25;;28050:3;28043:5;28040:14;28037:2;;;28057:18;;:::i;:::-;28090:5;;;27834:271;;28189:2;28179:8;28176:16;28170:3;28164:4;28161:13;28157:36;28151:2;28141:8;28138:16;28133:2;28127:4;28124:12;28120:35;28117:77;28114:2;;;-1:-1:-1;28226:19:1;;;28261:14;;;28258:2;;;28278:18;;:::i;:::-;28311:5;;28114:2;28358:42;28396:3;28386:8;28380:4;28377:1;28358:42;:::i;:::-;28433:6;28428:3;28424:16;28415:7;28412:29;28409:2;;;28444:18;;:::i;:::-;28482:20;;27650:858;-1:-1:-1;;;;27650:858:1:o;28513:287::-;;-1:-1:-1;;;;;28646:2:1;28643:1;28639:10;28676:2;28673:1;28669:10;28732:3;28728:2;28724:12;28719:3;28716:21;28709:3;28702:11;28695:19;28691:47;28688:2;;;28741:18;;:::i;28805:168::-;;28911:1;28907;28903:6;28899:14;28896:1;28893:21;28888:1;28881:9;28874:17;28870:45;28867:2;;;28918:18;;:::i;:::-;-1:-1:-1;28958:9:1;;28857:116::o;28978:246::-;;-1:-1:-1;;;;;29131:10:1;;;;29101;;29153:12;;;29150:2;;;29168:18;;:::i;:::-;29205:13;;29027:197;-1:-1:-1;;;29027:197:1:o;29229:125::-;;29297:1;29294;29291:8;29288:2;;;29302:18;;:::i;:::-;-1:-1:-1;29339:9:1;;29278:76::o;29359:258::-;29431:1;29441:113;29455:6;29452:1;29449:13;29441:113;;;29531:11;;;29525:18;29512:11;;;29505:39;29477:2;29470:10;29441:113;;;29572:6;29569:1;29566:13;29563:2;;;-1:-1:-1;;29607:1:1;29589:16;;29582:27;29412:205::o;29622:135::-;;-1:-1:-1;;29682:17:1;;29679:2;;;29702:18;;:::i;:::-;-1:-1:-1;29749:1:1;29738:13;;29669:88::o;29762:127::-;29823:10;29818:3;29814:20;29811:1;29804:31;29854:4;29851:1;29844:15;29878:4;29875:1;29868:15;29894:127;29955:10;29950:3;29946:20;29943:1;29936:31;29986:4;29983:1;29976:15;30010:4;30007:1;30000:15;30026:127;30087:10;30082:3;30078:20;30075:1;30068:31;30118:4;30115:1;30108:15;30142:4;30139:1;30132:15;30158:118;30244:5;30237:13;30230:21;30223:5;30220:32;30210:2;;30266:1;30263;30256:12;30210:2;30200:76;:::o
Swarm Source
ipfs://e7ba85f0b708b8abff3092672d9a78fa4f5bfad0b48efb112edf3021161eae9a
Loading...
Loading
Loading...
Loading
OVERVIEW
Solidity library for the Feeder Pool contracts.Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.