More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 568 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Unwind | 17171751 | 429 days ago | IN | 0 ETH | 0.01666204 | ||||
Unwind | 17070585 | 444 days ago | IN | 0 ETH | 0.01503535 | ||||
Unwind | 17070574 | 444 days ago | IN | 0 ETH | 0.01565822 | ||||
Build | 17010769 | 452 days ago | IN | 0 ETH | 0.00657077 | ||||
Build | 16978899 | 457 days ago | IN | 0 ETH | 0.00897341 | ||||
Unwind | 16831555 | 477 days ago | IN | 0 ETH | 0.00627605 | ||||
Liquidate | 16797212 | 482 days ago | IN | 0 ETH | 0.01172218 | ||||
Liquidate | 16796193 | 482 days ago | IN | 0 ETH | 0.00711756 | ||||
Liquidate | 16796190 | 482 days ago | IN | 0 ETH | 0.00702517 | ||||
Liquidate | 16796187 | 482 days ago | IN | 0 ETH | 0.00732263 | ||||
Liquidate | 16767961 | 486 days ago | IN | 0 ETH | 0.00635296 | ||||
Liquidate | 16767960 | 486 days ago | IN | 0 ETH | 0.00649123 | ||||
Build | 16739103 | 490 days ago | IN | 0 ETH | 0.00742775 | ||||
Liquidate | 16729515 | 492 days ago | IN | 0 ETH | 0.00815194 | ||||
Unwind | 16660991 | 501 days ago | IN | 0 ETH | 0.00666742 | ||||
Unwind | 16654112 | 502 days ago | IN | 0 ETH | 0.00889385 | ||||
Unwind | 16652190 | 503 days ago | IN | 0 ETH | 0.0091414 | ||||
Build | 16651769 | 503 days ago | IN | 0 ETH | 0.0099009 | ||||
Unwind | 16651033 | 503 days ago | IN | 0 ETH | 0.01632481 | ||||
Unwind | 16644492 | 504 days ago | IN | 0 ETH | 0.01419116 | ||||
Unwind | 16644491 | 504 days ago | IN | 0 ETH | 0.01419462 | ||||
Liquidate | 16642576 | 504 days ago | IN | 0 ETH | 0.02688852 | ||||
Unwind | 16642084 | 504 days ago | IN | 0 ETH | 0.018814 | ||||
Unwind | 16639966 | 504 days ago | IN | 0 ETH | 0.01040091 | ||||
Unwind | 16639965 | 504 days ago | IN | 0 ETH | 0.01025874 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
15641602 | 644 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
OverlayV1Market
Compiler Version
v0.8.10+commit.fc410830
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-09-29 */ // SPDX-License-Identifier: BUSL-1.1 // File: https://github.com/overlay-market/v1-core/blob/main/contracts/libraries/uniswap/v3-core/FullMath.sol pragma solidity ^0.8.0; /// COPIED FROM: /// https://github.com/Uniswap/v3-core/blob/0.8/contracts/libraries/FullMath.sol /// @title Contains 512-bit math functions /// @notice Facilitates multiplication and division that can have overflow of /// @notice an intermediate value without any loss of precision /// @dev Handles "phantom overflow" i.e., allows multiplication and division /// @dev where an intermediate value overflows 256 bits library FullMath { /// @notice Calculates floor(a×b÷denominator) with full precision. /// @notice Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv function mulDiv( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = a * b // Compute the product mod 2**256 and mod 2**256 - 1 // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2**256 + prod0 uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(a, b, not(0)) prod0 := mul(a, b) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { require(denominator > 0); assembly { result := div(prod0, denominator) } return result; } // Make sure the result is less than 2**256. // Also prevents denominator == 0 require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0] // Compute remainder using mulmod uint256 remainder; assembly { remainder := mulmod(a, b, denominator) } // Subtract 256 bit number from 512 bit number assembly { prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator // Compute largest power of two divisor of denominator. // Always >= 1. uint256 twos = (0 - denominator) & denominator; // Divide denominator by power of two assembly { denominator := div(denominator, twos) } // Divide [prod1 prod0] by the factors of two assembly { prod0 := div(prod0, twos) } // Shift in bits from prod1 into prod0. For this we need // to flip `twos` such that it is 2**256 / twos. // If twos is zero, then it becomes one assembly { twos := add(div(sub(0, twos), twos), 1) } prod0 |= prod1 * twos; // Invert denominator mod 2**256 // Now that denominator is an odd number, it has an inverse // modulo 2**256 such that denominator * inv = 1 mod 2**256. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, denominator * inv = 1 mod 2**4 uint256 inv = (3 * denominator) ^ 2; // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv *= 2 - denominator * inv; // inverse mod 2**8 inv *= 2 - denominator * inv; // inverse mod 2**16 inv *= 2 - denominator * inv; // inverse mod 2**32 inv *= 2 - denominator * inv; // inverse mod 2**64 inv *= 2 - denominator * inv; // inverse mod 2**128 inv *= 2 - denominator * inv; // inverse mod 2**256 // Because the division is now exact we can divide by multiplying // with the modular inverse of denominator. This will give us the // correct result modulo 2**256. Since the precoditions guarantee // that the outcome is less than 2**256, this is the final result. // We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inv; return result; } } /// @notice Calculates ceil(a×b÷denominator) with full precision. /// @notice Throws if result overflows a uint256 or denominator == 0 /// @param a The multiplicand /// @param b The multiplier /// @param denominator The divisor /// @return result The 256-bit result function mulDivRoundingUp( uint256 a, uint256 b, uint256 denominator ) internal pure returns (uint256 result) { unchecked { result = mulDiv(a, b, denominator); if (mulmod(a, b, denominator) > 0) { require(result < type(uint256).max); result++; } } } } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/libraries/FixedCast.sol pragma solidity 0.8.10; library FixedCast { uint256 internal constant ONE_256 = 1e18; // 18 decimal places uint256 internal constant ONE_16 = 1e4; // 4 decimal places /// @dev casts a uint16 to a FixedPoint uint256 with 18 decimals function toUint256Fixed(uint16 value) internal pure returns (uint256) { uint256 multiplier = ONE_256 / ONE_16; return (uint256(value) * multiplier); } /// @dev casts a FixedPoint uint256 to a uint16 with 4 decimals function toUint16Fixed(uint256 value) internal pure returns (uint16) { uint256 divisor = ONE_256 / ONE_16; uint256 ret256 = value / divisor; require(ret256 <= type(uint16).max, "OVLV1: FixedCast out of bounds"); return uint16(ret256); } } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/utils/Errors.sol // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity 0.8.10; // solhint-disable /** * @dev Reverts if `condition` is false, with a revert reason containing `errorCode`. Only codes up to 999 are * supported. */ function _require(bool condition, uint256 errorCode) pure { if (!condition) _revert(errorCode); } /** * @dev Reverts with a revert reason containing `errorCode`. Only codes up to 999 are supported. */ function _revert(uint256 errorCode) pure { // We're going to dynamically create a revert string based on the error code, with the following format: // 'BAL#{errorCode}' // where the code is left-padded with zeroes to three digits (so they range from 000 to 999). // // We don't have revert strings embedded in the contract to save bytecode size: it takes much less space to store a // number (8 to 16 bits) than the individual string characters. // // The dynamic string creation algorithm that follows could be implemented in Solidity, but assembly allows for a // much denser implementation, again saving bytecode size. Given this function unconditionally reverts, this is a // safe place to rely on it without worrying about how its usage might affect e.g. memory contents. assembly { // First, we need to compute the ASCII representation of the error code. We assume that it is in the 0-999 // range, so we only need to convert three digits. To convert the digits to ASCII, we add 0x30, the value for // the '0' character. let units := add(mod(errorCode, 10), 0x30) errorCode := div(errorCode, 10) let tenths := add(mod(errorCode, 10), 0x30) errorCode := div(errorCode, 10) let hundreds := add(mod(errorCode, 10), 0x30) // With the individual characters, we can now construct the full string. The "BAL#" part is a known constant // (0x42414c23): we simply shift this by 24 (to provide space for the 3 bytes of the error code), and add the // characters to it, each shifted by a multiple of 8. // The revert reason is then shifted left by 200 bits (256 minus the length of the string, 7 characters * 8 bits // per character = 56) to locate it in the most significant part of the 256 slot (the beginning of a byte // array). let revertReason := shl( 200, add(0x42414c23000000, add(add(units, shl(8, tenths)), shl(16, hundreds))) ) // We can now encode the reason in memory, which can be safely overwritten as we're about to revert. The encoded // message will have the following layout: // [ revert reason identifier ] [ string location offset ] [ string length ] [ string contents ] // The Solidity revert reason identifier is 0x08c739a0, the function selector of the Error(string) function. We // also write zeroes to the next 28 bytes of memory, but those are about to be overwritten. mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000) // Next is the offset to the location of the string, which will be placed immediately after (20 bytes away). mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) // The string length is fixed: 7 characters. mstore(0x24, 7) // Finally, the string itself is stored. mstore(0x44, revertReason) // Even if the string is only 7 bytes long, we need to return a full 32 byte slot containing it. The length of // the encoded message is therefore 4 + 32 + 32 + 32 = 100. revert(0, 100) } } library Errors { // Math uint256 internal constant ADD_OVERFLOW = 0; uint256 internal constant SUB_OVERFLOW = 1; uint256 internal constant SUB_UNDERFLOW = 2; uint256 internal constant MUL_OVERFLOW = 3; uint256 internal constant ZERO_DIVISION = 4; uint256 internal constant DIV_INTERNAL = 5; uint256 internal constant X_OUT_OF_BOUNDS = 6; uint256 internal constant Y_OUT_OF_BOUNDS = 7; uint256 internal constant PRODUCT_OUT_OF_BOUNDS = 8; uint256 internal constant INVALID_EXPONENT = 9; // Input uint256 internal constant OUT_OF_BOUNDS = 100; uint256 internal constant UNSORTED_ARRAY = 101; uint256 internal constant UNSORTED_TOKENS = 102; uint256 internal constant INPUT_LENGTH_MISMATCH = 103; uint256 internal constant ZERO_TOKEN = 104; // Shared pools uint256 internal constant MIN_TOKENS = 200; uint256 internal constant MAX_TOKENS = 201; uint256 internal constant MAX_SWAP_FEE_PERCENTAGE = 202; uint256 internal constant MIN_SWAP_FEE_PERCENTAGE = 203; uint256 internal constant MINIMUM_BPT = 204; uint256 internal constant CALLER_NOT_VAULT = 205; uint256 internal constant UNINITIALIZED = 206; uint256 internal constant BPT_IN_MAX_AMOUNT = 207; uint256 internal constant BPT_OUT_MIN_AMOUNT = 208; uint256 internal constant EXPIRED_PERMIT = 209; uint256 internal constant NOT_TWO_TOKENS = 210; uint256 internal constant DISABLED = 211; // Pools uint256 internal constant MIN_AMP = 300; uint256 internal constant MAX_AMP = 301; uint256 internal constant MIN_WEIGHT = 302; uint256 internal constant MAX_STABLE_TOKENS = 303; uint256 internal constant MAX_IN_RATIO = 304; uint256 internal constant MAX_OUT_RATIO = 305; uint256 internal constant MIN_BPT_IN_FOR_TOKEN_OUT = 306; uint256 internal constant MAX_OUT_BPT_FOR_TOKEN_IN = 307; uint256 internal constant NORMALIZED_WEIGHT_INVARIANT = 308; uint256 internal constant INVALID_TOKEN = 309; uint256 internal constant UNHANDLED_JOIN_KIND = 310; uint256 internal constant ZERO_INVARIANT = 311; uint256 internal constant ORACLE_INVALID_SECONDS_QUERY = 312; uint256 internal constant ORACLE_NOT_INITIALIZED = 313; uint256 internal constant ORACLE_QUERY_TOO_OLD = 314; uint256 internal constant ORACLE_INVALID_INDEX = 315; uint256 internal constant ORACLE_BAD_SECS = 316; uint256 internal constant AMP_END_TIME_TOO_CLOSE = 317; uint256 internal constant AMP_ONGOING_UPDATE = 318; uint256 internal constant AMP_RATE_TOO_HIGH = 319; uint256 internal constant AMP_NO_ONGOING_UPDATE = 320; uint256 internal constant STABLE_INVARIANT_DIDNT_CONVERGE = 321; uint256 internal constant STABLE_GET_BALANCE_DIDNT_CONVERGE = 322; uint256 internal constant RELAYER_NOT_CONTRACT = 323; uint256 internal constant BASE_POOL_RELAYER_NOT_CALLED = 324; uint256 internal constant REBALANCING_RELAYER_REENTERED = 325; uint256 internal constant GRADUAL_UPDATE_TIME_TRAVEL = 326; uint256 internal constant SWAPS_DISABLED = 327; uint256 internal constant CALLER_IS_NOT_LBP_OWNER = 328; uint256 internal constant PRICE_RATE_OVERFLOW = 329; uint256 internal constant INVALID_JOIN_EXIT_KIND_WHILE_SWAPS_DISABLED = 330; uint256 internal constant WEIGHT_CHANGE_TOO_FAST = 331; uint256 internal constant LOWER_GREATER_THAN_UPPER_TARGET = 332; uint256 internal constant UPPER_TARGET_TOO_HIGH = 333; uint256 internal constant UNHANDLED_BY_LINEAR_POOL = 334; uint256 internal constant OUT_OF_TARGET_RANGE = 335; uint256 internal constant UNHANDLED_EXIT_KIND = 336; uint256 internal constant UNAUTHORIZED_EXIT = 337; uint256 internal constant MAX_MANAGEMENT_SWAP_FEE_PERCENTAGE = 338; uint256 internal constant UNHANDLED_BY_MANAGED_POOL = 339; uint256 internal constant UNHANDLED_BY_PHANTOM_POOL = 340; uint256 internal constant TOKEN_DOES_NOT_HAVE_RATE_PROVIDER = 341; uint256 internal constant INVALID_INITIALIZATION = 342; uint256 internal constant OUT_OF_NEW_TARGET_RANGE = 343; uint256 internal constant UNAUTHORIZED_OPERATION = 344; uint256 internal constant UNINITIALIZED_POOL_CONTROLLER = 345; // Lib uint256 internal constant REENTRANCY = 400; uint256 internal constant SENDER_NOT_ALLOWED = 401; uint256 internal constant PAUSED = 402; uint256 internal constant PAUSE_WINDOW_EXPIRED = 403; uint256 internal constant MAX_PAUSE_WINDOW_DURATION = 404; uint256 internal constant MAX_BUFFER_PERIOD_DURATION = 405; uint256 internal constant INSUFFICIENT_BALANCE = 406; uint256 internal constant INSUFFICIENT_ALLOWANCE = 407; uint256 internal constant ERC20_TRANSFER_FROM_ZERO_ADDRESS = 408; uint256 internal constant ERC20_TRANSFER_TO_ZERO_ADDRESS = 409; uint256 internal constant ERC20_MINT_TO_ZERO_ADDRESS = 410; uint256 internal constant ERC20_BURN_FROM_ZERO_ADDRESS = 411; uint256 internal constant ERC20_APPROVE_FROM_ZERO_ADDRESS = 412; uint256 internal constant ERC20_APPROVE_TO_ZERO_ADDRESS = 413; uint256 internal constant ERC20_TRANSFER_EXCEEDS_ALLOWANCE = 414; uint256 internal constant ERC20_DECREASED_ALLOWANCE_BELOW_ZERO = 415; uint256 internal constant ERC20_TRANSFER_EXCEEDS_BALANCE = 416; uint256 internal constant ERC20_BURN_EXCEEDS_ALLOWANCE = 417; uint256 internal constant SAFE_ERC20_CALL_FAILED = 418; uint256 internal constant ADDRESS_INSUFFICIENT_BALANCE = 419; uint256 internal constant ADDRESS_CANNOT_SEND_VALUE = 420; uint256 internal constant SAFE_CAST_VALUE_CANT_FIT_INT256 = 421; uint256 internal constant GRANT_SENDER_NOT_ADMIN = 422; uint256 internal constant REVOKE_SENDER_NOT_ADMIN = 423; uint256 internal constant RENOUNCE_SENDER_NOT_ALLOWED = 424; uint256 internal constant BUFFER_PERIOD_EXPIRED = 425; uint256 internal constant CALLER_IS_NOT_OWNER = 426; uint256 internal constant NEW_OWNER_IS_ZERO = 427; uint256 internal constant CODE_DEPLOYMENT_FAILED = 428; uint256 internal constant CALL_TO_NON_CONTRACT = 429; uint256 internal constant LOW_LEVEL_CALL_FAILED = 430; uint256 internal constant NOT_PAUSED = 431; uint256 internal constant ADDRESS_ALREADY_ALLOWLISTED = 432; uint256 internal constant ADDRESS_NOT_ALLOWLISTED = 433; uint256 internal constant ERC20_BURN_EXCEEDS_BALANCE = 434; // Vault uint256 internal constant INVALID_POOL_ID = 500; uint256 internal constant CALLER_NOT_POOL = 501; uint256 internal constant SENDER_NOT_ASSET_MANAGER = 502; uint256 internal constant USER_DOESNT_ALLOW_RELAYER = 503; uint256 internal constant INVALID_SIGNATURE = 504; uint256 internal constant EXIT_BELOW_MIN = 505; uint256 internal constant JOIN_ABOVE_MAX = 506; uint256 internal constant SWAP_LIMIT = 507; uint256 internal constant SWAP_DEADLINE = 508; uint256 internal constant CANNOT_SWAP_SAME_TOKEN = 509; uint256 internal constant UNKNOWN_AMOUNT_IN_FIRST_SWAP = 510; uint256 internal constant MALCONSTRUCTED_MULTIHOP_SWAP = 511; uint256 internal constant INTERNAL_BALANCE_OVERFLOW = 512; uint256 internal constant INSUFFICIENT_INTERNAL_BALANCE = 513; uint256 internal constant INVALID_ETH_INTERNAL_BALANCE = 514; uint256 internal constant INVALID_POST_LOAN_BALANCE = 515; uint256 internal constant INSUFFICIENT_ETH = 516; uint256 internal constant UNALLOCATED_ETH = 517; uint256 internal constant ETH_TRANSFER = 518; uint256 internal constant CANNOT_USE_ETH_SENTINEL = 519; uint256 internal constant TOKENS_MISMATCH = 520; uint256 internal constant TOKEN_NOT_REGISTERED = 521; uint256 internal constant TOKEN_ALREADY_REGISTERED = 522; uint256 internal constant TOKENS_ALREADY_SET = 523; uint256 internal constant TOKENS_LENGTH_MUST_BE_2 = 524; uint256 internal constant NONZERO_TOKEN_BALANCE = 525; uint256 internal constant BALANCE_TOTAL_OVERFLOW = 526; uint256 internal constant POOL_NO_TOKENS = 527; uint256 internal constant INSUFFICIENT_FLASH_LOAN_BALANCE = 528; // Fees uint256 internal constant SWAP_FEE_PERCENTAGE_TOO_HIGH = 600; uint256 internal constant FLASH_LOAN_FEE_PERCENTAGE_TOO_HIGH = 601; uint256 internal constant INSUFFICIENT_FLASH_LOAN_FEE_AMOUNT = 602; } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/libraries/LogExpMath.sol // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the “Software”), to deal in the // Software without restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the // Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // COPIED AND MODIFIED FROM: // @balancer-v2-monorepo/pkg/solidity-utils/contracts/math/LogExpMath.sol // XXX for changes // XXX: 0.8.10; unchecked functions pragma solidity 0.8.10; /* solhint-disable */ /** * @dev Exponentiation and logarithm functions for 18 decimal fixed point numbers (both base and exponent/argument). * * Exponentiation and logarithm with arbitrary bases (x^y and log_x(y)) are implemented by conversion to natural * exponentiation and logarithm (where the base is Euler's number). * * @author Fernando Martinelli - @fernandomartinelli * @author Sergio Yuhjtman - @sergioyuhjtman * @author Daniel Fernandez - @dmf7z */ library LogExpMath { // All fixed point multiplications and divisions are inlined. This means we need to divide by ONE when multiplying // two numbers, and multiply by ONE when dividing them. // All arguments and return values are 18 decimal fixed point numbers. int256 constant ONE_18 = 1e18; // Internally, intermediate values are computed with higher precision as 20 decimal fixed point numbers, and in the // case of ln36, 36 decimals. int256 constant ONE_20 = 1e20; int256 constant ONE_36 = 1e36; // The domain of natural exponentiation is bound by the word size and number of decimals used. // // Because internally the result will be stored using 20 decimals, the largest possible result is // (2^255 - 1) / 10^20, which makes the largest exponent ln((2^255 - 1) / 10^20) = 130.700829182905140221. // The smallest possible result is 10^(-18), which makes largest negative argument // ln(10^(-18)) = -41.446531673892822312. // We use 130.0 and -41.0 to have some safety margin. int256 constant MAX_NATURAL_EXPONENT = 130e18; int256 constant MIN_NATURAL_EXPONENT = -41e18; // Bounds for ln_36's argument. Both ln(0.9) and ln(1.1) can be represented with 36 decimal places in a fixed point // 256 bit integer. int256 constant LN_36_LOWER_BOUND = ONE_18 - 1e17; int256 constant LN_36_UPPER_BOUND = ONE_18 + 1e17; uint256 constant MILD_EXPONENT_BOUND = 2**254 / uint256(ONE_20); // 18 decimal constants int256 constant x0 = 128000000000000000000; // 2ˆ7 int256 constant a0 = 38877084059945950922200000000000000000000000000000000000; // eˆ(x0) (no decimals) int256 constant x1 = 64000000000000000000; // 2ˆ6 int256 constant a1 = 6235149080811616882910000000; // eˆ(x1) (no decimals) // 20 decimal constants int256 constant x2 = 3200000000000000000000; // 2ˆ5 int256 constant a2 = 7896296018268069516100000000000000; // eˆ(x2) int256 constant x3 = 1600000000000000000000; // 2ˆ4 int256 constant a3 = 888611052050787263676000000; // eˆ(x3) int256 constant x4 = 800000000000000000000; // 2ˆ3 int256 constant a4 = 298095798704172827474000; // eˆ(x4) int256 constant x5 = 400000000000000000000; // 2ˆ2 int256 constant a5 = 5459815003314423907810; // eˆ(x5) int256 constant x6 = 200000000000000000000; // 2ˆ1 int256 constant a6 = 738905609893065022723; // eˆ(x6) int256 constant x7 = 100000000000000000000; // 2ˆ0 int256 constant a7 = 271828182845904523536; // eˆ(x7) int256 constant x8 = 50000000000000000000; // 2ˆ-1 int256 constant a8 = 164872127070012814685; // eˆ(x8) int256 constant x9 = 25000000000000000000; // 2ˆ-2 int256 constant a9 = 128402541668774148407; // eˆ(x9) int256 constant x10 = 12500000000000000000; // 2ˆ-3 int256 constant a10 = 113314845306682631683; // eˆ(x10) int256 constant x11 = 6250000000000000000; // 2ˆ-4 int256 constant a11 = 106449445891785942956; // eˆ(x11) /** * @dev Exponentiation (x^y) with unsigned 18 decimal fixed point base and exponent. * * Reverts if ln(x) * y is smaller than `MIN_NATURAL_EXPONENT`, or larger than `MAX_NATURAL_EXPONENT`. */ function pow(uint256 x, uint256 y) internal pure returns (uint256) { unchecked { if (y == 0) { // We solve the 0^0 indetermination by making it equal one. return uint256(ONE_18); } if (x == 0) { return 0; } // Instead of computing x^y directly, we instead rely on the properties of logarithms and exponentiation to // arrive at that result. In particular, exp(ln(x)) = x, and ln(x^y) = y * ln(x). This means // x^y = exp(y * ln(x)). // The ln function takes a signed value, so we need to make sure x fits in the signed 256 bit range. _require(x < 2**255, Errors.X_OUT_OF_BOUNDS); int256 x_int256 = int256(x); // We will compute y * ln(x) in a single step. Depending on the value of x, we can either use ln or ln_36. In // both cases, we leave the division by ONE_18 (due to fixed point multiplication) to the end. // This prevents y * ln(x) from overflowing, and at the same time guarantees y fits in the signed 256 bit range. _require(y < MILD_EXPONENT_BOUND, Errors.Y_OUT_OF_BOUNDS); int256 y_int256 = int256(y); int256 logx_times_y; if (LN_36_LOWER_BOUND < x_int256 && x_int256 < LN_36_UPPER_BOUND) { int256 ln_36_x = _ln_36(x_int256); // ln_36_x has 36 decimal places, so multiplying by y_int256 isn't as straightforward, since we can't just // bring y_int256 to 36 decimal places, as it might overflow. Instead, we perform two 18 decimal // multiplications and add the results: one with the first 18 decimals of ln_36_x, and one with the // (downscaled) last 18 decimals. logx_times_y = ((ln_36_x / ONE_18) * y_int256 + ((ln_36_x % ONE_18) * y_int256) / ONE_18); } else { logx_times_y = _ln(x_int256) * y_int256; } logx_times_y /= ONE_18; // Finally, we compute exp(y * ln(x)) to arrive at x^y _require( MIN_NATURAL_EXPONENT <= logx_times_y && logx_times_y <= MAX_NATURAL_EXPONENT, Errors.PRODUCT_OUT_OF_BOUNDS ); return uint256(exp(logx_times_y)); } } /** * @dev Natural exponentiation (e^x) with signed 18 decimal fixed point exponent. * * Reverts if `x` is smaller than MIN_NATURAL_EXPONENT, or larger than `MAX_NATURAL_EXPONENT`. */ function exp(int256 x) internal pure returns (int256) { _require(x >= MIN_NATURAL_EXPONENT && x <= MAX_NATURAL_EXPONENT, Errors.INVALID_EXPONENT); unchecked { if (x < 0) { // We only handle positive exponents: e^(-x) is computed as 1 / e^x. We can safely make x positive since it // fits in the signed 256 bit range (as it is larger than MIN_NATURAL_EXPONENT). // Fixed point division requires multiplying by ONE_18. return ((ONE_18 * ONE_18) / exp(-x)); } // First, we use the fact that e^(x+y) = e^x * e^y to decompose x into a sum of powers of two, which we call x_n, // where x_n == 2^(7 - n), and e^x_n = a_n has been precomputed. We choose the first x_n, x0, to equal 2^7 // because all larger powers are larger than MAX_NATURAL_EXPONENT, and therefore not present in the // decomposition. // At the end of this process we will have the product of all e^x_n = a_n that apply, and the remainder of this // decomposition, which will be lower than the smallest x_n. // exp(x) = k_0 * a_0 * k_1 * a_1 * ... + k_n * a_n * exp(remainder), where each k_n equals either 0 or 1. // We mutate x by subtracting x_n, making it the remainder of the decomposition. // The first two a_n (e^(2^7) and e^(2^6)) are too large if stored as 18 decimal numbers, and could cause // intermediate overflows. Instead we store them as plain integers, with 0 decimals. // Additionally, x0 + x1 is larger than MAX_NATURAL_EXPONENT, which means they will not both be present in the // decomposition. // For each x_n, we test if that term is present in the decomposition (if x is larger than it), and if so deduct // it and compute the accumulated product. int256 firstAN; if (x >= x0) { x -= x0; firstAN = a0; } else if (x >= x1) { x -= x1; firstAN = a1; } else { firstAN = 1; // One with no decimal places } // We now transform x into a 20 decimal fixed point number, to have enhanced precision when computing the // smaller terms. x *= 100; // `product` is the accumulated product of all a_n (except a0 and a1), which starts at 20 decimal fixed point // one. Recall that fixed point multiplication requires dividing by ONE_20. int256 product = ONE_20; if (x >= x2) { x -= x2; product = (product * a2) / ONE_20; } if (x >= x3) { x -= x3; product = (product * a3) / ONE_20; } if (x >= x4) { x -= x4; product = (product * a4) / ONE_20; } if (x >= x5) { x -= x5; product = (product * a5) / ONE_20; } if (x >= x6) { x -= x6; product = (product * a6) / ONE_20; } if (x >= x7) { x -= x7; product = (product * a7) / ONE_20; } if (x >= x8) { x -= x8; product = (product * a8) / ONE_20; } if (x >= x9) { x -= x9; product = (product * a9) / ONE_20; } // x10 and x11 are unnecessary here since we have high enough precision already. // Now we need to compute e^x, where x is small (in particular, it is smaller than x9). We use the Taylor series // expansion for e^x: 1 + x + (x^2 / 2!) + (x^3 / 3!) + ... + (x^n / n!). int256 seriesSum = ONE_20; // The initial one in the sum, with 20 decimal places. int256 term; // Each term in the sum, where the nth term is (x^n / n!). // The first term is simply x. term = x; seriesSum += term; // Each term (x^n / n!) equals the previous one times x, divided by n. Since x is a fixed point number, // multiplying by it requires dividing by ONE_20, but dividing by the non-fixed point n values does not. term = ((term * x) / ONE_20) / 2; seriesSum += term; term = ((term * x) / ONE_20) / 3; seriesSum += term; term = ((term * x) / ONE_20) / 4; seriesSum += term; term = ((term * x) / ONE_20) / 5; seriesSum += term; term = ((term * x) / ONE_20) / 6; seriesSum += term; term = ((term * x) / ONE_20) / 7; seriesSum += term; term = ((term * x) / ONE_20) / 8; seriesSum += term; term = ((term * x) / ONE_20) / 9; seriesSum += term; term = ((term * x) / ONE_20) / 10; seriesSum += term; term = ((term * x) / ONE_20) / 11; seriesSum += term; term = ((term * x) / ONE_20) / 12; seriesSum += term; // 12 Taylor terms are sufficient for 18 decimal precision. // We now have the first a_n (with no decimals), and the product of all other a_n present, and the Taylor // approximation of the exponentiation of the remainder (both with 20 decimals). All that remains is to multiply // all three (one 20 decimal fixed point multiplication, dividing by ONE_20, and one integer multiplication), // and then drop two digits to return an 18 decimal value. return (((product * seriesSum) / ONE_20) * firstAN) / 100; } } /** * @dev Logarithm (log(arg, base), with signed 18 decimal fixed point base and argument. */ function log(int256 arg, int256 base) internal pure returns (int256) { // This performs a simple base change: log(arg, base) = ln(arg) / ln(base). unchecked { // Both logBase and logArg are computed as 36 decimal fixed point numbers, either by using ln_36, or by // upscaling. int256 logBase; if (LN_36_LOWER_BOUND < base && base < LN_36_UPPER_BOUND) { logBase = _ln_36(base); } else { logBase = _ln(base) * ONE_18; } int256 logArg; if (LN_36_LOWER_BOUND < arg && arg < LN_36_UPPER_BOUND) { logArg = _ln_36(arg); } else { logArg = _ln(arg) * ONE_18; } // When dividing, we multiply by ONE_18 to arrive at a result with 18 decimal places return (logArg * ONE_18) / logBase; } } /** * @dev Natural logarithm (ln(a)) with signed 18 decimal fixed point argument. */ function ln(int256 a) internal pure returns (int256) { // The real natural logarithm is not defined for negative numbers or zero. _require(a > 0, Errors.OUT_OF_BOUNDS); unchecked { if (LN_36_LOWER_BOUND < a && a < LN_36_UPPER_BOUND) { return _ln_36(a) / ONE_18; } else { return _ln(a); } } } /** * @dev Internal natural logarithm (ln(a)) with signed 18 decimal fixed point argument. */ function _ln(int256 a) private pure returns (int256) { unchecked { if (a < ONE_18) { // Since ln(a^k) = k * ln(a), we can compute ln(a) as ln(a) = ln((1/a)^(-1)) = - ln((1/a)). If a is less // than one, 1/a will be greater than one, and this if statement will not be entered in the recursive call. // Fixed point division requires multiplying by ONE_18. return (-_ln((ONE_18 * ONE_18) / a)); } // First, we use the fact that ln^(a * b) = ln(a) + ln(b) to decompose ln(a) into a sum of powers of two, which // we call x_n, where x_n == 2^(7 - n), which are the natural logarithm of precomputed quantities a_n (that is, // ln(a_n) = x_n). We choose the first x_n, x0, to equal 2^7 because the exponential of all larger powers cannot // be represented as 18 fixed point decimal numbers in 256 bits, and are therefore larger than a. // At the end of this process we will have the sum of all x_n = ln(a_n) that apply, and the remainder of this // decomposition, which will be lower than the smallest a_n. // ln(a) = k_0 * x_0 + k_1 * x_1 + ... + k_n * x_n + ln(remainder), where each k_n equals either 0 or 1. // We mutate a by subtracting a_n, making it the remainder of the decomposition. // For reasons related to how `exp` works, the first two a_n (e^(2^7) and e^(2^6)) are not stored as fixed point // numbers with 18 decimals, but instead as plain integers with 0 decimals, so we need to multiply them by // ONE_18 to convert them to fixed point. // For each a_n, we test if that term is present in the decomposition (if a is larger than it), and if so divide // by it and compute the accumulated sum. int256 sum = 0; if (a >= a0 * ONE_18) { a /= a0; // Integer, not fixed point division sum += x0; } if (a >= a1 * ONE_18) { a /= a1; // Integer, not fixed point division sum += x1; } // All other a_n and x_n are stored as 20 digit fixed point numbers, so we convert the sum and a to this format. sum *= 100; a *= 100; // Because further a_n are 20 digit fixed point numbers, we multiply by ONE_20 when dividing by them. if (a >= a2) { a = (a * ONE_20) / a2; sum += x2; } if (a >= a3) { a = (a * ONE_20) / a3; sum += x3; } if (a >= a4) { a = (a * ONE_20) / a4; sum += x4; } if (a >= a5) { a = (a * ONE_20) / a5; sum += x5; } if (a >= a6) { a = (a * ONE_20) / a6; sum += x6; } if (a >= a7) { a = (a * ONE_20) / a7; sum += x7; } if (a >= a8) { a = (a * ONE_20) / a8; sum += x8; } if (a >= a9) { a = (a * ONE_20) / a9; sum += x9; } if (a >= a10) { a = (a * ONE_20) / a10; sum += x10; } if (a >= a11) { a = (a * ONE_20) / a11; sum += x11; } // a is now a small number (smaller than a_11, which roughly equals 1.06). This means we can use a Taylor series // that converges rapidly for values of `a` close to one - the same one used in ln_36. // Let z = (a - 1) / (a + 1). // ln(a) = 2 * (z + z^3 / 3 + z^5 / 5 + z^7 / 7 + ... + z^(2 * n + 1) / (2 * n + 1)) // Recall that 20 digit fixed point division requires multiplying by ONE_20, and multiplication requires // division by ONE_20. int256 z = ((a - ONE_20) * ONE_20) / (a + ONE_20); int256 z_squared = (z * z) / ONE_20; // num is the numerator of the series: the z^(2 * n + 1) term int256 num = z; // seriesSum holds the accumulated sum of each term in the series, starting with the initial z int256 seriesSum = num; // In each step, the numerator is multiplied by z^2 num = (num * z_squared) / ONE_20; seriesSum += num / 3; num = (num * z_squared) / ONE_20; seriesSum += num / 5; num = (num * z_squared) / ONE_20; seriesSum += num / 7; num = (num * z_squared) / ONE_20; seriesSum += num / 9; num = (num * z_squared) / ONE_20; seriesSum += num / 11; // 6 Taylor terms are sufficient for 36 decimal precision. // Finally, we multiply by 2 (non fixed point) to compute ln(remainder) seriesSum *= 2; // We now have the sum of all x_n present, and the Taylor approximation of the logarithm of the remainder (both // with 20 decimals). All that remains is to sum these two, and then drop two digits to return a 18 decimal // value. return (sum + seriesSum) / 100; } } /** * @dev Intrnal high precision (36 decimal places) natural logarithm (ln(x)) with signed 18 decimal fixed point argument, * for x close to one. * * Should only be used if x is between LN_36_LOWER_BOUND and LN_36_UPPER_BOUND. */ function _ln_36(int256 x) private pure returns (int256) { unchecked { // Since ln(1) = 0, a value of x close to one will yield a very small result, which makes using 36 digits // worthwhile. // First, we transform x to a 36 digit fixed point value. x *= ONE_18; // We will use the following Taylor expansion, which converges very rapidly. Let z = (x - 1) / (x + 1). // ln(x) = 2 * (z + z^3 / 3 + z^5 / 5 + z^7 / 7 + ... + z^(2 * n + 1) / (2 * n + 1)) // Recall that 36 digit fixed point division requires multiplying by ONE_36, and multiplication requires // division by ONE_36. int256 z = ((x - ONE_36) * ONE_36) / (x + ONE_36); int256 z_squared = (z * z) / ONE_36; // num is the numerator of the series: the z^(2 * n + 1) term int256 num = z; // seriesSum holds the accumulated sum of each term in the series, starting with the initial z int256 seriesSum = num; // In each step, the numerator is multiplied by z^2 num = (num * z_squared) / ONE_36; seriesSum += num / 3; num = (num * z_squared) / ONE_36; seriesSum += num / 5; num = (num * z_squared) / ONE_36; seriesSum += num / 7; num = (num * z_squared) / ONE_36; seriesSum += num / 9; num = (num * z_squared) / ONE_36; seriesSum += num / 11; num = (num * z_squared) / ONE_36; seriesSum += num / 13; num = (num * z_squared) / ONE_36; seriesSum += num / 15; // 8 Taylor terms are sufficient for 36 decimal precision. // All that remains is multiplying by 2 (non fixed point). return seriesSum * 2; } } } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/libraries/FixedPoint.sol // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // // COPIED AND MODIFIED FROM: // @balancer-v2-monorepo/pkg/solidity-utils/contracts/math/FixedPoint.sol // XXX for changes // XXX: 0.8.10; removed requires for overflow checks pragma solidity 0.8.10; /* solhint-disable private-vars-leading-underscore */ library FixedPoint { uint256 internal constant ONE = 1e18; // 18 decimal places uint256 internal constant TWO = 2 * ONE; uint256 internal constant FOUR = 4 * ONE; uint256 internal constant MAX_POW_RELATIVE_ERROR = 10000; // 10^(-14) // Minimum base for the power function when the exponent is 'free' (larger than ONE). uint256 internal constant MIN_POW_BASE_FREE_EXPONENT = 0.7e18; function add(uint256 a, uint256 b) internal pure returns (uint256) { // Fixed Point addition is the same as regular checked addition uint256 c = a + b; return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { // Fixed Point addition is the same as regular checked addition uint256 c = a - b; return c; } /// @notice a - b but floors to zero if a <= b /// XXX: subFloor implementation function subFloor(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a > b ? a - b : 0; return c; } function mulDown(uint256 a, uint256 b) internal pure returns (uint256) { uint256 product = a * b; return product / ONE; } function mulUp(uint256 a, uint256 b) internal pure returns (uint256) { uint256 product = a * b; if (product == 0) { return 0; } else { // The traditional divUp formula is: // divUp(x, y) := (x + y - 1) / y // To avoid intermediate overflow in the addition, we distribute the division and get: // divUp(x, y) := (x - 1) / y + 1 // Note that this requires x != 0, which we already tested for. return ((product - 1) / ONE) + 1; } } function divDown(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } else { uint256 aInflated = a * ONE; return aInflated / b; } } function divUp(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } else { uint256 aInflated = a * ONE; // The traditional divUp formula is: // divUp(x, y) := (x + y - 1) / y // To avoid intermediate overflow in the addition, we distribute the division and get: // divUp(x, y) := (x - 1) / y + 1 // Note that this requires x != 0, which we already tested for. return ((aInflated - 1) / b) + 1; } } /** * @dev Returns x^y, assuming both are fixed point numbers, rounding down. * The result is guaranteed to not be above the true value (that is, * the error function expected - actual is always positive). */ function powDown(uint256 x, uint256 y) internal pure returns (uint256) { // Optimize for when y equals 1.0, 2.0 or 4.0, as those are very simple // to implement and occur often in 50/50 and 80/20 Weighted Pools // XXX: checks for y == 0, x == ONE, x == 0 if (0 == y || x == ONE) { return ONE; } else if (x == 0) { return 0; } else if (y == ONE) { return x; } else if (y == TWO) { return mulDown(x, x); } else if (y == FOUR) { uint256 square = mulDown(x, x); return mulDown(square, square); } else { uint256 raw = LogExpMath.pow(x, y); uint256 maxError = add(mulUp(raw, MAX_POW_RELATIVE_ERROR), 1); if (raw < maxError) { return 0; } else { return sub(raw, maxError); } } } /** * @dev Returns x^y, assuming both are fixed point numbers, rounding up. * The result is guaranteed to not be below the true value (that is, * the error function expected - actual is always negative). */ function powUp(uint256 x, uint256 y) internal pure returns (uint256) { // Optimize for when y equals 1.0, 2.0 or 4.0, as those are very simple // to implement and occur often in 50/50 and 80/20 Weighted Pools // XXX: checks for y == 0, x == ONE, x == 0 if (0 == y || x == ONE) { return ONE; } else if (x == 0) { return 0; } else if (y == ONE) { return x; } else if (y == TWO) { return mulUp(x, x); } else if (y == FOUR) { uint256 square = mulUp(x, x); return mulUp(square, square); } else { uint256 raw = LogExpMath.pow(x, y); uint256 maxError = add(mulUp(raw, MAX_POW_RELATIVE_ERROR), 1); return add(raw, maxError); } } /** * @dev Returns e^x, assuming x is a fixed point number, rounding down. * The result is guaranteed to not be above the true value (that is, * the error function expected - actual is always positive). * XXX: expDown implementation */ function expDown(uint256 x) internal pure returns (uint256) { if (x == 0) { return ONE; } require(x < 2**255, "FixedPoint: x out of bounds"); int256 x_int256 = int256(x); uint256 raw = uint256(LogExpMath.exp(x_int256)); uint256 maxError = add(mulUp(raw, MAX_POW_RELATIVE_ERROR), 1); if (raw < maxError) { return 0; } else { return sub(raw, maxError); } } /** * @dev Returns e^x, assuming x is a fixed point number, rounding up. * The result is guaranteed to not be below the true value (that is, * the error function expected - actual is always negative). * XXX: expUp implementation */ function expUp(uint256 x) internal pure returns (uint256) { if (x == 0) { return ONE; } require(x < 2**255, "FixedPoint: x out of bounds"); int256 x_int256 = int256(x); uint256 raw = uint256(LogExpMath.exp(x_int256)); uint256 maxError = add(mulUp(raw, MAX_POW_RELATIVE_ERROR), 1); return add(raw, maxError); } /** * @dev Returns log_b(a), assuming a, b are fixed point numbers, rounding down. * The result is guaranteed to not be above the true value (that is, * the error function expected - actual is always positive). * XXX: logDown implementation */ function logDown(uint256 a, uint256 b) internal pure returns (int256) { require(a > 0 && a < 2**255, "FixedPoint: a out of bounds"); require(b > 0 && b < 2**255, "FixedPoint: b out of bounds"); int256 arg = int256(a); int256 base = int256(b); int256 raw = LogExpMath.log(arg, base); // NOTE: see @openzeppelin/contracts/utils/math/SignedMath.sol#L37 uint256 rawAbs; unchecked { rawAbs = uint256(raw >= 0 ? raw : -raw); } uint256 maxError = add(mulUp(rawAbs, MAX_POW_RELATIVE_ERROR), 1); return raw - int256(maxError); } /** * @dev Returns log_b(a), assuming a, b are fixed point numbers, rounding up. * The result is guaranteed to not be below the true value (that is, * the error function expected - actual is always negative). * XXX: logUp implementation */ function logUp(uint256 a, uint256 b) internal pure returns (int256) { require(a > 0 && a < 2**255, "FixedPoint: a out of bounds"); require(b > 0 && b < 2**255, "FixedPoint: b out of bounds"); int256 arg = int256(a); int256 base = int256(b); int256 raw = LogExpMath.log(arg, base); // NOTE: see @openzeppelin/contracts/utils/math/SignedMath.sol#L37 uint256 rawAbs; unchecked { rawAbs = uint256(raw >= 0 ? raw : -raw); } uint256 maxError = add(mulUp(rawAbs, MAX_POW_RELATIVE_ERROR), 1); return raw + int256(maxError); } /** * @dev Returns the complement of a value (1 - x), capped to 0 if x is larger than 1. * * Useful when computing the complement for values with some level of relative error, * as it strips this error and prevents intermediate negative values. */ function complement(uint256 x) internal pure returns (uint256) { return (x < ONE) ? (ONE - x) : 0; } } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/libraries/Cast.sol pragma solidity 0.8.10; library Cast { /// @dev casts an uint256 to an uint32 bounded by uint32 range of values /// @dev to avoid reverts and overflows function toUint32Bounded(uint256 value) internal pure returns (uint32) { uint32 value32 = (value <= type(uint32).max) ? uint32(value) : type(uint32).max; return value32; } /// @dev casts an int256 to an int192 bounded by int192 range of values /// @dev to avoid reverts and overflows function toInt192Bounded(int256 value) internal pure returns (int192) { int192 value192 = value < type(int192).min ? type(int192).min : (value > type(int192).max ? type(int192).max : int192(value)); return value192; } } // File: @openzeppelin/contracts/utils/math/SignedMath.sol // OpenZeppelin Contracts (last updated v4.5.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/libraries/Tick.sol pragma solidity 0.8.10; library Tick { using FixedPoint for uint256; using SignedMath for int256; uint256 internal constant ONE = 1e18; uint256 internal constant PRICE_BASE = 1.0001e18; int256 internal constant MAX_TICK_256 = 120e22; int256 internal constant MIN_TICK_256 = -41e22; /// @notice Computes the tick associated with the given price /// @notice where price = 1.0001 ** tick /// @dev FixedPoint lib constraints on min/max natural exponent of /// @dev -41e18, 130e18 respectively, means min/max tick will be /// @dev -41e18/ln(1.0001), 130e18/ln(1.0001), respectively (w some buffer) function priceToTick(uint256 price) internal pure returns (int24) { int256 tick256 = price.logDown(PRICE_BASE); require(tick256 >= MIN_TICK_256 && tick256 <= MAX_TICK_256, "OVLV1: tick out of bounds"); // tick256 is FixedPoint format with 18 decimals. Divide by ONE // then truncate to int24 return int24(tick256 / int256(ONE)); } /// @notice Computes the price associated with the given tick /// @notice where price = 1.0001 ** tick /// @dev FixedPoint lib constraints on min/max natural exponent of /// @dev -41e18, 130e18 respectively, means min/max tick will be /// @dev -41e18/ln(1.0001), 130e18/ln(1.0001), respectively (w some buffer) function tickToPrice(int24 tick) internal pure returns (uint256) { // tick needs to be converted to Fixed point format with 18 decimals // to use FixedPoint powUp int256 tick256 = int256(tick) * int256(ONE); require(tick256 >= MIN_TICK_256 && tick256 <= MAX_TICK_256, "OVLV1: tick out of bounds"); uint256 pow = uint256(tick256.abs()); return (tick256 >= 0 ? PRICE_BASE.powDown(pow) : ONE.divDown(PRICE_BASE.powUp(pow))); } } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/libraries/Roller.sol pragma solidity 0.8.10; library Roller { using Cast for uint256; using Cast for int256; using FixedPoint for uint256; using SignedMath for int256; struct Snapshot { uint32 timestamp; // time last snapshot was taken uint32 window; // window (length of time) over which will decay int192 accumulator; // accumulator value which will decay to zero over window } /// @dev returns the stored accumulator value as an int256 function cumulative(Snapshot memory self) internal view returns (int256) { return int256(self.accumulator); } /// @dev adjusts accumulator value downward linearly over time. /// @dev accumulator should go to zero as one window passes function transform( Snapshot memory self, uint256 timestamp, uint256 window, int256 value ) internal view returns (Snapshot memory) { uint32 timestamp32 = uint32(timestamp); // truncated by compiler // int/uint256 values to use in calculations uint256 dt = timestamp32 >= self.timestamp ? uint256(timestamp32 - self.timestamp) : uint256(2**32) + uint256(timestamp32) - uint256(self.timestamp); uint256 snapWindow = uint256(self.window); int256 snapAccumulator = cumulative(self); if (dt >= snapWindow || snapWindow == 0) { // if one window has passed, prior value has decayed to zero return Snapshot({ timestamp: timestamp32, window: window.toUint32Bounded(), accumulator: value.toInt192Bounded() }); } // otherwise, calculate fraction of value remaining given linear decay. // fraction of value to take off due to decay (linear drift toward zero) // is fraction of windowLast that has elapsed since timestampLast snapAccumulator = (snapAccumulator * int256(snapWindow - dt)) / int256(snapWindow); // add in the new value for accumulator now int256 accumulatorNow = snapAccumulator + value; if (accumulatorNow == 0) { // if accumulator now is zero, windowNow is simply window return Snapshot({ timestamp: timestamp32, window: window.toUint32Bounded(), accumulator: 0 }); } // recalculate windowNow_ for future decay as a value weighted average time // of time left in windowLast for accumulatorLast and window for value // vwat = (|accumulatorLastWithDecay| * (windowLast - dt) + |value| * window) / // (|accumulatorLastWithDecay| + |value|) uint256 w1 = snapAccumulator.abs(); uint256 w2 = value.abs(); uint256 windowNow = (w1 * (snapWindow - dt) + w2 * window) / (w1 + w2); return Snapshot({ timestamp: timestamp32, window: windowNow.toUint32Bounded(), accumulator: accumulatorNow.toInt192Bounded() }); } } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/libraries/Oracle.sol pragma solidity 0.8.10; library Oracle { struct Data { uint256 timestamp; uint256 microWindow; uint256 macroWindow; uint256 priceOverMicroWindow; // p(now) averaged over micro uint256 priceOverMacroWindow; // p(now) averaged over macro uint256 priceOneMacroWindowAgo; // p(now - macro) avg over macro uint256 reserveOverMicroWindow; // r(now) in ovl averaged over micro bool hasReserve; // whether oracle has manipulable reserve pool } } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/interfaces/feeds/IOverlayV1Feed.sol pragma solidity 0.8.10; interface IOverlayV1Feed { // immutables function feedFactory() external view returns (address); function microWindow() external view returns (uint256); function macroWindow() external view returns (uint256); // returns freshest possible data from oracle function latest() external view returns (Oracle.Data memory); } // File: @openzeppelin/contracts/access/IAccessControl.sol // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; } // File: @openzeppelin/contracts/access/IAccessControlEnumerable.sol // OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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 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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount ) external returns (bool); } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/interfaces/IOverlayV1Token.sol pragma solidity 0.8.10; bytes32 constant MINTER_ROLE = keccak256("MINTER"); bytes32 constant BURNER_ROLE = keccak256("BURNER"); bytes32 constant GOVERNOR_ROLE = keccak256("GOVERNOR"); bytes32 constant GUARDIAN_ROLE = keccak256("GUARDIAN"); interface IOverlayV1Token is IAccessControlEnumerable, IERC20 { // mint/burn function mint(address _recipient, uint256 _amount) external; function burn(uint256 _amount) external; } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/interfaces/IOverlayV1Deployer.sol pragma solidity 0.8.10; interface IOverlayV1Deployer { function factory() external view returns (address); function ovl() external view returns (address); function deploy(address feed) external returns (address); function parameters() external view returns ( address ovl_, address feed_, address factory_ ); } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/libraries/Risk.sol pragma solidity 0.8.10; library Risk { enum Parameters { K, // funding constant Lmbda, // market impact constant Delta, // bid-ask static spread constant CapPayoff, // payoff cap CapNotional, // initial notional cap CapLeverage, // initial leverage cap CircuitBreakerWindow, // trailing window for circuit breaker CircuitBreakerMintTarget, // target worst case inflation rate over trailing window MaintenanceMarginFraction, // maintenance margin (mm) constant MaintenanceMarginBurnRate, // burn rate for mm constant LiquidationFeeRate, // liquidation fee charged on liquidate TradingFeeRate, // trading fee charged on build/unwind MinCollateral, // minimum ovl collateral to open position PriceDriftUpperLimit, // upper limit for feed price changes since last update AverageBlockTime // average block time of the respective chain } /// @notice Gets the value associated with the given parameter type function get(uint256[15] storage self, Parameters name) internal view returns (uint256) { return self[uint256(name)]; } /// @notice Sets the value associated with the given parameter type function set( uint256[15] storage self, Parameters name, uint256 value ) internal { self[uint256(name)] = value; } } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/interfaces/IOverlayV1Market.sol pragma solidity 0.8.10; interface IOverlayV1Market { // immutables function ovl() external view returns (IOverlayV1Token); function feed() external view returns (address); function factory() external view returns (address); // risk params function params(uint256 idx) external view returns (uint256); // oi related quantities function oiLong() external view returns (uint256); function oiShort() external view returns (uint256); function oiLongShares() external view returns (uint256); function oiShortShares() external view returns (uint256); // rollers function snapshotVolumeBid() external view returns ( uint32 timestamp_, uint32 window_, int192 accumulator_ ); function snapshotVolumeAsk() external view returns ( uint32 timestamp_, uint32 window_, int192 accumulator_ ); function snapshotMinted() external view returns ( uint32 timestamp_, uint32 window_, int192 accumulator_ ); // positions function positions(bytes32 key) external view returns ( uint96 notionalInitial_, uint96 debtInitial_, int24 midTick_, int24 entryTick_, bool isLong_, bool liquidated_, uint240 oiShares_, uint16 fractionRemaining_ ); // update related quantities function timestampUpdateLast() external view returns (uint256); // cached risk calcs function dpUpperLimit() external view returns (uint256); // emergency shutdown function isShutdown() external view returns (bool); // initializes market function initialize(uint256[15] memory params) external; // position altering functions function build( uint256 collateral, uint256 leverage, bool isLong, uint256 priceLimit ) external returns (uint256 positionId_); function unwind( uint256 positionId, uint256 fraction, uint256 priceLimit ) external; function liquidate(address owner, uint256 positionId) external; // updates market function update() external returns (Oracle.Data memory); // sanity check on data fetched from oracle in case of manipulation function dataIsValid(Oracle.Data memory) external view returns (bool); // current open interest after funding payments transferred function oiAfterFunding( uint256 oiOverweight, uint256 oiUnderweight, uint256 timeElapsed ) external view returns (uint256 oiOverweight_, uint256 oiUnderweight_); // current open interest cap with adjustments for circuit breaker if market has // printed a lot in recent past function capOiAdjustedForCircuitBreaker(uint256 cap) external view returns (uint256); // bound on open interest cap from circuit breaker function circuitBreaker(Roller.Snapshot memory snapshot, uint256 cap) external view returns (uint256); // current notional cap with adjustments to prevent front-running // trade and back-running trade function capNotionalAdjustedForBounds(Oracle.Data memory data, uint256 cap) external view returns (uint256); // bound on open interest cap to mitigate front-running attack function frontRunBound(Oracle.Data memory data) external view returns (uint256); // bound on open interest cap to mitigate back-running attack function backRunBound(Oracle.Data memory data) external view returns (uint256); // transforms notional into number of contracts (open interest) function oiFromNotional(uint256 notional, uint256 midPrice) external view returns (uint256); // bid price given oracle data and recent volume function bid(Oracle.Data memory data, uint256 volume) external view returns (uint256 bid_); // ask price given oracle data and recent volume function ask(Oracle.Data memory data, uint256 volume) external view returns (uint256 ask_); // risk parameter setter function setRiskParam(Risk.Parameters name, uint256 value) external; // emergency shutdown market function shutdown() external; // emergency withdraw collateral after shutdown function emergencyWithdraw(uint256 positionId) external; } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/interfaces/IOverlayV1Factory.sol pragma solidity 0.8.10; interface IOverlayV1Factory { // risk param bounds function PARAMS_MIN(uint256 idx) external view returns (uint256); function PARAMS_MAX(uint256 idx) external view returns (uint256); // immutables function ovl() external view returns (IOverlayV1Token); function deployer() external view returns (IOverlayV1Deployer); // global parameter function feeRecipient() external view returns (address); // registry of supported feed factories function isFeedFactory(address feedFactory) external view returns (bool); // registry of markets; for a given feed address, returns associated market function getMarket(address feed) external view returns (address market_); // registry of deployed markets by factory function isMarket(address market) external view returns (bool); // adding feed factory to allowed feed types function addFeedFactory(address feedFactory) external; // removing feed factory from allowed feed types function removeFeedFactory(address feedFactory) external; // deploy new market function deployMarket( address feedFactory, address feed, uint256[15] calldata params ) external returns (address market_); // per-market risk parameter setters function setRiskParam( address feed, Risk.Parameters name, uint256 value ) external; // fee repository setter function setFeeRecipient(address _feeRecipient) external; } // File: @openzeppelin/contracts/utils/math/Math.sol // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`. // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`. // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a // good first aproximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1; uint256 x = a; if (x >> 128 > 0) { x >>= 128; result <<= 64; } if (x >> 64 > 0) { x >>= 64; result <<= 32; } if (x >> 32 > 0) { x >>= 32; result <<= 16; } if (x >> 16 > 0) { x >>= 16; result <<= 8; } if (x >> 8 > 0) { x >>= 8; result <<= 4; } if (x >> 4 > 0) { x >>= 4; result <<= 2; } if (x >> 2 > 0) { result <<= 1; } // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { uint256 result = sqrt(a); if (rounding == Rounding.Up && result * result < a) { result += 1; } return result; } } // File: https://github.com/overlay-market/v1-core/blob/main/contracts/libraries/Position.sol pragma solidity 0.8.10; library Position { using FixedCast for uint16; using FixedCast for uint256; using FixedPoint for uint256; uint256 internal constant ONE = 1e18; /// @dev immutables: notionalInitial, debtInitial, midTick, entryTick, isLong /// @dev mutables: liquidated, oiShares, fractionRemaining struct Info { uint96 notionalInitial; // initial notional = collateral * leverage uint96 debtInitial; // initial debt = notional - collateral int24 midTick; // midPrice = 1.0001 ** midTick at build int24 entryTick; // entryPrice = 1.0001 ** entryTick at build bool isLong; // whether long or short bool liquidated; // whether has been liquidated (mutable) uint240 oiShares; // current shares of aggregate open interest on side (mutable) uint16 fractionRemaining; // fraction of initial position remaining (mutable) } /*/////////////////////////////////////////////////////////////// POSITIONS MAPPING FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Retrieves a position from positions mapping function get( mapping(bytes32 => Info) storage self, address owner, uint256 id ) internal view returns (Info memory position_) { position_ = self[keccak256(abi.encodePacked(owner, id))]; } /// @notice Stores a position in positions mapping function set( mapping(bytes32 => Info) storage self, address owner, uint256 id, Info memory position ) internal { self[keccak256(abi.encodePacked(owner, id))] = position; } /*/////////////////////////////////////////////////////////////// POSITION CAST GETTER FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Computes the position's initial notional cast to uint256 function _notionalInitial(Info memory self) private pure returns (uint256) { return uint256(self.notionalInitial); } /// @notice Computes the position's initial debt cast to uint256 function _debtInitial(Info memory self) private pure returns (uint256) { return uint256(self.debtInitial); } /// @notice Computes the position's current shares of open interest /// @notice cast to uint256 function _oiShares(Info memory self) private pure returns (uint256) { return uint256(self.oiShares); } /// @notice Computes the fraction remaining of the position cast to uint256 function _fractionRemaining(Info memory self) private pure returns (uint256) { return self.fractionRemaining.toUint256Fixed(); } /*/////////////////////////////////////////////////////////////// POSITION EXISTENCE FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Whether the position exists /// @dev Is false if position has been liquidated or fraction remaining == 0 function exists(Info memory self) internal pure returns (bool exists_) { return (!self.liquidated && self.fractionRemaining > 0); } /*/////////////////////////////////////////////////////////////// POSITION FRACTION REMAINING FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Gets the current fraction remaining of the initial position function getFractionRemaining(Info memory self) internal pure returns (uint256) { return _fractionRemaining(self); } /// @notice Computes an updated fraction remaining of the initial position /// @notice given fractionRemoved unwound/liquidated from remaining position function updatedFractionRemaining(Info memory self, uint256 fractionRemoved) internal pure returns (uint16) { require(fractionRemoved <= ONE, "OVLV1:fraction>max"); uint256 fractionRemaining = _fractionRemaining(self).mulDown(ONE - fractionRemoved); return fractionRemaining.toUint16Fixed(); } /*/////////////////////////////////////////////////////////////// POSITION PRICE FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Computes the midPrice of the position at entry cast to uint256 /// @dev Will be slightly different (tol of 1bps) vs actual /// @dev midPrice at build given tick resolution limited to 1bps /// @dev Only affects value() calc below and thus PnL slightly function midPriceAtEntry(Info memory self) internal pure returns (uint256 midPrice_) { midPrice_ = Tick.tickToPrice(self.midTick); } /// @notice Computes the entryPrice of the position cast to uint256 /// @dev Will be slightly different (tol of 1bps) vs actual /// @dev entryPrice at build given tick resolution limited to 1bps /// @dev Only affects value() calc below and thus PnL slightly function entryPrice(Info memory self) internal pure returns (uint256 entryPrice_) { entryPrice_ = Tick.tickToPrice(self.entryTick); } /*/////////////////////////////////////////////////////////////// POSITION OI FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Computes the amount of shares of open interest to issue /// @notice a newly built position /// @dev use mulDiv function calcOiShares( uint256 oi, uint256 oiTotalOnSide, uint256 oiTotalSharesOnSide ) internal pure returns (uint256 oiShares_) { oiShares_ = (oiTotalOnSide == 0 || oiTotalSharesOnSide == 0) ? oi : FullMath.mulDiv(oi, oiTotalSharesOnSide, oiTotalOnSide); } /// @notice Computes the position's initial open interest cast to uint256 /// @dev oiInitial = Q / midPriceAtEntry /// @dev Will be slightly different (tol of 1bps) vs actual oi at build /// @dev given midTick resolution limited to 1bps /// @dev Only affects value() calc below and thus PnL slightly function _oiInitial(Info memory self) private pure returns (uint256) { uint256 q = _notionalInitial(self); uint256 mid = midPriceAtEntry(self); return q.divDown(mid); } /*/////////////////////////////////////////////////////////////// POSITION FRACTIONAL GETTER FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Computes the initial notional of position when built /// @notice accounting for amount of position remaining /// @dev use mulUp to avoid rounding leftovers on unwind function notionalInitial(Info memory self, uint256 fraction) internal pure returns (uint256) { uint256 fractionRemaining = _fractionRemaining(self); uint256 notionalForRemaining = _notionalInitial(self).mulUp(fractionRemaining); return notionalForRemaining.mulUp(fraction); } /// @notice Computes the initial open interest of position when built /// @notice accounting for amount of position remaining /// @dev use mulUp to avoid rounding leftovers on unwind function oiInitial(Info memory self, uint256 fraction) internal pure returns (uint256) { uint256 fractionRemaining = _fractionRemaining(self); uint256 oiInitialForRemaining = _oiInitial(self).mulUp(fractionRemaining); return oiInitialForRemaining.mulUp(fraction); } /// @notice Computes the current shares of open interest position holds /// @notice on pos.isLong side of the market /// @dev use mulDown to avoid giving excess shares to pos owner on unwind function oiSharesCurrent(Info memory self, uint256 fraction) internal pure returns (uint256) { uint256 oiSharesForRemaining = _oiShares(self); // WARNING: must mulDown to avoid giving excess oi shares return oiSharesForRemaining.mulDown(fraction); } /// @notice Computes the current debt position holds accounting /// @notice for amount of position remaining /// @dev use mulUp to avoid rounding leftovers on unwind function debtInitial(Info memory self, uint256 fraction) internal pure returns (uint256) { uint256 fractionRemaining = _fractionRemaining(self); uint256 debtForRemaining = _debtInitial(self).mulUp(fractionRemaining); return debtForRemaining.mulUp(fraction); } /// @notice Computes the current open interest of remaining position accounting for /// @notice potential funding payments between long/short sides /// @dev returns zero when oiShares = oiTotalOnSide = oiTotalSharesOnSide = 0 to avoid /// @dev div by zero errors /// @dev use mulDiv function oiCurrent( Info memory self, uint256 fraction, uint256 oiTotalOnSide, uint256 oiTotalSharesOnSide ) internal pure returns (uint256) { uint256 oiShares = oiSharesCurrent(self, fraction); if (oiShares == 0 || oiTotalOnSide == 0 || oiTotalSharesOnSide == 0) return 0; return FullMath.mulDiv(oiShares, oiTotalOnSide, oiTotalSharesOnSide); } /// @notice Computes the remaining position's cost cast to uint256 function cost(Info memory self, uint256 fraction) internal pure returns (uint256) { uint256 posNotionalInitial = notionalInitial(self, fraction); uint256 posDebt = debtInitial(self, fraction); // should always be > 0 but use subFloor to be safe w reverts uint256 posCost = posNotionalInitial; posCost = posCost.subFloor(posDebt); return posCost; } /*/////////////////////////////////////////////////////////////// POSITION CALC FUNCTIONS //////////////////////////////////////////////////////////////*/ /// @notice Computes the value of remaining position /// @dev Floors to zero, so won't properly compute if self is underwater function value( Info memory self, uint256 fraction, uint256 oiTotalOnSide, uint256 oiTotalSharesOnSide, uint256 currentPrice, uint256 capPayoff ) internal pure returns (uint256 val_) { uint256 posOiInitial = oiInitial(self, fraction); uint256 posNotionalInitial = notionalInitial(self, fraction); uint256 posDebt = debtInitial(self, fraction); uint256 posOiCurrent = oiCurrent(self, fraction, oiTotalOnSide, oiTotalSharesOnSide); uint256 posEntryPrice = entryPrice(self); // NOTE: PnL = +/- oiCurrent * [currentPrice - entryPrice]; ... (w/o capPayoff) // NOTE: fundingPayments = notionalInitial * ( oiCurrent / oiInitial - 1 ) // NOTE: value = collateralInitial + PnL + fundingPayments // NOTE: = notionalInitial - debt + PnL + fundingPayments if (self.isLong) { // val = notionalInitial * oiCurrent / oiInitial // + oiCurrent * min[currentPrice, entryPrice * (1 + capPayoff)] // - oiCurrent * entryPrice - debt val_ = posNotionalInitial.mulUp(posOiCurrent).divUp(posOiInitial) + Math.min( posOiCurrent.mulUp(currentPrice), posOiCurrent.mulUp(posEntryPrice).mulUp(ONE + capPayoff) ); // floor to 0 val_ = val_.subFloor(posDebt + posOiCurrent.mulUp(posEntryPrice)); } else { // NOTE: capPayoff >= 1, so no need to include w short // val = notionalInitial * oiCurrent / oiInitial + oiCurrent * entryPrice // - oiCurrent * currentPrice - debt val_ = posNotionalInitial.mulUp(posOiCurrent).divUp(posOiInitial) + posOiCurrent.mulUp(posEntryPrice); // floor to 0 val_ = val_.subFloor(posDebt + posOiCurrent.mulUp(currentPrice)); } } /// @notice Computes the current notional of remaining position including PnL /// @dev Floors to debt if value <= 0 function notionalWithPnl( Info memory self, uint256 fraction, uint256 oiTotalOnSide, uint256 oiTotalSharesOnSide, uint256 currentPrice, uint256 capPayoff ) internal pure returns (uint256 notionalWithPnl_) { uint256 posValue = value( self, fraction, oiTotalOnSide, oiTotalSharesOnSide, currentPrice, capPayoff ); uint256 posDebt = debtInitial(self, fraction); notionalWithPnl_ = posValue + posDebt; } /// @notice Computes the trading fees to be imposed on remaining position /// @notice for build/unwind function tradingFee( Info memory self, uint256 fraction, uint256 oiTotalOnSide, uint256 oiTotalSharesOnSide, uint256 currentPrice, uint256 capPayoff, uint256 tradingFeeRate ) internal pure returns (uint256 tradingFee_) { uint256 posNotional = notionalWithPnl( self, fraction, oiTotalOnSide, oiTotalSharesOnSide, currentPrice, capPayoff ); tradingFee_ = posNotional.mulUp(tradingFeeRate); } /// @notice Whether a position can be liquidated /// @dev is true when value * (1 - liq fee rate) < maintenance margin /// @dev liq fees are reward given to liquidator function liquidatable( Info memory self, uint256 oiTotalOnSide, uint256 oiTotalSharesOnSide, uint256 currentPrice, uint256 capPayoff, uint256 maintenanceMarginFraction, uint256 liquidationFeeRate ) internal pure returns (bool can_) { uint256 fraction = ONE; uint256 posNotionalInitial = notionalInitial(self, fraction); if (self.liquidated || self.fractionRemaining == 0) { // already been liquidated or doesn't exist // latter covers edge case of val == 0 and MM + liq fee == 0 return false; } uint256 val = value( self, fraction, oiTotalOnSide, oiTotalSharesOnSide, currentPrice, capPayoff ); uint256 maintenanceMargin = posNotionalInitial.mulUp(maintenanceMarginFraction); uint256 liquidationFee = val.mulDown(liquidationFeeRate); can_ = val < maintenanceMargin + liquidationFee; } } // File: github/overlay-market/v1-core/contracts/OverlayV1Market.sol pragma solidity 0.8.10; contract OverlayV1Market is IOverlayV1Market { using FixedCast for uint16; using FixedCast for uint256; using FixedPoint for uint256; using Oracle for Oracle.Data; using Position for mapping(bytes32 => Position.Info); using Position for Position.Info; using Risk for uint256[15]; using Roller for Roller.Snapshot; // internal constants uint256 internal constant ONE = 1e18; // 18 decimal places // cap for euler exponent powers; SEE: ./libraries/LogExpMath.sol::pow // using ~ 1/2 library max for substantial padding uint256 internal constant MAX_NATURAL_EXPONENT = 20e18; // immutables IOverlayV1Token public immutable ovl; // ovl token address public immutable feed; // oracle feed address public immutable factory; // factory that deployed this market // risk params uint256[15] public params; // params.idx order based on Risk.Parameters enum // aggregate oi quantities uint256 public oiLong; uint256 public oiShort; uint256 public oiLongShares; uint256 public oiShortShares; // rollers Roller.Snapshot public override snapshotVolumeBid; // snapshot of recent volume on bid Roller.Snapshot public override snapshotVolumeAsk; // snapshot of recent volume on ask Roller.Snapshot public override snapshotMinted; // snapshot of recent PnL minted/burned // positions mapping(bytes32 => Position.Info) public override positions; uint256 private _totalPositions; // data from last call to update uint256 public timestampUpdateLast; // cached risk calcs uint256 public dpUpperLimit; // e**(+priceDriftUpperLimit * macroWindow) // emergency shutdown bool public isShutdown; // factory modifier for governance sensitive functions modifier onlyFactory() { require(msg.sender == factory, "OVLV1: !factory"); _; } // not shutdown modifier for regular functionality modifier notShutdown() { require(!isShutdown, "OVLV1: shutdown"); _; } // shutdown modifier for emergencies modifier hasShutdown() { require(isShutdown, "OVLV1: !shutdown"); _; } // events for core functions event Build( address indexed sender, // address that initiated build (owns position) uint256 positionId, // id of built position uint256 oi, // oi of position at build uint256 debt, // debt of position at build bool isLong, // whether is long or short uint256 price // entry price ); event Unwind( address indexed sender, // address that initiated unwind (owns position) uint256 positionId, // id of unwound position uint256 fraction, // fraction of position unwound int256 mint, // total amount minted/burned (+/-) at unwind uint256 price // exit price ); event Liquidate( address indexed sender, // address that initiated liquidate address indexed owner, // address that owned the liquidated position uint256 positionId, // id of the liquidated position int256 mint, // total amount burned (-) at liquidate uint256 price // liquidation price ); event EmergencyWithdraw( address indexed sender, // address that initiated withdraw (owns position) uint256 positionId, // id of withdrawn position uint256 collateral // total amount of collateral withdrawn ); constructor() { (address _ovl, address _feed, address _factory) = IOverlayV1Deployer(msg.sender) .parameters(); ovl = IOverlayV1Token(_ovl); feed = _feed; factory = _factory; } /// @notice initializes the market and its risk params /// @notice called only once by factory on deployment function initialize(uint256[15] memory _params) external onlyFactory { // initialize update data Oracle.Data memory data = IOverlayV1Feed(feed).latest(); require(_midFromFeed(data) > 0, "OVLV1:!data"); timestampUpdateLast = block.timestamp; // check risk params valid uint256 _capLeverage = _params[uint256(Risk.Parameters.CapLeverage)]; uint256 _delta = _params[uint256(Risk.Parameters.Delta)]; uint256 _maintenanceMarginFraction = _params[ uint256(Risk.Parameters.MaintenanceMarginFraction) ]; uint256 _liquidationFeeRate = _params[uint256(Risk.Parameters.LiquidationFeeRate)]; require( _capLeverage <= ONE.divDown( 2 * _delta + _maintenanceMarginFraction.divDown(ONE - _liquidationFeeRate) ), "OVLV1: max lev immediately liquidatable" ); uint256 _priceDriftUpperLimit = _params[uint256(Risk.Parameters.PriceDriftUpperLimit)]; require( _priceDriftUpperLimit * data.macroWindow < MAX_NATURAL_EXPONENT, "OVLV1: price drift exceeds max exp" ); _cacheRiskCalc(Risk.Parameters.PriceDriftUpperLimit, _priceDriftUpperLimit); // set the risk params for (uint256 i = 0; i < _params.length; i++) { params[i] = _params[i]; } } /// @dev builds a new position function build( uint256 collateral, uint256 leverage, bool isLong, uint256 priceLimit ) external notShutdown returns (uint256 positionId_) { require(leverage >= ONE, "OVLV1:lev<min"); require(leverage <= params.get(Risk.Parameters.CapLeverage), "OVLV1:lev>max"); require(collateral >= params.get(Risk.Parameters.MinCollateral), "OVLV1:collateral<min"); uint256 oi; uint256 debt; uint256 price; uint256 tradingFee; // avoids stack too deep { // call to update before any effects Oracle.Data memory data = update(); // calculate notional, oi, and trading fees. fees charged on notional // and added to collateral transferred in uint256 notional = collateral.mulUp(leverage); uint256 midPrice = _midFromFeed(data); oi = oiFromNotional(notional, midPrice); // check have more than zero number of contracts built require(oi > 0, "OVLV1:oi==0"); // calculate debt and trading fees. fees charged on notional // and added to collateral transferred in debt = notional - collateral; tradingFee = notional.mulUp(params.get(Risk.Parameters.TradingFeeRate)); // calculate current notional cap adjusted for front run // and back run bounds. transform into a cap on open interest uint256 capOi = oiFromNotional( capNotionalAdjustedForBounds(data, params.get(Risk.Parameters.CapNotional)), midPrice ); // longs get the ask and shorts get the bid on build // register the additional volume on either the ask or bid // where volume = oi / capOi price = isLong ? ask(data, _registerVolumeAsk(data, oi, capOi)) : bid(data, _registerVolumeBid(data, oi, capOi)); // check price hasn't changed more than max slippage specified by trader require(isLong ? price <= priceLimit : price >= priceLimit, "OVLV1:slippage>max"); // add new position's open interest to the side's aggregate oi value // and increase number of oi shares issued uint256 oiShares = _addToOiAggregates(oi, capOi, isLong); // assemble position info data // check position is not immediately liquidatable prior to storing Position.Info memory pos = Position.Info({ notionalInitial: uint96(notional), // won't overflow as capNotional max is 8e24 debtInitial: uint96(debt), midTick: Tick.priceToTick(midPrice), entryTick: Tick.priceToTick(price), isLong: isLong, liquidated: false, oiShares: uint240(oiShares), // won't overflow as oiShares ~ notional/mid fractionRemaining: ONE.toUint16Fixed() }); require( !pos.liquidatable( isLong ? oiLong : oiShort, isLong ? oiLongShares : oiShortShares, midPrice, // mid price used on liquidations params.get(Risk.Parameters.CapPayoff), params.get(Risk.Parameters.MaintenanceMarginFraction), params.get(Risk.Parameters.LiquidationFeeRate) ), "OVLV1:liquidatable" ); // store the position info data positionId_ = _totalPositions; positions.set(msg.sender, positionId_, pos); _totalPositions++; } // emit build event emit Build(msg.sender, positionId_, oi, debt, isLong, price); // transfer in the OVL collateral needed to back the position + fees // trading fees charged as a percentage on notional size of position ovl.transferFrom(msg.sender, address(this), collateral + tradingFee); // send trading fees to trading fee recipient ovl.transfer(IOverlayV1Factory(factory).feeRecipient(), tradingFee); } /// @dev unwinds fraction of an existing position function unwind( uint256 positionId, uint256 fraction, uint256 priceLimit ) external notShutdown { require(fraction <= ONE, "OVLV1:fraction>max"); // only keep 4 decimal precision (1 bps) for fraction given // pos.fractionRemaining only to 4 decimals fraction = fraction.toUint16Fixed().toUint256Fixed(); require(fraction > 0, "OVLV1:fraction<min"); uint256 value; uint256 cost; uint256 price; uint256 tradingFee; // avoids stack too deep { // call to update before any effects Oracle.Data memory data = update(); // check position exists Position.Info memory pos = positions.get(msg.sender, positionId); require(pos.exists(), "OVLV1:!position"); // cache for gas savings uint256 oiTotalOnSide = pos.isLong ? oiLong : oiShort; uint256 oiTotalSharesOnSide = pos.isLong ? oiLongShares : oiShortShares; // check position not liquidatable otherwise can't unwind require( !pos.liquidatable( oiTotalOnSide, oiTotalSharesOnSide, _midFromFeed(data), // mid price used on liquidations params.get(Risk.Parameters.CapPayoff), params.get(Risk.Parameters.MaintenanceMarginFraction), params.get(Risk.Parameters.LiquidationFeeRate) ), "OVLV1:liquidatable" ); // longs get the bid and shorts get the ask on unwind // register the additional volume on either the ask or bid // where volume = oi / capOi // current cap only adjusted for bounds (no circuit breaker so traders // don't get stuck in a position) uint256 capOi = oiFromNotional( capNotionalAdjustedForBounds(data, params.get(Risk.Parameters.CapNotional)), _midFromFeed(data) ); price = pos.isLong ? bid( data, _registerVolumeBid( data, pos.oiCurrent(fraction, oiTotalOnSide, oiTotalSharesOnSide), capOi ) ) : ask( data, _registerVolumeAsk( data, pos.oiCurrent(fraction, oiTotalOnSide, oiTotalSharesOnSide), capOi ) ); // check price hasn't changed more than max slippage specified by trader require(pos.isLong ? price >= priceLimit : price <= priceLimit, "OVLV1:slippage>max"); // calculate the value and cost of the position for pnl determinations // and amount to transfer uint256 capPayoff = params.get(Risk.Parameters.CapPayoff); value = pos.value(fraction, oiTotalOnSide, oiTotalSharesOnSide, price, capPayoff); cost = pos.cost(fraction); // calculate the trading fee as % on notional uint256 tradingFeeRate = params.get(Risk.Parameters.TradingFeeRate); tradingFee = pos.tradingFee( fraction, oiTotalOnSide, oiTotalSharesOnSide, price, capPayoff, tradingFeeRate ); tradingFee = Math.min(tradingFee, value); // if value < tradingFee // subtract unwound open interest from the side's aggregate oi value // and decrease number of oi shares issued // NOTE: use subFloor to avoid reverts with oi rounding issues if (pos.isLong) { oiLong = oiLong.subFloor( pos.oiCurrent(fraction, oiTotalOnSide, oiTotalSharesOnSide) ); oiLongShares -= pos.oiSharesCurrent(fraction); } else { oiShort = oiShort.subFloor( pos.oiCurrent(fraction, oiTotalOnSide, oiTotalSharesOnSide) ); oiShortShares -= pos.oiSharesCurrent(fraction); } // register the amount to be minted/burned // capPayoff prevents overflow reverts with int256 cast _registerMintOrBurn(int256(value) - int256(cost)); // store the updated position info data by reducing the // oiShares and fraction remaining of initial position pos.oiShares -= uint240(pos.oiSharesCurrent(fraction)); pos.fractionRemaining = pos.updatedFractionRemaining(fraction); positions.set(msg.sender, positionId, pos); } // emit unwind event emit Unwind(msg.sender, positionId, fraction, int256(value) - int256(cost), price); // mint or burn the pnl for the position if (value >= cost) { ovl.mint(address(this), value - cost); } else { ovl.burn(cost - value); } // transfer out the unwound position value less fees to trader ovl.transfer(msg.sender, value - tradingFee); // send trading fees to trading fee recipient ovl.transfer(IOverlayV1Factory(factory).feeRecipient(), tradingFee); } /// @dev liquidates a liquidatable position function liquidate(address owner, uint256 positionId) external notShutdown { uint256 value; uint256 cost; uint256 price; uint256 liquidationFee; uint256 marginToBurn; uint256 marginRemaining; // avoids stack too deep { // check position exists Position.Info memory pos = positions.get(owner, positionId); require(pos.exists(), "OVLV1:!position"); // call to update before any effects Oracle.Data memory data = update(); // cache for gas savings uint256 oiTotalOnSide = pos.isLong ? oiLong : oiShort; uint256 oiTotalSharesOnSide = pos.isLong ? oiLongShares : oiShortShares; uint256 capPayoff = params.get(Risk.Parameters.CapPayoff); // entire position should be liquidated uint256 fraction = ONE; // Use mid price without volume for liquidation (oracle price effectively) to // prevent market impact manipulation from causing unneccessary liquidations price = _midFromFeed(data); // check position is liquidatable require( pos.liquidatable( oiTotalOnSide, oiTotalSharesOnSide, price, capPayoff, params.get(Risk.Parameters.MaintenanceMarginFraction), params.get(Risk.Parameters.LiquidationFeeRate) ), "OVLV1:!liquidatable" ); // calculate the value and cost of the position for pnl determinations // and amount to transfer value = pos.value(fraction, oiTotalOnSide, oiTotalSharesOnSide, price, capPayoff); cost = pos.cost(fraction); // calculate the liquidation fee as % on remaining value // sent as reward to liquidator liquidationFee = value.mulDown(params.get(Risk.Parameters.LiquidationFeeRate)); marginRemaining = value - liquidationFee; // Reduce burn amount further by the mm burn rate, as insurance // for cases when not liquidated in time marginToBurn = marginRemaining.mulDown( params.get(Risk.Parameters.MaintenanceMarginBurnRate) ); marginRemaining -= marginToBurn; // subtract liquidated open interest from the side's aggregate oi value // and decrease number of oi shares issued // NOTE: use subFloor to avoid reverts with oi rounding issues if (pos.isLong) { oiLong = oiLong.subFloor( pos.oiCurrent(fraction, oiTotalOnSide, oiTotalSharesOnSide) ); oiLongShares -= pos.oiSharesCurrent(fraction); } else { oiShort = oiShort.subFloor( pos.oiCurrent(fraction, oiTotalOnSide, oiTotalSharesOnSide) ); oiShortShares -= pos.oiSharesCurrent(fraction); } // register the amount to be burned _registerMintOrBurn(int256(value) - int256(cost) - int256(marginToBurn)); // store the updated position info data. mark as liquidated pos.liquidated = true; pos.oiShares = 0; pos.fractionRemaining = 0; positions.set(owner, positionId, pos); } // emit liquidate event emit Liquidate( msg.sender, owner, positionId, int256(value) - int256(cost) - int256(marginToBurn), price ); // burn the pnl for the position + insurance margin ovl.burn(cost - value + marginToBurn); // transfer out the liquidation fee to liquidator for reward ovl.transfer(msg.sender, liquidationFee); // send remaining margin to trading fee recipient ovl.transfer(IOverlayV1Factory(factory).feeRecipient(), marginRemaining); } /// @dev updates market: pays funding and fetches freshest data from feed /// @dev update is called every time market is interacted with function update() public returns (Oracle.Data memory) { // pay funding for time elasped since last interaction w market _payFunding(); // fetch new oracle data from feed // applies sanity check in case of data manipulation Oracle.Data memory data = IOverlayV1Feed(feed).latest(); require(dataIsValid(data), "OVLV1:!data"); // return the latest data from feed return data; } /// @dev sanity check on data fetched from oracle in case of manipulation /// @dev rough check that log price bounded by +/- priceDriftUpperLimit * dt /// @dev when comparing priceMacro(now) vs priceMacro(now - macroWindow) function dataIsValid(Oracle.Data memory data) public view returns (bool) { // upper and lower limits are e**(+/- priceDriftUpperLimit * dt) uint256 _dpUpperLimit = dpUpperLimit; uint256 _dpLowerLimit = ONE.divDown(_dpUpperLimit); // compare current price over macro window vs price over macro window // one macro window in the past uint256 priceNow = data.priceOverMacroWindow; uint256 priceLast = data.priceOneMacroWindowAgo; if (priceLast == 0 || priceNow == 0) { // data is not valid if price is zero return false; } // price is valid if within upper and lower limits on drift given // time elapsed over one macro window uint256 dp = priceNow.divUp(priceLast); return (dp >= _dpLowerLimit && dp <= _dpUpperLimit); } /// @notice Current open interest after funding payments transferred /// @notice from overweight oi side to underweight oi side /// @dev The value of oiOverweight must be >= oiUnderweight function oiAfterFunding( uint256 oiOverweight, uint256 oiUnderweight, uint256 timeElapsed ) public view returns (uint256, uint256) { uint256 oiTotal = oiOverweight + oiUnderweight; uint256 oiImbalance = oiOverweight - oiUnderweight; uint256 oiInvariant = oiUnderweight.mulUp(oiOverweight); // If no OI or imbalance, no funding occurs. Handles div by zero case below if (oiTotal == 0 || oiImbalance == 0) { return (oiOverweight, oiUnderweight); } // draw down the imbalance by factor of e**(-2*k*t) // but min to zero if pow = 2*k*t exceeds MAX_NATURAL_EXPONENT uint256 fundingFactor; uint256 pow = 2 * params.get(Risk.Parameters.K) * timeElapsed; if (pow < MAX_NATURAL_EXPONENT) { fundingFactor = ONE.divDown(pow.expUp()); // e**(-pow) } // Decrease total aggregate open interest (i.e. oiLong + oiShort) // to compensate protocol for pro-rata share of imbalance liability // OI_tot(t) = OI_tot(0) * \ // sqrt( 1 - (OI_imb(0)/OI_tot(0))**2 * (1 - e**(-4*k*t)) ) // Guaranteed 0 <= underRoot <= 1 uint256 oiImbFraction = oiImbalance.divDown(oiTotal); uint256 underRoot = ONE - oiImbFraction.mulDown(oiImbFraction).mulDown( ONE - fundingFactor.mulDown(fundingFactor) ); // oiTotalNow guaranteed <= oiTotalBefore (burn happens) oiTotal = oiTotal.mulDown(underRoot.powDown(ONE / 2)); // Time decay imbalance: OI_imb(t) = OI_imb(0) * e**(-2*k*t) // oiImbalanceNow guaranteed <= oiImbalanceBefore oiImbalance = oiImbalance.mulDown(fundingFactor); // overweight pays underweight // use oiOver * oiUnder = invariant for oiUnderNow to avoid any // potential overflow reverts oiOverweight = (oiTotal + oiImbalance) / 2; if (oiOverweight != 0) { oiUnderweight = oiInvariant.divUp(oiOverweight); } return (oiOverweight, oiUnderweight); } /// @dev current oi cap with adjustments to lower in the event /// @dev market has printed a lot in recent past function capOiAdjustedForCircuitBreaker(uint256 cap) public view returns (uint256) { // Adjust cap downward for circuit breaker. Use snapshotMinted // but transformed to account for decay in magnitude of minted since // last snapshot taken Roller.Snapshot memory snapshot = snapshotMinted; uint256 circuitBreakerWindow = params.get(Risk.Parameters.CircuitBreakerWindow); snapshot = snapshot.transform(block.timestamp, circuitBreakerWindow, 0); cap = circuitBreaker(snapshot, cap); return cap; } /// @dev bound on oi cap from circuit breaker /// @dev Three cases: /// @dev 1. minted < 1x target amount over circuitBreakerWindow: return cap /// @dev 2. minted > 2x target amount over last circuitBreakerWindow: return 0 /// @dev 3. minted between 1x and 2x target amount: return cap * (2 - minted/target) function circuitBreaker(Roller.Snapshot memory snapshot, uint256 cap) public view returns (uint256) { int256 minted = int256(snapshot.cumulative()); uint256 circuitBreakerMintTarget = params.get(Risk.Parameters.CircuitBreakerMintTarget); if (minted <= int256(circuitBreakerMintTarget)) { return cap; } else if (minted >= 2 * int256(circuitBreakerMintTarget)) { return 0; } // case 3 (circuit breaker adjustment downward) uint256 adjustment = 2 * ONE - uint256(minted).divDown(circuitBreakerMintTarget); return cap.mulDown(adjustment); } /// @dev current notional cap with adjustments to prevent /// @dev front-running trade and back-running trade function capNotionalAdjustedForBounds(Oracle.Data memory data, uint256 cap) public view returns (uint256) { if (data.hasReserve) { // Adjust cap downward if exceeds bounds from front run attack cap = Math.min(cap, frontRunBound(data)); // Adjust cap downward if exceeds bounds from back run attack cap = Math.min(cap, backRunBound(data)); } return cap; } /// @dev bound on notional cap to mitigate front-running attack /// @dev bound = lmbda * reserveInOvl function frontRunBound(Oracle.Data memory data) public view returns (uint256) { uint256 lmbda = params.get(Risk.Parameters.Lmbda); return lmbda.mulDown(data.reserveOverMicroWindow); } /// @dev bound on notional cap to mitigate back-running attack /// @dev bound = macroWindowInBlocks * reserveInOvl * 2 * delta function backRunBound(Oracle.Data memory data) public view returns (uint256) { uint256 averageBlockTime = params.get(Risk.Parameters.AverageBlockTime); uint256 window = (data.macroWindow * ONE) / averageBlockTime; uint256 delta = params.get(Risk.Parameters.Delta); return delta.mulDown(data.reserveOverMicroWindow).mulDown(window).mulDown(2 * ONE); } /// @dev Returns the open interest in number of contracts for a given notional /// @dev Uses _midFromFeed(data) price to calculate oi: OI = Q / P function oiFromNotional(uint256 notional, uint256 midPrice) public view returns (uint256) { return notional.divDown(midPrice); } /// @dev bid price given oracle data and recent volume function bid(Oracle.Data memory data, uint256 volume) public view returns (uint256 bid_) { bid_ = Math.min(data.priceOverMicroWindow, data.priceOverMacroWindow); // add static spread (delta) and market impact (lmbda * volume) uint256 delta = params.get(Risk.Parameters.Delta); uint256 lmbda = params.get(Risk.Parameters.Lmbda); uint256 pow = delta + lmbda.mulUp(volume); require(pow < MAX_NATURAL_EXPONENT, "OVLV1:slippage>max"); bid_ = bid_.mulDown(ONE.divDown(pow.expUp())); // bid * e**(-pow) } /// @dev ask price given oracle data and recent volume function ask(Oracle.Data memory data, uint256 volume) public view returns (uint256 ask_) { ask_ = Math.max(data.priceOverMicroWindow, data.priceOverMacroWindow); // add static spread (delta) and market impact (lmbda * volume) uint256 delta = params.get(Risk.Parameters.Delta); uint256 lmbda = params.get(Risk.Parameters.Lmbda); uint256 pow = delta + lmbda.mulUp(volume); require(pow < MAX_NATURAL_EXPONENT, "OVLV1:slippage>max"); ask_ = ask_.mulUp(pow.expUp()); // ask * e**(pow) } /// @dev mid price without impact/spread given oracle data and recent volume /// @dev used for gas savings to avoid accessing storage for delta, lmbda function _midFromFeed(Oracle.Data memory data) private view returns (uint256 mid_) { mid_ = Math.average(data.priceOverMicroWindow, data.priceOverMacroWindow); } /// @dev Rolling volume adjustments on bid side to be used for market impact. /// @dev Volume values are normalized with respect to cap function _registerVolumeBid( Oracle.Data memory data, uint256 volume, uint256 cap ) private returns (uint256) { // save gas with snapshot in memory Roller.Snapshot memory snapshot = snapshotVolumeBid; int256 value = int256(volume.divUp(cap)); // calculates the decay in the rolling volume since last snapshot // and determines new window to decay over snapshot = snapshot.transform(block.timestamp, data.microWindow, value); // store the transformed snapshot snapshotVolumeBid = snapshot; // return the cumulative volume return uint256(snapshot.cumulative()); } /// @dev Rolling volume adjustments on ask side to be used for market impact. /// @dev Volume values are normalized with respect to cap function _registerVolumeAsk( Oracle.Data memory data, uint256 volume, uint256 cap ) private returns (uint256) { // save gas with snapshot in memory Roller.Snapshot memory snapshot = snapshotVolumeAsk; int256 value = int256(volume.divUp(cap)); // calculates the decay in the rolling volume since last snapshot // and determines new window to decay over snapshot = snapshot.transform(block.timestamp, data.microWindow, value); // store the transformed snapshot snapshotVolumeAsk = snapshot; // return the cumulative volume return uint256(snapshot.cumulative()); } /// @notice Rolling mint accumulator to be used for circuit breaker /// @dev value > 0 registers a mint, value <= 0 registers a burn function _registerMintOrBurn(int256 value) private returns (int256) { // save gas with snapshot in memory Roller.Snapshot memory snapshot = snapshotMinted; // calculates the decay in the rolling amount minted since last snapshot // and determines new window to decay over uint256 circuitBreakerWindow = params.get(Risk.Parameters.CircuitBreakerWindow); snapshot = snapshot.transform(block.timestamp, circuitBreakerWindow, value); // store the transformed snapshot snapshotMinted = snapshot; // return the cumulative mint amount int256 minted = snapshot.cumulative(); return minted; } /// @notice Updates the market for funding changes to open interest /// @notice since last time market was interacted with function _payFunding() private { // apply funding if at least one block has passed uint256 timeElapsed = block.timestamp - timestampUpdateLast; if (timeElapsed > 0) { // calculate adjustments to oi due to funding bool isLongOverweight = oiLong > oiShort; uint256 oiOverweight = isLongOverweight ? oiLong : oiShort; uint256 oiUnderweight = isLongOverweight ? oiShort : oiLong; (oiOverweight, oiUnderweight) = oiAfterFunding( oiOverweight, oiUnderweight, timeElapsed ); // pay funding oiLong = isLongOverweight ? oiOverweight : oiUnderweight; oiShort = isLongOverweight ? oiUnderweight : oiOverweight; // set last time market was updated timestampUpdateLast = block.timestamp; } } /// @notice Adds open interest and open interest shares to aggregate storage /// @notice pairs (oiLong, oiLongShares) or (oiShort, oiShortShares) /// @return oiShares_ as the new position's shares of aggregate open interest function _addToOiAggregates( uint256 oi, uint256 capOi, bool isLong ) private returns (uint256 oiShares_) { // cache for gas savings uint256 oiTotalOnSide = isLong ? oiLong : oiShort; uint256 oiTotalSharesOnSide = isLong ? oiLongShares : oiShortShares; // calculate oi shares uint256 oiShares = Position.calcOiShares(oi, oiTotalOnSide, oiTotalSharesOnSide); // add oi and oi shares to temp aggregate values oiTotalOnSide += oi; oiTotalSharesOnSide += oiShares; // check new total oi on side does not exceed capOi after // adjusted for circuit breaker uint256 capOiCircuited = capOiAdjustedForCircuitBreaker(capOi); require(oiTotalOnSide <= capOiCircuited, "OVLV1:oi>cap"); // update total aggregate oi and oi shares storage vars if (isLong) { oiLong = oiTotalOnSide; oiLongShares = oiTotalSharesOnSide; } else { oiShort = oiTotalOnSide; oiShortShares = oiTotalSharesOnSide; } // return new position's oi shares oiShares_ = oiShares; } /// @notice Sets the governance per-market risk parameter /// @dev updates funding state of market but does not fetch from oracle /// @dev to avoid edge cases when dataIsValid is false function setRiskParam(Risk.Parameters name, uint256 value) external onlyFactory { // pay funding to update state of market since last interaction _payFunding(); // check then set risk param _checkRiskParam(name, value); _cacheRiskCalc(name, value); params.set(name, value); } /// @notice Checks the governance per-market risk parameter is valid function _checkRiskParam(Risk.Parameters name, uint256 value) private { // checks delta won't cause position to be immediately // liquidatable given current leverage cap (capLeverage), // liquidation fee rate (liquidationFeeRate), and // maintenance margin fraction (maintenanceMarginFraction) if (name == Risk.Parameters.Delta) { uint256 _delta = value; uint256 capLeverage = params.get(Risk.Parameters.CapLeverage); uint256 maintenanceMarginFraction = params.get( Risk.Parameters.MaintenanceMarginFraction ); uint256 liquidationFeeRate = params.get(Risk.Parameters.LiquidationFeeRate); require( capLeverage <= ONE.divDown( 2 * _delta + maintenanceMarginFraction.divDown(ONE - liquidationFeeRate) ), "OVLV1: max lev immediately liquidatable" ); } // checks capLeverage won't cause position to be immediately // liquidatable given current spread (delta), // liquidation fee rate (liquidationFeeRate), and // maintenance margin fraction (maintenanceMarginFraction) if (name == Risk.Parameters.CapLeverage) { uint256 _capLeverage = value; uint256 delta = params.get(Risk.Parameters.Delta); uint256 maintenanceMarginFraction = params.get( Risk.Parameters.MaintenanceMarginFraction ); uint256 liquidationFeeRate = params.get(Risk.Parameters.LiquidationFeeRate); require( _capLeverage <= ONE.divDown( 2 * delta + maintenanceMarginFraction.divDown(ONE - liquidationFeeRate) ), "OVLV1: max lev immediately liquidatable" ); } // checks maintenanceMarginFraction won't cause position // to be immediately liquidatable given current spread (delta), // liquidation fee rate (liquidationFeeRate), // and leverage cap (capLeverage) if (name == Risk.Parameters.MaintenanceMarginFraction) { uint256 _maintenanceMarginFraction = value; uint256 delta = params.get(Risk.Parameters.Delta); uint256 capLeverage = params.get(Risk.Parameters.CapLeverage); uint256 liquidationFeeRate = params.get(Risk.Parameters.LiquidationFeeRate); require( capLeverage <= ONE.divDown( 2 * delta + _maintenanceMarginFraction.divDown(ONE - liquidationFeeRate) ), "OVLV1: max lev immediately liquidatable" ); } // checks liquidationFeeRate won't cause position // to be immediately liquidatable given current spread (delta), // leverage cap (capLeverage), and // maintenance margin fraction (maintenanceMarginFraction) if (name == Risk.Parameters.LiquidationFeeRate) { uint256 _liquidationFeeRate = value; uint256 delta = params.get(Risk.Parameters.Delta); uint256 capLeverage = params.get(Risk.Parameters.CapLeverage); uint256 maintenanceMarginFraction = params.get( Risk.Parameters.MaintenanceMarginFraction ); require( capLeverage <= ONE.divDown( 2 * delta + maintenanceMarginFraction.divDown(ONE - _liquidationFeeRate) ), "OVLV1: max lev immediately liquidatable" ); } // checks priceDriftUpperLimit won't cause pow() call in dataIsValid // to exceed max if (name == Risk.Parameters.PriceDriftUpperLimit) { Oracle.Data memory data = IOverlayV1Feed(feed).latest(); uint256 _priceDriftUpperLimit = value; require( _priceDriftUpperLimit * data.macroWindow < MAX_NATURAL_EXPONENT, "OVLV1: price drift exceeds max exp" ); } } /// @notice Caches risk param calculations used in market contract /// @notice for gas savings function _cacheRiskCalc(Risk.Parameters name, uint256 value) private { // caches calculations for dpUpperLimit // = e**(priceDriftUpperLimit * data.macroWindow) if (name == Risk.Parameters.PriceDriftUpperLimit) { Oracle.Data memory data = IOverlayV1Feed(feed).latest(); uint256 _priceDriftUpperLimit = value; uint256 pow = _priceDriftUpperLimit * data.macroWindow; dpUpperLimit = pow.expUp(); // e**(pow) } } /// @notice Irreversibly shuts down the market. Can be triggered by /// @notice governance through factory contract in the event of an emergency function shutdown() external notShutdown onlyFactory { isShutdown = true; } /// @notice Allows emergency withdrawal of remaining collateral /// @notice associated with position. Ignores any outstanding PnL and /// @notice funding considerations function emergencyWithdraw(uint256 positionId) external hasShutdown { // check position exists Position.Info memory pos = positions.get(msg.sender, positionId); require(pos.exists(), "OVLV1:!position"); // calculate remaining collateral backing position uint256 fraction = ONE; uint256 cost = pos.cost(fraction); cost = Math.min(ovl.balanceOf(address(this)), cost); // if cost > balance // set fraction remaining to zero so position no longer exists pos.fractionRemaining = 0; positions.set(msg.sender, positionId, pos); // emit withdraw event emit EmergencyWithdraw(msg.sender, positionId, cost); // transfer available collateral out to position owner ovl.transfer(msg.sender, cost); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oi","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debt","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isLong","type":"bool"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"Build","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateral","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":false,"internalType":"int256","name":"mint","type":"int256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"Liquidate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"positionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fraction","type":"uint256"},{"indexed":false,"internalType":"int256","name":"mint","type":"int256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"Unwind","type":"event"},{"inputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"microWindow","type":"uint256"},{"internalType":"uint256","name":"macroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMicroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMacroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOneMacroWindowAgo","type":"uint256"},{"internalType":"uint256","name":"reserveOverMicroWindow","type":"uint256"},{"internalType":"bool","name":"hasReserve","type":"bool"}],"internalType":"struct Oracle.Data","name":"data","type":"tuple"},{"internalType":"uint256","name":"volume","type":"uint256"}],"name":"ask","outputs":[{"internalType":"uint256","name":"ask_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"microWindow","type":"uint256"},{"internalType":"uint256","name":"macroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMicroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMacroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOneMacroWindowAgo","type":"uint256"},{"internalType":"uint256","name":"reserveOverMicroWindow","type":"uint256"},{"internalType":"bool","name":"hasReserve","type":"bool"}],"internalType":"struct Oracle.Data","name":"data","type":"tuple"}],"name":"backRunBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"microWindow","type":"uint256"},{"internalType":"uint256","name":"macroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMicroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMacroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOneMacroWindowAgo","type":"uint256"},{"internalType":"uint256","name":"reserveOverMicroWindow","type":"uint256"},{"internalType":"bool","name":"hasReserve","type":"bool"}],"internalType":"struct Oracle.Data","name":"data","type":"tuple"},{"internalType":"uint256","name":"volume","type":"uint256"}],"name":"bid","outputs":[{"internalType":"uint256","name":"bid_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"leverage","type":"uint256"},{"internalType":"bool","name":"isLong","type":"bool"},{"internalType":"uint256","name":"priceLimit","type":"uint256"}],"name":"build","outputs":[{"internalType":"uint256","name":"positionId_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"microWindow","type":"uint256"},{"internalType":"uint256","name":"macroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMicroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMacroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOneMacroWindowAgo","type":"uint256"},{"internalType":"uint256","name":"reserveOverMicroWindow","type":"uint256"},{"internalType":"bool","name":"hasReserve","type":"bool"}],"internalType":"struct Oracle.Data","name":"data","type":"tuple"},{"internalType":"uint256","name":"cap","type":"uint256"}],"name":"capNotionalAdjustedForBounds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"cap","type":"uint256"}],"name":"capOiAdjustedForCircuitBreaker","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint32","name":"window","type":"uint32"},{"internalType":"int192","name":"accumulator","type":"int192"}],"internalType":"struct Roller.Snapshot","name":"snapshot","type":"tuple"},{"internalType":"uint256","name":"cap","type":"uint256"}],"name":"circuitBreaker","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"microWindow","type":"uint256"},{"internalType":"uint256","name":"macroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMicroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMacroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOneMacroWindowAgo","type":"uint256"},{"internalType":"uint256","name":"reserveOverMicroWindow","type":"uint256"},{"internalType":"bool","name":"hasReserve","type":"bool"}],"internalType":"struct Oracle.Data","name":"data","type":"tuple"}],"name":"dataIsValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dpUpperLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"positionId","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"microWindow","type":"uint256"},{"internalType":"uint256","name":"macroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMicroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMacroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOneMacroWindowAgo","type":"uint256"},{"internalType":"uint256","name":"reserveOverMicroWindow","type":"uint256"},{"internalType":"bool","name":"hasReserve","type":"bool"}],"internalType":"struct Oracle.Data","name":"data","type":"tuple"}],"name":"frontRunBound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[15]","name":"_params","type":"uint256[15]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isShutdown","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"positionId","type":"uint256"}],"name":"liquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"oiOverweight","type":"uint256"},{"internalType":"uint256","name":"oiUnderweight","type":"uint256"},{"internalType":"uint256","name":"timeElapsed","type":"uint256"}],"name":"oiAfterFunding","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"notional","type":"uint256"},{"internalType":"uint256","name":"midPrice","type":"uint256"}],"name":"oiFromNotional","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oiLong","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oiLongShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oiShort","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oiShortShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ovl","outputs":[{"internalType":"contract IOverlayV1Token","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"params","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"positions","outputs":[{"internalType":"uint96","name":"notionalInitial","type":"uint96"},{"internalType":"uint96","name":"debtInitial","type":"uint96"},{"internalType":"int24","name":"midTick","type":"int24"},{"internalType":"int24","name":"entryTick","type":"int24"},{"internalType":"bool","name":"isLong","type":"bool"},{"internalType":"bool","name":"liquidated","type":"bool"},{"internalType":"uint240","name":"oiShares","type":"uint240"},{"internalType":"uint16","name":"fractionRemaining","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum Risk.Parameters","name":"name","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setRiskParam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shutdown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"snapshotMinted","outputs":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint32","name":"window","type":"uint32"},{"internalType":"int192","name":"accumulator","type":"int192"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"snapshotVolumeAsk","outputs":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint32","name":"window","type":"uint32"},{"internalType":"int192","name":"accumulator","type":"int192"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"snapshotVolumeBid","outputs":[{"internalType":"uint32","name":"timestamp","type":"uint32"},{"internalType":"uint32","name":"window","type":"uint32"},{"internalType":"int192","name":"accumulator","type":"int192"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timestampUpdateLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"positionId","type":"uint256"},{"internalType":"uint256","name":"fraction","type":"uint256"},{"internalType":"uint256","name":"priceLimit","type":"uint256"}],"name":"unwind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"update","outputs":[{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"microWindow","type":"uint256"},{"internalType":"uint256","name":"macroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMicroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOverMacroWindow","type":"uint256"},{"internalType":"uint256","name":"priceOneMacroWindowAgo","type":"uint256"},{"internalType":"uint256","name":"reserveOverMicroWindow","type":"uint256"},{"internalType":"bool","name":"hasReserve","type":"bool"}],"internalType":"struct Oracle.Data","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e06040523480156200001157600080fd5b506000806000336001600160a01b031663890357306040518163ffffffff1660e01b8152600401606060405180830381865afa15801562000056573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200007c9190620000bb565b6001600160a01b0392831660805290821660a0521660c0525062000105915050565b80516001600160a01b0381168114620000b657600080fd5b919050565b600080600060608486031215620000d157600080fd5b620000dc846200009e565b9250620000ec602085016200009e565b9150620000fc604085016200009e565b90509250925092565b60805160a05160c051614db5620001c8600039600081816105b001528181610d00015281816115260152818161162f015281816118520152818161209a01526122ec0152600081816102460152818161167001528181611bcd01528181612e8501526131fd01526000818161052e01528181610b0801528181610ba501528181610c2f01528181610cd101528181610eae01528181610f8c0152818161144b015281816114f701528181611f4d01528181611ff1015261206b0152614db56000f3fe608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638eba35351161011a578063bf65b2fb116100ad578063d43cbd8e1161007c578063d43cbd8e146105db578063d565cc33146105ee578063ecc1619114610616578063f333fe1314610629578063fc0e74d11461063257600080fd5b8063bf65b2fb1461058b578063bf86d6901461059e578063c45a0155146105ab578063c6838e8b146105d257600080fd5b8063a2e62045116100e9578063a2e62045146104be578063b29fa9c314610529578063b445e2e714610550578063bcbaf4871461057857600080fd5b80638eba35351461045d57806392aac701146104705780639d2f053c146104835780639f0a54591461049657600080fd5b806358171a61116101925780635dedde6d116101615780635dedde6d1461041b578063640d0c28146104245780636c629159146104375780638607f5c31461044a57600080fd5b806358171a611461038457806359968288146103a75780635ad7226f146103ba5780635b6df29a146103cd57600080fd5b806337a7b7d8116101ce57806337a7b7d81461024157806346322c3714610280578063514ea4bf146102955780635312ea8e1461037157600080fd5b806309163014146102005780632acb38101461021c5780632eda95c2146102255780633197e19214610238575b600080fd5b61020960105481565b6040519081526020015b60405180910390f35b61020960115481565b6102096102333660046146a3565b61063a565b61020960195481565b6102687f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610213565b61029361028e3660046146d0565b6106d4565b005b6103136102a33660046146fc565b601660205260009081526040902080546001909101546001600160601b0380831692600160601b810490911691600160c01b8204600290810b92600160d81b810490910b91600160f01b80830460ff90811693600160f81b900416916001600160f01b03811691900461ffff1688565b604080516001600160601b03998a168152989097166020890152600295860b968801969096529290930b60608601521515608085015290151560a08401526001600160f01b031660c083015261ffff1660e082015261010001610213565b61029361037f3660046146fc565b610dfb565b610397610392366004614715565b611008565b6040519015158152602001610213565b6102096103b5366004614732565b611074565b6102936103c8366004614771565b611624565b6015546103f59063ffffffff80821691600160201b810490911690600160401b900460170b83565b6040805163ffffffff948516815293909216602084015260170b90820152606001610213565b610209600f5481565b6102936104323660046147f0565b611847565b610209610445366004614715565b6118bb565b6102096104583660046146a3565b6118e9565b61020961046b366004614820565b611973565b61020961047e366004614715565b611988565b6102096104913660046146fc565b611a0e565b6104a96104a43660046146d0565b611a25565b60408051928352602083019190915201610213565b6104c6611b77565b6040516102139190600061010082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e0830151151560e083015292915050565b6102687f000000000000000000000000000000000000000000000000000000000000000081565b6013546103f59063ffffffff80821691600160201b810490911690600160401b900460170b83565b610293610586366004614857565b611c98565b6102096105993660046146fc565b612196565b601a546103979060ff1681565b6102687f000000000000000000000000000000000000000000000000000000000000000081565b61020960185481565b6102096105e9366004614889565b612204565b6014546103f59063ffffffff80821691600160201b810490911690600160401b900460170b83565b6102096106243660046146a3565b612288565b61020960125481565b6102936122be565b600061064e83606001518460800151612338565b9050600061065d81600261234f565b9050600061066c81600161234f565b9050600061067a828661237d565b610684908461492b565b90506801158e460913d0000081106106b75760405162461bcd60e51b81526004016106ae90614943565b60405180910390fd5b6106ca6106c3826123cc565b859061237d565b9695505050505050565b601a5460ff16156106f75760405162461bcd60e51b81526004016106ae9061496f565b670de0b6b3a76400008211156107445760405162461bcd60e51b815260206004820152601260248201527109eac98ac6274cce4c2c6e8d2dedc7cdac2f60731b60448201526064016106ae565b61075961075083612467565b61ffff166124e0565b9150600082116107a05760405162461bcd60e51b815260206004820152601260248201527127ab262b189d333930b1ba34b7b71e36b4b760711b60448201526064016106ae565b60008060008060006107b0611b77565b905060006107c06016338b612507565b90506107cb81612620565b6107e75760405162461bcd60e51b81526004016106ae90614998565b600081608001516107fa576010546107fe565b600f545b90506000826080015161081357601254610817565b6011545b905061085782826108278761263d565b6108336000600361234f565b61083f6000600861234f565b61084b6000600a61234f565b89959493929190612651565b156108995760405162461bcd60e51b81526020600482015260126024820152714f564c56313a6c6971756964617461626c6560701b60448201526064016106ae565b60006108b66108ad8661062484600461234f565b61046b8761263d565b905083608001516108eb576108e685610233876108e08f88888b6126da909392919063ffffffff16565b85612717565b610910565b610910856104588761090a8f88888b6126da909392919063ffffffff16565b856127de565b965083608001516109245789871115610929565b898710155b6109455760405162461bcd60e51b81526004016106ae90614943565b600061095281600361234f565b9050610962858d86868c866128a0565b995061096e858d6129ac565b9850600061097d81600b61234f565b905061098e868e87878d87876129d4565b975061099a888c6129fe565b97508560800151156109e7576109be6109b5878f88886126da565b600f5490612a0d565b600f556109cb868e612a28565b601160008282546109dc91906149c1565b90915550610a239050565b6109ff6109f6878f88886126da565b60105490612a0d565b601055610a0c868e612a28565b60126000828254610a1d91906149c1565b90915550505b610a35610a308b8d6149d8565b612a4b565b50610a40868e612a28565b8660c001818151610a519190614a17565b6001600160f01b0316905250610a67868e612b09565b8660e0019061ffff16908161ffff1681525050610a92338f886016612b83909392919063ffffffff16565b50505050505050336001600160a01b03167fc13b78a0772a556b5387d497953273371ed42cff2af20c019d9f119a737685ba88888688610ad291906149d8565b604080519384526020840192909252908201526060810185905260800160405180910390a2828410610b9b576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f1930610b3886886149c1565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610b7e57600080fd5b505af1158015610b92573d6000803e3d6000fd5b50505050610c25565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166342966c68610bd486866149c1565b6040518263ffffffff1660e01b8152600401610bf291815260200190565b600060405180830381600087803b158015610c0c57600080fd5b505af1158015610c20573d6000803e3d6000fd5b505050505b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663a9059cbb33610c5f84886149c1565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610caa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cce9190614a3f565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663469048406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d809190614a5c565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df19190614a3f565b5050505050505050565b601a5460ff16610e405760405162461bcd60e51b815260206004820152601060248201526f27ab262b189d1010b9b43aba3237bbb760811b60448201526064016106ae565b6000610e4e60163384612507565b9050610e5981612620565b610e755760405162461bcd60e51b81526004016106ae90614998565b670de0b6b3a76400006000610e8a83836129ac565b6040516370a0823160e01b8152306004820152909150610f1f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610ef5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f199190614a79565b826129fe565b600060e08501529050610f356016338686612b83565b604080518581526020810183905233917fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae0595910160405180910390a260405163a9059cbb60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015610fdd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110019190614a3f565b5050505050565b60195460009081611021670de0b6b3a764000083612ca8565b608085015160a08601519192509080158061103a575081155b1561104b5750600095945050505050565b60006110578383612cd7565b90508381101580156110695750848111155b979650505050505050565b601a5460009060ff161561109a5760405162461bcd60e51b81526004016106ae9061496f565b670de0b6b3a76400008410156110e25760405162461bcd60e51b815260206004820152600d60248201526c27ab262b189d3632bb1e36b4b760991b60448201526064016106ae565b6110ee6000600561234f565b84111561112d5760405162461bcd60e51b815260206004820152600d60248201526c09eac98ac6274d8caec7cdac2f609b1b60448201526064016106ae565b6111396000600c61234f565b85101561117f5760405162461bcd60e51b815260206004820152601460248201527327ab262b189d31b7b63630ba32b930b61e36b4b760611b60448201526064016106ae565b600080600080600061118f611b77565b9050600061119d8b8b61237d565b905060006111aa8361263d565b90506111b68282611973565b9650600087116111f65760405162461bcd60e51b815260206004820152600b60248201526a04f564c56313a6f693d3d360ac1b60448201526064016106ae565b6112008c836149c1565b95506112186112116000600b61234f565b839061237d565b9350600061123461122e8561062484600461234f565b83611973565b90508a61124f5761124a84610458868b856127de565b61125e565b61125e84610233868b85612717565b95508a61126e5789861015611273565b898611155b61128f5760405162461bcd60e51b81526004016106ae90614943565b600061129c89838e612d08565b90506000604051806101000160405280866001600160601b031681526020018a6001600160601b031681526020016112d386612dd1565b60020b81526020016112e48a612dd1565b60020b81528e15156020820152600060408201526001600160f01b038416606082015260800161131b670de0b6b3a7640000612467565b61ffff16905290506113798d61133357601054611337565b600f545b8e61134457601254611348565b6011545b866113556000600361234f565b6113616000600861234f565b61136d6000600a61234f565b87959493929190612651565b156113bb5760405162461bcd60e51b81526020600482015260126024820152714f564c56313a6c6971756964617461626c6560701b60448201526064016106ae565b6017549a506113cd6016338d84612b83565b601780549060006113dd83614a92565b9091555050604080518c8152602081018c90529081018a90528d15156060820152608081018990523396507fb98b46cc473761b09478db481c36070133bf6b7a18241892f5477e725b063b5a955060a001935061143992505050565b60405180910390a26001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166323b872dd333061147c858e61492b565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af11580156114d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f49190614a3f565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663469048406040518163ffffffff1660e01b8152600401602060405180830381865afa158015611582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a69190614a5c565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af11580156115f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116179190614a3f565b5050505050949350505050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461166c5760405162461bcd60e51b81526004016106ae90614aad565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166352bfe7896040518163ffffffff1660e01b815260040161010060405180830381865afa1580156116cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f19190614ad6565b905060006116fe8261263d565b116117395760405162461bcd60e51b815260206004820152600b60248201526a4f564c56313a216461746160a81b60448201526064016106ae565b4260185560a0820151604083015161010084015161014085015161179661177261176b83670de0b6b3a76400006149c1565b8490612ca8565b61177d856002614b9c565b611787919061492b565b670de0b6b3a764000090612ca8565b8411156117b55760405162461bcd60e51b81526004016106ae90614bbb565b6101a086015160408601516801158e460913d00000906117d59083614b9c565b106117f25760405162461bcd60e51b81526004016106ae90614c02565b6117fd600d82612e67565b60005b600f811015610df1578781600f811061181b5761181b614b86565b6020020151600082600f811061183357611833614b86565b01558061183f81614a92565b915050611800565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461188f5760405162461bcd60e51b81526004016106ae90614aad565b611897612f32565b6118a18282612fb6565b6118ab8282612e67565b6118b7600083836132c0565b5050565b6000806118c981600161234f565b90506118e28360c00151826132eb90919063ffffffff16565b9392505050565b60006118fd836060015184608001516129fe565b9050600061190c81600261234f565b9050600061191b81600161234f565b90506000611929828661237d565b611933908461492b565b90506801158e460913d00000811061195d5760405162461bcd60e51b81526004016106ae90614943565b6106ca61196c611787836123cc565b85906132eb565b600061197f8383612ca8565b90505b92915050565b60008061199681600e61234f565b9050600081670de0b6b3a764000085604001516119b39190614b9c565b6119bd9190614c5a565b905060006119cc81600261234f565b9050611a056119e4670de0b6b3a76400006002614b9c565b6119ff846119ff8960c00151866132eb90919063ffffffff16565b906132eb565b95945050505050565b600081600f8110611a1e57600080fd5b0154905081565b60008080611a33858761492b565b90506000611a4186886149c1565b90506000611a4f878961237d565b9050821580611a5c575081155b15611a6f57878794509450505050611b6f565b60008087611a7d828061234f565b611a88906002614b9c565b611a929190614b9c565b90506801158e460913d00000811015611ab457611ab1611787826123cc565b91505b6000611ac08587612ca8565b90506000611aed611ad185806132eb565b611ae390670de0b6b3a76400006149c1565b6119ff84806132eb565b611aff90670de0b6b3a76400006149c1565b9050611b28611b21611b1a6002670de0b6b3a7640000614c5a565b839061330c565b88906132eb565b9650611b3486856132eb565b95506002611b42878961492b565b611b4c9190614c5a565b9b508b15611b6157611b5e858d612cd7565b9a505b8b8b98509850505050505050505b935093915050565b611bc1604051806101000160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581525090565b611bc9612f32565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166352bfe7896040518163ffffffff1660e01b815260040161010060405180830381865afa158015611c2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4e9190614ad6565b9050611c5981611008565b611c935760405162461bcd60e51b815260206004820152600b60248201526a4f564c56313a216461746160a81b60448201526064016106ae565b919050565b601a5460ff1615611cbb5760405162461bcd60e51b81526004016106ae9061496f565b6000808080808080611ccf60168a8a612507565b9050611cda81612620565b611cf65760405162461bcd60e51b81526004016106ae90614998565b6000611d00611b77565b905060008260800151611d1557601054611d19565b600f545b905060008360800151611d2e57601254611d32565b6011545b90506000611d4181600361234f565b9050670de0b6b3a7640000611d558561263d565b9950611d8284848c85611d6a6000600861234f565b611d766000600a61234f565b8c959493929190612651565b611dc45760405162461bcd60e51b81526020600482015260136024820152724f564c56313a216c6971756964617461626c6560681b60448201526064016106ae565b611dd2868286868e876128a0565b9b50611dde86826129ac565b9a50611df6611def6000600a61234f565b8d906132eb565b9850611e02898d6149c1565b9650611e13611b216000600961234f565b9750611e1f88886149c1565b9650856080015115611e6357611e3a6109b5878387876126da565b600f55611e478682612a28565b60116000828254611e5891906149c1565b90915550611e969050565b611e726109f6878387876126da565b601055611e7f8682612a28565b60126000828254611e9091906149c1565b90915550505b611eae88611ea48d8f6149d8565b610a3091906149d8565b50600160a0870152600060c0870181905260e0870152611ed160168f8f89612b83565b505050505050876001600160a01b0316336001600160a01b03167ff1deb4d6391f20e8cad919356063127cf8453da1fdf246eb1b5e4549e848112e8985898b611f1a91906149d8565b611f2491906149d8565b604080519283526020830191909152810188905260600160405180910390a36001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166342966c6883611f7d89896149c1565b611f87919061492b565b6040518263ffffffff1660e01b8152600401611fa591815260200190565b600060405180830381600087803b158015611fbf57600080fd5b505af1158015611fd3573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063a9059cbb91506044016020604051808303816000875af1158015612044573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120689190614a3f565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663469048406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211a9190614a5c565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b9190614a3f565b505050505050505050565b6040805160608101825260155463ffffffff8082168352600160201b820481166020840152600160401b90910460170b9282019290925260009182906121e190829060069061234f16565b90506121f082428360006133fe565b91506121fc8285612204565b949350505050565b600080612215846040015160170b90565b9050600061222481600761234f565b9050808213612237578392505050611982565b612242816002614c6e565b821261225357600092505050611982565b600061225f8383612ca8565b612272670de0b6b3a76400006002614b9c565b61227c91906149c1565b90506106ca85826132eb565b60008260e00151156122b8576122a6826122a1856118bb565b6129fe565b91506122b5826122a185611988565b91505b50919050565b601a5460ff16156122e15760405162461bcd60e51b81526004016106ae9061496f565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146123295760405162461bcd60e51b81526004016106ae90614aad565b601a805460ff19166001179055565b600081831015612348578161197f565b5090919050565b60008282600e81111561236457612364614b70565b600f811061237457612374614b86565b01549392505050565b60008061238a8385614b9c565b90508061239b576000915050611982565b670de0b6b3a76400006123af6001836149c1565b6123b99190614c5a565b6123c490600161492b565b915050611982565b6000816123e25750670de0b6b3a7640000919050565b600160ff1b82106124355760405162461bcd60e51b815260206004820152601b60248201527f4669786564506f696e743a2078206f7574206f6620626f756e6473000000000060448201526064016106ae565b816000612441826135fa565b9050600061245b6124548361271061237d565b60016139dc565b9050611a0582826139dc565b60008061247e612710670de0b6b3a7640000614c5a565b9050600061248c8285614c5a565b905061ffff8111156118e25760405162461bcd60e51b815260206004820152601e60248201527f4f564c56313a20466978656443617374206f7574206f6620626f756e6473000060448201526064016106ae565b6000806124f7612710670de0b6b3a7640000614c5a565b90506118e28161ffff8516614b9c565b60408051610100810182526000808252602080830182905282840182905260608084018390526080840183905260a0840183905260c0840183905260e090930182905283519590921b6bffffffffffffffffffffffff1916858301526034808601949094528251808603909401845260548501808452845194830194909420815294905292839020610154830190935282546001600160601b038082168352600160601b8204166074840152600160c01b8104600290810b6094850152600160d81b8204900b60b4840152600160f01b80820460ff908116151560d4860152600160f81b909204909116151560f48401526001909301546001600160f01b0381166101148401529290920461ffff166101349091015290565b60008160a0015115801561198257505060e0015161ffff16151590565b6000611982826060015183608001516139e9565b6000670de0b6b3a7640000816126678a83613a04565b90508960a001518061267f575060e08a015161ffff16155b1561268f57600092505050611069565b600061269f8b848c8c8c8c6128a0565b905060006126ad838861237d565b905060006126bb83886132eb565b90506126c7818361492b565b9092109c9b505050505050505050505050565b6000806126e78686612a28565b90508015806126f4575083155b806126fd575082155b1561270c5760009150506121fc565b6106ca818585613a35565b6040805160608101825260145463ffffffff8082168352600160201b820481166020840152600160401b90910460170b9282019290925260009182906127619086908690612cd716565b60208701519091506127779083904290846133fe565b8051601480546020840151604085015163ffffffff94851667ffffffffffffffff1990931692909217600160201b94909116939093029290921767ffffffffffffffff16600160401b6001600160c01b0384160217905590925060170b9695505050505050565b6040805160608101825260135463ffffffff8082168352600160201b820481166020840152600160401b90910460170b9282019290925260009182906128289086908690612cd716565b602087015190915061283e9083904290846133fe565b8051601380546020840151604085015163ffffffff94851667ffffffffffffffff1990931692909217600160201b94909116939093029290921767ffffffffffffffff16600160401b6001600160c01b0384160217905590925060170b6106ca565b6000806128ad8888613ae8565b905060006128bb8989613a04565b905060006128c98a8a613b05565b905060006128d98b8b8b8b6126da565b905060006128e68c613b2d565b90508b6080015115612969576129246128ff838a61237d565b6122a16129148a670de0b6b3a764000061492b565b61291e868661237d565b9061237d565b61293886612932878661237d565b90612cd7565b612942919061492b565b9550612962612951838361237d565b61295b908561492b565b8790612a0d565b955061299d565b612973828261237d565b61298186612932878661237d565b61298b919061492b565b955061299a612951838a61237d565b95505b50505050509695505050505050565b6000806129b98484613a04565b905060006129c78585613b05565b9050816106ca8183612a0d565b6000806129e5898989898989613b3c565b90506129f1818461237d565b9998505050505050505050565b6000818310612348578161197f565b600080828411612a1e5760006121fc565b6121fc83856149c1565b600080612a3f8460c001516001600160f01b031690565b90506121fc81846132eb565b6040805160608101825260155463ffffffff8082168352600160201b820481166020840152600160401b90910460170b928201929092526000918290612a9690829060069061234f16565b9050612aa4824283876133fe565b8051601580546020840151604085015163ffffffff94851667ffffffffffffffff1990931692909217600160201b94909116939093029290921767ffffffffffffffff16600160401b6001600160c01b0384160217905590925060009060170b611a05565b6000670de0b6b3a7640000821115612b585760405162461bcd60e51b815260206004820152601260248201527109eac98ac6274cce4c2c6e8d2dedc7cdac2f60731b60448201526064016106ae565b6000612b78612b6f84670de0b6b3a76400006149c1565b6119ff86613b67565b90506121fc81612467565b6040516bffffffffffffffffffffffff19606085901b166020820152603481018390528190859060009060540160408051808303601f1901815291815281516020928301208352828201939093529082016000208351815492850151938501516060860151608087015160a08801516001600160601b039485166001600160c01b031990971696909617600160601b94909716939093029590951765ffffffffffff60c01b1916600160c01b62ffffff9283160262ffffff60d81b191617600160d81b9190951602939093176001600160f01b03908116600160f01b94151585026001600160f81b031617600160f81b9315159390930292909217815560c084015160e0909401519390911661ffff9093169091029190911760019091015550505050565b600082612cb757506000611982565b6000612ccb670de0b6b3a764000085614b9c565b90506123c48382614c5a565b600082612ce657506000611982565b6000612cfa670de0b6b3a764000085614b9c565b9050826123af6001836149c1565b60008082612d1857601054612d1c565b600f545b9050600083612d2d57601254612d31565b6011545b90506000612d40878484613b7a565b9050612d4c878461492b565b9250612d58818361492b565b91506000612d6587612196565b905080841115612da65760405162461bcd60e51b815260206004820152600c60248201526b04f564c56313a6f693e6361760a41b60448201526064016106ae565b8515612dbb57600f8490556011839055612dc6565b601084905560128390555b509695505050505050565b600080612de683670de111a6b7de4000613ba3565b90506956d225004ee68c3fffff198112158015612e0d575069fe1c215e8f838e0000008113155b612e555760405162461bcd60e51b81526020600482015260196024820152784f564c56313a207469636b206f7574206f6620626f756e647360381b60448201526064016106ae565b6118e2670de0b6b3a764000082614cf3565b600d82600e811115612e7b57612e7b614b70565b14156118b75760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166352bfe7896040518163ffffffff1660e01b815260040161010060405180830381865afa158015612ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f069190614ad6565b60408101519091508290600090612f1d9083614b9c565b9050612f28816123cc565b6019555050505050565b600060185442612f4291906149c1565b90508015612fb357601054600f5411600081612f6057601054612f64565b600f545b9050600082612f7557600f54612f79565b6010545b9050612f86828286611a25565b909250905082612f965780612f98565b815b600f5582612fa65781612fa8565b805b601055505042601855505b50565b600282600e811115612fca57612fca614b70565b141561304557806000612fde81600561234f565b90506000612fed81600861234f565b90506000612ffc81600a61234f565b905061302161301661176b83670de0b6b3a76400006149c1565b61177d866002614b9c565b8311156130405760405162461bcd60e51b81526004016106ae90614bbb565b505050505b600582600e81111561305957613059614b70565b14156130c95780600061306d81600261234f565b9050600061307c81600861234f565b9050600061308b81600a61234f565b90506130a561177261176b83670de0b6b3a76400006149c1565b8411156130c45760405162461bcd60e51b81526004016106ae90614bbb565b505050505b600882600e8111156130dd576130dd614b70565b1415613154578060006130f181600261234f565b9050600061310081600561234f565b9050600061310f81600a61234f565b905061313061177261312983670de0b6b3a76400006149c1565b8690612ca8565b82111561314f5760405162461bcd60e51b81526004016106ae90614bbb565b505050505b600a82600e81111561316857613168614b70565b14156131df5780600061317c81600261234f565b9050600061318b81600561234f565b9050600061319a81600861234f565b90506131bb6117726131b486670de0b6b3a76400006149c1565b8390612ca8565b8211156131da5760405162461bcd60e51b81526004016106ae90614bbb565b505050505b600d82600e8111156131f3576131f3614b70565b14156118b75760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166352bfe7896040518163ffffffff1660e01b815260040161010060405180830381865afa15801561325a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327e9190614ad6565b604081015190915082906801158e460913d000009061329d9083614b9c565b106132ba5760405162461bcd60e51b81526004016106ae90614c02565b50505050565b808383600e8111156132d4576132d4614b70565b600f81106132e4576132e4614b86565b0155505050565b6000806132f88385614b9c565b90506121fc670de0b6b3a764000082614c5a565b60008115806133225750670de0b6b3a764000083145b156133365750670de0b6b3a7640000611982565b8261334357506000611982565b670de0b6b3a764000082141561335a575081611982565b61336d670de0b6b3a76400006002614b9c565b8214156133855761337e83846132eb565b9050611982565b613398670de0b6b3a76400006004614b9c565b8214156133b75760006133ab84856132eb565b90506123c481826132eb565b60006133c38484613cb2565b905060006133d66124548361271061237d565b9050808210156133eb57600092505050611982565b6133f58282613db3565b92505050611982565b6040805160608101825260008082526020820181905291810182905285519091859163ffffffff908116908316101561345b57865163ffffffff9081169061344c908416600160201b61492b565b61345691906149c1565b61346e565b86516134679083614d21565b63ffffffff165b602088015190915063ffffffff16600061348c896040015160170b90565b9050818310158061349b575081155b156134e55760405180606001604052808563ffffffff1681526020016134c089613dc0565b63ffffffff1681526020016134d488613dd9565b60170b8152509450505050506121fc565b816134f084826149c1565b6134fa9083614c6e565b6135049190614cf3565b905060006135128783614d3e565b9050806135565760405180606001604052808663ffffffff1681526020016135398a613dc0565b63ffffffff168152600060209091015295506121fc945050505050565b600061356183613e1c565b9050600061356e89613e1c565b9050600061357c828461492b565b6135868c84614b9c565b61359089896149c1565b61359a9086614b9c565b6135a4919061492b565b6135ae9190614c5a565b905060405180606001604052808963ffffffff1681526020016135d083613dc0565b63ffffffff1681526020016135e486613dd9565b60170b90529d9c50505050505050505050505050565b6000613629680238fd42c5cf03ffff198312158015613622575068070c1cc73b00c800008313155b6009613e33565b60008212156136615761363e826000036135fa565b6a0c097ce7bc90715b34b9f160241b8161365a5761365a614c44565b0592915050565b60006806f05b59d3b200000083126136a157506806f05b59d3b1ffffff1990910190770195e54c5dd42177f53a27172fa9ec6302628270000000006136d7565b6803782dace9d900000083126136d357506803782dace9d8ffffff19909101906b1425982cf597cd205cef73806136d7565b5060015b6064929092029168056bc75e2d6310000068ad78ebc5ac6200000084126137275768ad78ebc5ac61ffffff199093019268056bc75e2d631000006e01855144814a7ff805980ff008400082020590505b6856bc75e2d6310000008412613763576856bc75e2d630ffffff199093019268056bc75e2d631000006b02df0ab5a80a22c61ab5a70082020590505b682b5e3af16b18800000841261379d57682b5e3af16b187fffff199093019268056bc75e2d63100000693f1fce3da636ea5cf85082020590505b6815af1d78b58c40000084126137d7576815af1d78b58c3fffff199093019268056bc75e2d63100000690127fa27722cc06cc5e282020590505b680ad78ebc5ac6200000841261381057680ad78ebc5ac61fffff199093019268056bc75e2d6310000068280e60114edb805d0382020590505b68056bc75e2d6310000084126138495768056bc75e2d630fffff199093019268056bc75e2d63100000680ebc5fb4174612111082020590505b6802b5e3af16b18800008412613882576802b5e3af16b187ffff199093019268056bc75e2d631000006808f00f760a4b2db55d82020590505b68015af1d78b58c4000084126138bb5768015af1d78b58c3ffff199093019268056bc75e2d631000006806f5f177578893793782020590505b68056bc75e2d631000008481019085906002908280020505918201919050600368056bc75e2d631000008783020505918201919050600468056bc75e2d631000008783020505918201919050600568056bc75e2d631000008783020505918201919050600668056bc75e2d631000008783020505918201919050600768056bc75e2d631000008783020505918201919050600868056bc75e2d631000008783020505918201919050600968056bc75e2d631000008783020505918201919050600a68056bc75e2d631000008783020505918201919050600b68056bc75e2d631000008783020505918201919050600c68056bc75e2d631000008783020505918201919050606468056bc75e2d63100000848402058502059695505050505050565b6000806121fc838561492b565b60006139f86002848418614c5a565b61197f9084841661492b565b600080613a1084613b67565b90506000613a298261291e87516001600160601b031690565b9050611a05818561237d565b600080806000198587098587029250828110838203039150508060001415613a6f5760008411613a6457600080fd5b5082900490506118e2565b808411613a7b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b600080613af484613b67565b90506000613a298261291e87613e41565b600080613b1184613b67565b90506000613a298261291e87602001516001600160601b031690565b60006119828260600151613e6e565b600080613b4d8888888888886128a0565b90506000613b5b8989613b05565b90506129f1818361492b565b60006119828260e0015161ffff166124e0565b6000821580613b87575081155b613b9b57613b96848385613a35565b6121fc565b509192915050565b60008083118015613bb75750600160ff1b83105b613c035760405162461bcd60e51b815260206004820152601b60248201527f4669786564506f696e743a2061206f7574206f6620626f756e6473000000000060448201526064016106ae565b600082118015613c165750600160ff1b82105b613c625760405162461bcd60e51b815260206004820152601b60248201527f4669786564506f696e743a2062206f7574206f6620626f756e6473000000000060448201526064016106ae565b82826000613c708383613f33565b9050600080821215613c855781600003613c87565b815b90506000613c9a6124548361271061237d565b9050613ca681846149d8565b98975050505050505050565b600081613cc85750670de0b6b3a7640000611982565b82613cd557506000611982565b613ce6600160ff1b84106006613e33565b82613d0c770bce5086492111aea88f4bb1ca6bcf584181ea8059f7653284106007613e33565b826000670c7d713b49da000083138015613d2d5750670f43fc2c04ee000083125b15613d64576000613d3d84613fed565b9050670de0b6b3a764000080820784020583670de0b6b3a764000083050201915050613d72565b81613d6e8461410c565b0290505b670de0b6b3a76400009005613daa680238fd42c5cf03ffff198212801590613da3575068070c1cc73b00c800008213155b6008613e33565b6106ca816135fa565b6000806121fc83856149c1565b60008063ffffffff8311156123485763ffffffff6118e2565b6000806001600160bf1b03198312613e0c576001600160bf1b038313613dff57826118e2565b6001600160bf1b036118e2565b6001600160bf1b03199392505050565b600080821215613e2f5781600003611982565b5090565b816118b7576118b7816144b6565b600080613e5583516001600160601b031690565b90506000613e6284614509565b90506121fc8282612ca8565b600080613e87670de0b6b3a7640000600285900b614c6e565b90506956d225004ee68c3fffff198112158015613eae575069fe1c215e8f838e0000008113155b613ef65760405162461bcd60e51b81526020600482015260196024820152784f564c56313a207469636b206f7574206f6620626f756e647360381b60448201526064016106ae565b6000613f0182613e1c565b90506000821215613f2157613b96611787670de111a6b7de400083614518565b6121fc670de111a6b7de40008261330c565b600080670c7d713b49da000083138015613f545750670f43fc2c04ee000083125b15613f6957613f6283613fed565b9050613f7f565b670de0b6b3a7640000613f7b8461410c565b0290505b6000670c7d713b49da000085138015613f9f5750670f43fc2c04ee000085125b15613fb457613fad85613fed565b9050613fca565b670de0b6b3a7640000613fc68661410c565b0290505b81670de0b6b3a7640000820281613fe357613fe3614c44565b0595945050505050565b670de0b6b3a7640000026000806a0c097ce7bc90715b34b9f160241b808401906ec097ce7bc90715b34b9f0fffffffff198501028161402e5761402e614c44565b05905060006a0c097ce7bc90715b34b9f160241b82800205905081806a0c097ce7bc90715b34b9f160241b81840205915060038205016a0c097ce7bc90715b34b9f160241b82840205915060058205016a0c097ce7bc90715b34b9f160241b82840205915060078205016a0c097ce7bc90715b34b9f160241b82840205915060098205016a0c097ce7bc90715b34b9f160241b828402059150600b8205016a0c097ce7bc90715b34b9f160241b828402059150600d8205016a0c097ce7bc90715b34b9f160241b828402059150600f82050160020295945050505050565b6000670de0b6b3a764000082121561414d57614144826a0c097ce7bc90715b34b9f160241b8161413e5761413e614c44565b0561410c565b60000392915050565b60007e1600ef3172e58d2e933ec884fde10064c63b5372d805e203c0000000000000831261419e57770195e54c5dd42177f53a27172fa9ec630262827000000000830592506806f05b59d3b2000000015b73011798004d755d3c8bc8e03204cf44619e00000083126141d6576b1425982cf597cd205cef7380830592506803782dace9d9000000015b606492830292026e01855144814a7ff805980ff0084000831261421e576e01855144814a7ff805980ff008400068056bc75e2d63100000840205925068ad78ebc5ac62000000015b6b02df0ab5a80a22c61ab5a7008312614259576b02df0ab5a80a22c61ab5a70068056bc75e2d6310000084020592506856bc75e2d631000000015b693f1fce3da636ea5cf850831261429057693f1fce3da636ea5cf85068056bc75e2d631000008402059250682b5e3af16b18800000015b690127fa27722cc06cc5e283126142c757690127fa27722cc06cc5e268056bc75e2d6310000084020592506815af1d78b58c400000015b68280e60114edb805d0383126142fc5768280e60114edb805d0368056bc75e2d631000008402059250680ad78ebc5ac6200000015b680ebc5fb41746121110831261432757680ebc5fb4174612111068056bc75e2d631000009384020592015b6808f00f760a4b2db55d831261435c576808f00f760a4b2db55d68056bc75e2d6310000084020592506802b5e3af16b1880000015b6806f5f17757889379378312614391576806f5f177578893793768056bc75e2d63100000840205925068015af1d78b58c40000015b6806248f33704b28660383126143c5576806248f33704b28660368056bc75e2d63100000840205925067ad78ebc5ac620000015b6805c548670b9510e7ac83126143f9576805c548670b9510e7ac68056bc75e2d6310000084020592506756bc75e2d6310000015b600068056bc75e2d63100000840168056bc75e2d63100000808603028161442257614422614c44565b059050600068056bc75e2d63100000828002059050818068056bc75e2d63100000818402059150600382050168056bc75e2d63100000828402059150600582050168056bc75e2d63100000828402059150600782050168056bc75e2d63100000828402059150600982050168056bc75e2d63100000828402059150600b820501600202606485820105979650505050505050565b62461bcd60e51b6000908152602060045260076024526642414c23000030600a808404818106603090810160081b95839006959095019082900491820690940160101b939093010160c81b604452606490fd5b60006119828260400151613e6e565b600081158061452e5750670de0b6b3a764000083145b156145425750670de0b6b3a7640000611982565b8261454f57506000611982565b670de0b6b3a7640000821415614566575081611982565b614579670de0b6b3a76400006002614b9c565b82141561458a5761337e838461237d565b61459d670de0b6b3a76400006004614b9c565b8214156145bc5760006145b0848561237d565b90506123c4818261237d565b60006145c88484613cb2565b905060006145db6124548361271061237d565b90506133f582826139dc565b634e487b7160e01b600052604160045260246000fd5b8015158114612fb357600080fd5b600061010080838503121561461f57600080fd5b6040519081019067ffffffffffffffff82118183101715614642576146426145e7565b81604052809250833581526020840135602082015260408401356040820152606084013560608201526080840135608082015260a084013560a082015260c084013560c082015260e08401359150614699826145fd565b60e0015292915050565b60008061012083850312156146b757600080fd5b6146c1848461460b565b94610100939093013593505050565b6000806000606084860312156146e557600080fd5b505081359360208301359350604090920135919050565b60006020828403121561470e57600080fd5b5035919050565b6000610100828403121561472857600080fd5b61197f838361460b565b6000806000806080858703121561474857600080fd5b84359350602085013592506040850135614761816145fd565b9396929550929360600135925050565b60006101e080838503121561478557600080fd5b83601f84011261479457600080fd5b60405181810181811067ffffffffffffffff821117156147b6576147b66145e7565b6040529083019080858311156147cb57600080fd5b845b838110156147e55780358252602091820191016147cd565b509095945050505050565b6000806040838503121561480357600080fd5b8235600f811061481257600080fd5b946020939093013593505050565b6000806040838503121561483357600080fd5b50508035926020909101359150565b6001600160a01b0381168114612fb357600080fd5b6000806040838503121561486a57600080fd5b823561481281614842565b803563ffffffff81168114611c9357600080fd5b600080828403608081121561489d57600080fd5b60608112156148ab57600080fd5b506040516060810181811067ffffffffffffffff821117156148cf576148cf6145e7565b6040526148db84614875565b81526148e960208501614875565b602082015260408401358060170b811461490257600080fd5b6040820152946060939093013593505050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561493e5761493e614915565b500190565b60208082526012908201527109eac98ac6274e6d8d2e0e0c2ceca7cdac2f60731b604082015260600190565b6020808252600f908201526e27ab262b189d1039b43aba3237bbb760891b604082015260600190565b6020808252600f908201526e27ab262b189d10b837b9b4ba34b7b760891b604082015260600190565b6000828210156149d3576149d3614915565b500390565b60008083128015600160ff1b8501841216156149f6576149f6614915565b6001600160ff1b0384018313811615614a1157614a11614915565b50500390565b60006001600160f01b0383811690831681811015614a3757614a37614915565b039392505050565b600060208284031215614a5157600080fd5b81516118e2816145fd565b600060208284031215614a6e57600080fd5b81516118e281614842565b600060208284031215614a8b57600080fd5b5051919050565b6000600019821415614aa657614aa6614915565b5060010190565b6020808252600f908201526e4f564c56313a2021666163746f727960881b604082015260600190565b6000610100808385031215614aea57600080fd5b6040519081019067ffffffffffffffff82118183101715614b0d57614b0d6145e7565b81604052835181526020840151602082015260408401516040820152606084015160608201526080840151608082015260a084015160a082015260c084015160c082015260e08401519150614b61826145fd565b60e08101919091529392505050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615614bb657614bb6614915565b500290565b60208082526027908201527f4f564c56313a206d6178206c657620696d6d6564696174656c79206c6971756960408201526664617461626c6560c81b606082015260800190565b60208082526022908201527f4f564c56313a2070726963652064726966742065786365656473206d61782065604082015261078760f41b606082015260800190565b634e487b7160e01b600052601260045260246000fd5b600082614c6957614c69614c44565b500490565b60006001600160ff1b0381841382841380821686840486111615614c9457614c94614915565b600160ff1b6000871282811687830589121615614cb357614cb3614915565b60008712925087820587128484161615614ccf57614ccf614915565b87850587128184161615614ce557614ce5614915565b505050929093029392505050565b600082614d0257614d02614c44565b600160ff1b821460001984141615614d1c57614d1c614915565b500590565b600063ffffffff83811690831681811015614a3757614a37614915565b600080821280156001600160ff1b0384900385131615614d6057614d60614915565b600160ff1b8390038412811615614d7957614d79614915565b5050019056fea2646970667358221220ee478acafbb18cfc986294a7b7b8431a058e742dfd924976abd552d038da8a6264736f6c634300080a0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101fb5760003560e01c80638eba35351161011a578063bf65b2fb116100ad578063d43cbd8e1161007c578063d43cbd8e146105db578063d565cc33146105ee578063ecc1619114610616578063f333fe1314610629578063fc0e74d11461063257600080fd5b8063bf65b2fb1461058b578063bf86d6901461059e578063c45a0155146105ab578063c6838e8b146105d257600080fd5b8063a2e62045116100e9578063a2e62045146104be578063b29fa9c314610529578063b445e2e714610550578063bcbaf4871461057857600080fd5b80638eba35351461045d57806392aac701146104705780639d2f053c146104835780639f0a54591461049657600080fd5b806358171a61116101925780635dedde6d116101615780635dedde6d1461041b578063640d0c28146104245780636c629159146104375780638607f5c31461044a57600080fd5b806358171a611461038457806359968288146103a75780635ad7226f146103ba5780635b6df29a146103cd57600080fd5b806337a7b7d8116101ce57806337a7b7d81461024157806346322c3714610280578063514ea4bf146102955780635312ea8e1461037157600080fd5b806309163014146102005780632acb38101461021c5780632eda95c2146102255780633197e19214610238575b600080fd5b61020960105481565b6040519081526020015b60405180910390f35b61020960115481565b6102096102333660046146a3565b61063a565b61020960195481565b6102687f000000000000000000000000ffdd8e8d16aed8cadf4b46dcaf4ba620dc269de181565b6040516001600160a01b039091168152602001610213565b61029361028e3660046146d0565b6106d4565b005b6103136102a33660046146fc565b601660205260009081526040902080546001909101546001600160601b0380831692600160601b810490911691600160c01b8204600290810b92600160d81b810490910b91600160f01b80830460ff90811693600160f81b900416916001600160f01b03811691900461ffff1688565b604080516001600160601b03998a168152989097166020890152600295860b968801969096529290930b60608601521515608085015290151560a08401526001600160f01b031660c083015261ffff1660e082015261010001610213565b61029361037f3660046146fc565b610dfb565b610397610392366004614715565b611008565b6040519015158152602001610213565b6102096103b5366004614732565b611074565b6102936103c8366004614771565b611624565b6015546103f59063ffffffff80821691600160201b810490911690600160401b900460170b83565b6040805163ffffffff948516815293909216602084015260170b90820152606001610213565b610209600f5481565b6102936104323660046147f0565b611847565b610209610445366004614715565b6118bb565b6102096104583660046146a3565b6118e9565b61020961046b366004614820565b611973565b61020961047e366004614715565b611988565b6102096104913660046146fc565b611a0e565b6104a96104a43660046146d0565b611a25565b60408051928352602083019190915201610213565b6104c6611b77565b6040516102139190600061010082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e0830151151560e083015292915050565b6102687f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f781565b6013546103f59063ffffffff80821691600160201b810490911690600160401b900460170b83565b610293610586366004614857565b611c98565b6102096105993660046146fc565b612196565b601a546103979060ff1681565b6102687f0000000000000000000000009a74758c2a80fa1b1d899e0e1f24cf505a4dea3381565b61020960185481565b6102096105e9366004614889565b612204565b6014546103f59063ffffffff80821691600160201b810490911690600160401b900460170b83565b6102096106243660046146a3565b612288565b61020960125481565b6102936122be565b600061064e83606001518460800151612338565b9050600061065d81600261234f565b9050600061066c81600161234f565b9050600061067a828661237d565b610684908461492b565b90506801158e460913d0000081106106b75760405162461bcd60e51b81526004016106ae90614943565b60405180910390fd5b6106ca6106c3826123cc565b859061237d565b9695505050505050565b601a5460ff16156106f75760405162461bcd60e51b81526004016106ae9061496f565b670de0b6b3a76400008211156107445760405162461bcd60e51b815260206004820152601260248201527109eac98ac6274cce4c2c6e8d2dedc7cdac2f60731b60448201526064016106ae565b61075961075083612467565b61ffff166124e0565b9150600082116107a05760405162461bcd60e51b815260206004820152601260248201527127ab262b189d333930b1ba34b7b71e36b4b760711b60448201526064016106ae565b60008060008060006107b0611b77565b905060006107c06016338b612507565b90506107cb81612620565b6107e75760405162461bcd60e51b81526004016106ae90614998565b600081608001516107fa576010546107fe565b600f545b90506000826080015161081357601254610817565b6011545b905061085782826108278761263d565b6108336000600361234f565b61083f6000600861234f565b61084b6000600a61234f565b89959493929190612651565b156108995760405162461bcd60e51b81526020600482015260126024820152714f564c56313a6c6971756964617461626c6560701b60448201526064016106ae565b60006108b66108ad8661062484600461234f565b61046b8761263d565b905083608001516108eb576108e685610233876108e08f88888b6126da909392919063ffffffff16565b85612717565b610910565b610910856104588761090a8f88888b6126da909392919063ffffffff16565b856127de565b965083608001516109245789871115610929565b898710155b6109455760405162461bcd60e51b81526004016106ae90614943565b600061095281600361234f565b9050610962858d86868c866128a0565b995061096e858d6129ac565b9850600061097d81600b61234f565b905061098e868e87878d87876129d4565b975061099a888c6129fe565b97508560800151156109e7576109be6109b5878f88886126da565b600f5490612a0d565b600f556109cb868e612a28565b601160008282546109dc91906149c1565b90915550610a239050565b6109ff6109f6878f88886126da565b60105490612a0d565b601055610a0c868e612a28565b60126000828254610a1d91906149c1565b90915550505b610a35610a308b8d6149d8565b612a4b565b50610a40868e612a28565b8660c001818151610a519190614a17565b6001600160f01b0316905250610a67868e612b09565b8660e0019061ffff16908161ffff1681525050610a92338f886016612b83909392919063ffffffff16565b50505050505050336001600160a01b03167fc13b78a0772a556b5387d497953273371ed42cff2af20c019d9f119a737685ba88888688610ad291906149d8565b604080519384526020840192909252908201526060810185905260800160405180910390a2828410610b9b576001600160a01b037f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f7166340c10f1930610b3886886149c1565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610b7e57600080fd5b505af1158015610b92573d6000803e3d6000fd5b50505050610c25565b6001600160a01b037f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f7166342966c68610bd486866149c1565b6040518263ffffffff1660e01b8152600401610bf291815260200190565b600060405180830381600087803b158015610c0c57600080fd5b505af1158015610c20573d6000803e3d6000fd5b505050505b6001600160a01b037f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f71663a9059cbb33610c5f84886149c1565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015610caa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cce9190614a3f565b507f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f76001600160a01b031663a9059cbb7f0000000000000000000000009a74758c2a80fa1b1d899e0e1f24cf505a4dea336001600160a01b031663469048406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d809190614a5c565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015610dcd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df19190614a3f565b5050505050505050565b601a5460ff16610e405760405162461bcd60e51b815260206004820152601060248201526f27ab262b189d1010b9b43aba3237bbb760811b60448201526064016106ae565b6000610e4e60163384612507565b9050610e5981612620565b610e755760405162461bcd60e51b81526004016106ae90614998565b670de0b6b3a76400006000610e8a83836129ac565b6040516370a0823160e01b8152306004820152909150610f1f906001600160a01b037f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f716906370a0823190602401602060405180830381865afa158015610ef5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f199190614a79565b826129fe565b600060e08501529050610f356016338686612b83565b604080518581526020810183905233917fbb757047c2b5f3974fe26b7c10f732e7bce710b0952a71082702781e62ae0595910160405180910390a260405163a9059cbb60e01b8152336004820152602481018290527f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f76001600160a01b03169063a9059cbb906044016020604051808303816000875af1158015610fdd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110019190614a3f565b5050505050565b60195460009081611021670de0b6b3a764000083612ca8565b608085015160a08601519192509080158061103a575081155b1561104b5750600095945050505050565b60006110578383612cd7565b90508381101580156110695750848111155b979650505050505050565b601a5460009060ff161561109a5760405162461bcd60e51b81526004016106ae9061496f565b670de0b6b3a76400008410156110e25760405162461bcd60e51b815260206004820152600d60248201526c27ab262b189d3632bb1e36b4b760991b60448201526064016106ae565b6110ee6000600561234f565b84111561112d5760405162461bcd60e51b815260206004820152600d60248201526c09eac98ac6274d8caec7cdac2f609b1b60448201526064016106ae565b6111396000600c61234f565b85101561117f5760405162461bcd60e51b815260206004820152601460248201527327ab262b189d31b7b63630ba32b930b61e36b4b760611b60448201526064016106ae565b600080600080600061118f611b77565b9050600061119d8b8b61237d565b905060006111aa8361263d565b90506111b68282611973565b9650600087116111f65760405162461bcd60e51b815260206004820152600b60248201526a04f564c56313a6f693d3d360ac1b60448201526064016106ae565b6112008c836149c1565b95506112186112116000600b61234f565b839061237d565b9350600061123461122e8561062484600461234f565b83611973565b90508a61124f5761124a84610458868b856127de565b61125e565b61125e84610233868b85612717565b95508a61126e5789861015611273565b898611155b61128f5760405162461bcd60e51b81526004016106ae90614943565b600061129c89838e612d08565b90506000604051806101000160405280866001600160601b031681526020018a6001600160601b031681526020016112d386612dd1565b60020b81526020016112e48a612dd1565b60020b81528e15156020820152600060408201526001600160f01b038416606082015260800161131b670de0b6b3a7640000612467565b61ffff16905290506113798d61133357601054611337565b600f545b8e61134457601254611348565b6011545b866113556000600361234f565b6113616000600861234f565b61136d6000600a61234f565b87959493929190612651565b156113bb5760405162461bcd60e51b81526020600482015260126024820152714f564c56313a6c6971756964617461626c6560701b60448201526064016106ae565b6017549a506113cd6016338d84612b83565b601780549060006113dd83614a92565b9091555050604080518c8152602081018c90529081018a90528d15156060820152608081018990523396507fb98b46cc473761b09478db481c36070133bf6b7a18241892f5477e725b063b5a955060a001935061143992505050565b60405180910390a26001600160a01b037f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f7166323b872dd333061147c858e61492b565b6040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064016020604051808303816000875af11580156114d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f49190614a3f565b507f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f76001600160a01b031663a9059cbb7f0000000000000000000000009a74758c2a80fa1b1d899e0e1f24cf505a4dea336001600160a01b031663469048406040518163ffffffff1660e01b8152600401602060405180830381865afa158015611582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a69190614a5c565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af11580156115f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116179190614a3f565b5050505050949350505050565b336001600160a01b037f0000000000000000000000009a74758c2a80fa1b1d899e0e1f24cf505a4dea33161461166c5760405162461bcd60e51b81526004016106ae90614aad565b60007f000000000000000000000000ffdd8e8d16aed8cadf4b46dcaf4ba620dc269de16001600160a01b03166352bfe7896040518163ffffffff1660e01b815260040161010060405180830381865afa1580156116cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f19190614ad6565b905060006116fe8261263d565b116117395760405162461bcd60e51b815260206004820152600b60248201526a4f564c56313a216461746160a81b60448201526064016106ae565b4260185560a0820151604083015161010084015161014085015161179661177261176b83670de0b6b3a76400006149c1565b8490612ca8565b61177d856002614b9c565b611787919061492b565b670de0b6b3a764000090612ca8565b8411156117b55760405162461bcd60e51b81526004016106ae90614bbb565b6101a086015160408601516801158e460913d00000906117d59083614b9c565b106117f25760405162461bcd60e51b81526004016106ae90614c02565b6117fd600d82612e67565b60005b600f811015610df1578781600f811061181b5761181b614b86565b6020020151600082600f811061183357611833614b86565b01558061183f81614a92565b915050611800565b336001600160a01b037f0000000000000000000000009a74758c2a80fa1b1d899e0e1f24cf505a4dea33161461188f5760405162461bcd60e51b81526004016106ae90614aad565b611897612f32565b6118a18282612fb6565b6118ab8282612e67565b6118b7600083836132c0565b5050565b6000806118c981600161234f565b90506118e28360c00151826132eb90919063ffffffff16565b9392505050565b60006118fd836060015184608001516129fe565b9050600061190c81600261234f565b9050600061191b81600161234f565b90506000611929828661237d565b611933908461492b565b90506801158e460913d00000811061195d5760405162461bcd60e51b81526004016106ae90614943565b6106ca61196c611787836123cc565b85906132eb565b600061197f8383612ca8565b90505b92915050565b60008061199681600e61234f565b9050600081670de0b6b3a764000085604001516119b39190614b9c565b6119bd9190614c5a565b905060006119cc81600261234f565b9050611a056119e4670de0b6b3a76400006002614b9c565b6119ff846119ff8960c00151866132eb90919063ffffffff16565b906132eb565b95945050505050565b600081600f8110611a1e57600080fd5b0154905081565b60008080611a33858761492b565b90506000611a4186886149c1565b90506000611a4f878961237d565b9050821580611a5c575081155b15611a6f57878794509450505050611b6f565b60008087611a7d828061234f565b611a88906002614b9c565b611a929190614b9c565b90506801158e460913d00000811015611ab457611ab1611787826123cc565b91505b6000611ac08587612ca8565b90506000611aed611ad185806132eb565b611ae390670de0b6b3a76400006149c1565b6119ff84806132eb565b611aff90670de0b6b3a76400006149c1565b9050611b28611b21611b1a6002670de0b6b3a7640000614c5a565b839061330c565b88906132eb565b9650611b3486856132eb565b95506002611b42878961492b565b611b4c9190614c5a565b9b508b15611b6157611b5e858d612cd7565b9a505b8b8b98509850505050505050505b935093915050565b611bc1604051806101000160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581525090565b611bc9612f32565b60007f000000000000000000000000ffdd8e8d16aed8cadf4b46dcaf4ba620dc269de16001600160a01b03166352bfe7896040518163ffffffff1660e01b815260040161010060405180830381865afa158015611c2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4e9190614ad6565b9050611c5981611008565b611c935760405162461bcd60e51b815260206004820152600b60248201526a4f564c56313a216461746160a81b60448201526064016106ae565b919050565b601a5460ff1615611cbb5760405162461bcd60e51b81526004016106ae9061496f565b6000808080808080611ccf60168a8a612507565b9050611cda81612620565b611cf65760405162461bcd60e51b81526004016106ae90614998565b6000611d00611b77565b905060008260800151611d1557601054611d19565b600f545b905060008360800151611d2e57601254611d32565b6011545b90506000611d4181600361234f565b9050670de0b6b3a7640000611d558561263d565b9950611d8284848c85611d6a6000600861234f565b611d766000600a61234f565b8c959493929190612651565b611dc45760405162461bcd60e51b81526020600482015260136024820152724f564c56313a216c6971756964617461626c6560681b60448201526064016106ae565b611dd2868286868e876128a0565b9b50611dde86826129ac565b9a50611df6611def6000600a61234f565b8d906132eb565b9850611e02898d6149c1565b9650611e13611b216000600961234f565b9750611e1f88886149c1565b9650856080015115611e6357611e3a6109b5878387876126da565b600f55611e478682612a28565b60116000828254611e5891906149c1565b90915550611e969050565b611e726109f6878387876126da565b601055611e7f8682612a28565b60126000828254611e9091906149c1565b90915550505b611eae88611ea48d8f6149d8565b610a3091906149d8565b50600160a0870152600060c0870181905260e0870152611ed160168f8f89612b83565b505050505050876001600160a01b0316336001600160a01b03167ff1deb4d6391f20e8cad919356063127cf8453da1fdf246eb1b5e4549e848112e8985898b611f1a91906149d8565b611f2491906149d8565b604080519283526020830191909152810188905260600160405180910390a36001600160a01b037f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f7166342966c6883611f7d89896149c1565b611f87919061492b565b6040518263ffffffff1660e01b8152600401611fa591815260200190565b600060405180830381600087803b158015611fbf57600080fd5b505af1158015611fd3573d6000803e3d6000fd5b505060405163a9059cbb60e01b8152336004820152602481018690527f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f76001600160a01b0316925063a9059cbb91506044016020604051808303816000875af1158015612044573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120689190614a3f565b507f000000000000000000000000dc77acc82cce1cc095cba197474cc06824ade6f76001600160a01b031663a9059cbb7f0000000000000000000000009a74758c2a80fa1b1d899e0e1f24cf505a4dea336001600160a01b031663469048406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211a9190614a5c565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af1158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b9190614a3f565b505050505050505050565b6040805160608101825260155463ffffffff8082168352600160201b820481166020840152600160401b90910460170b9282019290925260009182906121e190829060069061234f16565b90506121f082428360006133fe565b91506121fc8285612204565b949350505050565b600080612215846040015160170b90565b9050600061222481600761234f565b9050808213612237578392505050611982565b612242816002614c6e565b821261225357600092505050611982565b600061225f8383612ca8565b612272670de0b6b3a76400006002614b9c565b61227c91906149c1565b90506106ca85826132eb565b60008260e00151156122b8576122a6826122a1856118bb565b6129fe565b91506122b5826122a185611988565b91505b50919050565b601a5460ff16156122e15760405162461bcd60e51b81526004016106ae9061496f565b336001600160a01b037f0000000000000000000000009a74758c2a80fa1b1d899e0e1f24cf505a4dea3316146123295760405162461bcd60e51b81526004016106ae90614aad565b601a805460ff19166001179055565b600081831015612348578161197f565b5090919050565b60008282600e81111561236457612364614b70565b600f811061237457612374614b86565b01549392505050565b60008061238a8385614b9c565b90508061239b576000915050611982565b670de0b6b3a76400006123af6001836149c1565b6123b99190614c5a565b6123c490600161492b565b915050611982565b6000816123e25750670de0b6b3a7640000919050565b600160ff1b82106124355760405162461bcd60e51b815260206004820152601b60248201527f4669786564506f696e743a2078206f7574206f6620626f756e6473000000000060448201526064016106ae565b816000612441826135fa565b9050600061245b6124548361271061237d565b60016139dc565b9050611a0582826139dc565b60008061247e612710670de0b6b3a7640000614c5a565b9050600061248c8285614c5a565b905061ffff8111156118e25760405162461bcd60e51b815260206004820152601e60248201527f4f564c56313a20466978656443617374206f7574206f6620626f756e6473000060448201526064016106ae565b6000806124f7612710670de0b6b3a7640000614c5a565b90506118e28161ffff8516614b9c565b60408051610100810182526000808252602080830182905282840182905260608084018390526080840183905260a0840183905260c0840183905260e090930182905283519590921b6bffffffffffffffffffffffff1916858301526034808601949094528251808603909401845260548501808452845194830194909420815294905292839020610154830190935282546001600160601b038082168352600160601b8204166074840152600160c01b8104600290810b6094850152600160d81b8204900b60b4840152600160f01b80820460ff908116151560d4860152600160f81b909204909116151560f48401526001909301546001600160f01b0381166101148401529290920461ffff166101349091015290565b60008160a0015115801561198257505060e0015161ffff16151590565b6000611982826060015183608001516139e9565b6000670de0b6b3a7640000816126678a83613a04565b90508960a001518061267f575060e08a015161ffff16155b1561268f57600092505050611069565b600061269f8b848c8c8c8c6128a0565b905060006126ad838861237d565b905060006126bb83886132eb565b90506126c7818361492b565b9092109c9b505050505050505050505050565b6000806126e78686612a28565b90508015806126f4575083155b806126fd575082155b1561270c5760009150506121fc565b6106ca818585613a35565b6040805160608101825260145463ffffffff8082168352600160201b820481166020840152600160401b90910460170b9282019290925260009182906127619086908690612cd716565b60208701519091506127779083904290846133fe565b8051601480546020840151604085015163ffffffff94851667ffffffffffffffff1990931692909217600160201b94909116939093029290921767ffffffffffffffff16600160401b6001600160c01b0384160217905590925060170b9695505050505050565b6040805160608101825260135463ffffffff8082168352600160201b820481166020840152600160401b90910460170b9282019290925260009182906128289086908690612cd716565b602087015190915061283e9083904290846133fe565b8051601380546020840151604085015163ffffffff94851667ffffffffffffffff1990931692909217600160201b94909116939093029290921767ffffffffffffffff16600160401b6001600160c01b0384160217905590925060170b6106ca565b6000806128ad8888613ae8565b905060006128bb8989613a04565b905060006128c98a8a613b05565b905060006128d98b8b8b8b6126da565b905060006128e68c613b2d565b90508b6080015115612969576129246128ff838a61237d565b6122a16129148a670de0b6b3a764000061492b565b61291e868661237d565b9061237d565b61293886612932878661237d565b90612cd7565b612942919061492b565b9550612962612951838361237d565b61295b908561492b565b8790612a0d565b955061299d565b612973828261237d565b61298186612932878661237d565b61298b919061492b565b955061299a612951838a61237d565b95505b50505050509695505050505050565b6000806129b98484613a04565b905060006129c78585613b05565b9050816106ca8183612a0d565b6000806129e5898989898989613b3c565b90506129f1818461237d565b9998505050505050505050565b6000818310612348578161197f565b600080828411612a1e5760006121fc565b6121fc83856149c1565b600080612a3f8460c001516001600160f01b031690565b90506121fc81846132eb565b6040805160608101825260155463ffffffff8082168352600160201b820481166020840152600160401b90910460170b928201929092526000918290612a9690829060069061234f16565b9050612aa4824283876133fe565b8051601580546020840151604085015163ffffffff94851667ffffffffffffffff1990931692909217600160201b94909116939093029290921767ffffffffffffffff16600160401b6001600160c01b0384160217905590925060009060170b611a05565b6000670de0b6b3a7640000821115612b585760405162461bcd60e51b815260206004820152601260248201527109eac98ac6274cce4c2c6e8d2dedc7cdac2f60731b60448201526064016106ae565b6000612b78612b6f84670de0b6b3a76400006149c1565b6119ff86613b67565b90506121fc81612467565b6040516bffffffffffffffffffffffff19606085901b166020820152603481018390528190859060009060540160408051808303601f1901815291815281516020928301208352828201939093529082016000208351815492850151938501516060860151608087015160a08801516001600160601b039485166001600160c01b031990971696909617600160601b94909716939093029590951765ffffffffffff60c01b1916600160c01b62ffffff9283160262ffffff60d81b191617600160d81b9190951602939093176001600160f01b03908116600160f01b94151585026001600160f81b031617600160f81b9315159390930292909217815560c084015160e0909401519390911661ffff9093169091029190911760019091015550505050565b600082612cb757506000611982565b6000612ccb670de0b6b3a764000085614b9c565b90506123c48382614c5a565b600082612ce657506000611982565b6000612cfa670de0b6b3a764000085614b9c565b9050826123af6001836149c1565b60008082612d1857601054612d1c565b600f545b9050600083612d2d57601254612d31565b6011545b90506000612d40878484613b7a565b9050612d4c878461492b565b9250612d58818361492b565b91506000612d6587612196565b905080841115612da65760405162461bcd60e51b815260206004820152600c60248201526b04f564c56313a6f693e6361760a41b60448201526064016106ae565b8515612dbb57600f8490556011839055612dc6565b601084905560128390555b509695505050505050565b600080612de683670de111a6b7de4000613ba3565b90506956d225004ee68c3fffff198112158015612e0d575069fe1c215e8f838e0000008113155b612e555760405162461bcd60e51b81526020600482015260196024820152784f564c56313a207469636b206f7574206f6620626f756e647360381b60448201526064016106ae565b6118e2670de0b6b3a764000082614cf3565b600d82600e811115612e7b57612e7b614b70565b14156118b75760007f000000000000000000000000ffdd8e8d16aed8cadf4b46dcaf4ba620dc269de16001600160a01b03166352bfe7896040518163ffffffff1660e01b815260040161010060405180830381865afa158015612ee2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f069190614ad6565b60408101519091508290600090612f1d9083614b9c565b9050612f28816123cc565b6019555050505050565b600060185442612f4291906149c1565b90508015612fb357601054600f5411600081612f6057601054612f64565b600f545b9050600082612f7557600f54612f79565b6010545b9050612f86828286611a25565b909250905082612f965780612f98565b815b600f5582612fa65781612fa8565b805b601055505042601855505b50565b600282600e811115612fca57612fca614b70565b141561304557806000612fde81600561234f565b90506000612fed81600861234f565b90506000612ffc81600a61234f565b905061302161301661176b83670de0b6b3a76400006149c1565b61177d866002614b9c565b8311156130405760405162461bcd60e51b81526004016106ae90614bbb565b505050505b600582600e81111561305957613059614b70565b14156130c95780600061306d81600261234f565b9050600061307c81600861234f565b9050600061308b81600a61234f565b90506130a561177261176b83670de0b6b3a76400006149c1565b8411156130c45760405162461bcd60e51b81526004016106ae90614bbb565b505050505b600882600e8111156130dd576130dd614b70565b1415613154578060006130f181600261234f565b9050600061310081600561234f565b9050600061310f81600a61234f565b905061313061177261312983670de0b6b3a76400006149c1565b8690612ca8565b82111561314f5760405162461bcd60e51b81526004016106ae90614bbb565b505050505b600a82600e81111561316857613168614b70565b14156131df5780600061317c81600261234f565b9050600061318b81600561234f565b9050600061319a81600861234f565b90506131bb6117726131b486670de0b6b3a76400006149c1565b8390612ca8565b8211156131da5760405162461bcd60e51b81526004016106ae90614bbb565b505050505b600d82600e8111156131f3576131f3614b70565b14156118b75760007f000000000000000000000000ffdd8e8d16aed8cadf4b46dcaf4ba620dc269de16001600160a01b03166352bfe7896040518163ffffffff1660e01b815260040161010060405180830381865afa15801561325a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327e9190614ad6565b604081015190915082906801158e460913d000009061329d9083614b9c565b106132ba5760405162461bcd60e51b81526004016106ae90614c02565b50505050565b808383600e8111156132d4576132d4614b70565b600f81106132e4576132e4614b86565b0155505050565b6000806132f88385614b9c565b90506121fc670de0b6b3a764000082614c5a565b60008115806133225750670de0b6b3a764000083145b156133365750670de0b6b3a7640000611982565b8261334357506000611982565b670de0b6b3a764000082141561335a575081611982565b61336d670de0b6b3a76400006002614b9c565b8214156133855761337e83846132eb565b9050611982565b613398670de0b6b3a76400006004614b9c565b8214156133b75760006133ab84856132eb565b90506123c481826132eb565b60006133c38484613cb2565b905060006133d66124548361271061237d565b9050808210156133eb57600092505050611982565b6133f58282613db3565b92505050611982565b6040805160608101825260008082526020820181905291810182905285519091859163ffffffff908116908316101561345b57865163ffffffff9081169061344c908416600160201b61492b565b61345691906149c1565b61346e565b86516134679083614d21565b63ffffffff165b602088015190915063ffffffff16600061348c896040015160170b90565b9050818310158061349b575081155b156134e55760405180606001604052808563ffffffff1681526020016134c089613dc0565b63ffffffff1681526020016134d488613dd9565b60170b8152509450505050506121fc565b816134f084826149c1565b6134fa9083614c6e565b6135049190614cf3565b905060006135128783614d3e565b9050806135565760405180606001604052808663ffffffff1681526020016135398a613dc0565b63ffffffff168152600060209091015295506121fc945050505050565b600061356183613e1c565b9050600061356e89613e1c565b9050600061357c828461492b565b6135868c84614b9c565b61359089896149c1565b61359a9086614b9c565b6135a4919061492b565b6135ae9190614c5a565b905060405180606001604052808963ffffffff1681526020016135d083613dc0565b63ffffffff1681526020016135e486613dd9565b60170b90529d9c50505050505050505050505050565b6000613629680238fd42c5cf03ffff198312158015613622575068070c1cc73b00c800008313155b6009613e33565b60008212156136615761363e826000036135fa565b6a0c097ce7bc90715b34b9f160241b8161365a5761365a614c44565b0592915050565b60006806f05b59d3b200000083126136a157506806f05b59d3b1ffffff1990910190770195e54c5dd42177f53a27172fa9ec6302628270000000006136d7565b6803782dace9d900000083126136d357506803782dace9d8ffffff19909101906b1425982cf597cd205cef73806136d7565b5060015b6064929092029168056bc75e2d6310000068ad78ebc5ac6200000084126137275768ad78ebc5ac61ffffff199093019268056bc75e2d631000006e01855144814a7ff805980ff008400082020590505b6856bc75e2d6310000008412613763576856bc75e2d630ffffff199093019268056bc75e2d631000006b02df0ab5a80a22c61ab5a70082020590505b682b5e3af16b18800000841261379d57682b5e3af16b187fffff199093019268056bc75e2d63100000693f1fce3da636ea5cf85082020590505b6815af1d78b58c40000084126137d7576815af1d78b58c3fffff199093019268056bc75e2d63100000690127fa27722cc06cc5e282020590505b680ad78ebc5ac6200000841261381057680ad78ebc5ac61fffff199093019268056bc75e2d6310000068280e60114edb805d0382020590505b68056bc75e2d6310000084126138495768056bc75e2d630fffff199093019268056bc75e2d63100000680ebc5fb4174612111082020590505b6802b5e3af16b18800008412613882576802b5e3af16b187ffff199093019268056bc75e2d631000006808f00f760a4b2db55d82020590505b68015af1d78b58c4000084126138bb5768015af1d78b58c3ffff199093019268056bc75e2d631000006806f5f177578893793782020590505b68056bc75e2d631000008481019085906002908280020505918201919050600368056bc75e2d631000008783020505918201919050600468056bc75e2d631000008783020505918201919050600568056bc75e2d631000008783020505918201919050600668056bc75e2d631000008783020505918201919050600768056bc75e2d631000008783020505918201919050600868056bc75e2d631000008783020505918201919050600968056bc75e2d631000008783020505918201919050600a68056bc75e2d631000008783020505918201919050600b68056bc75e2d631000008783020505918201919050600c68056bc75e2d631000008783020505918201919050606468056bc75e2d63100000848402058502059695505050505050565b6000806121fc838561492b565b60006139f86002848418614c5a565b61197f9084841661492b565b600080613a1084613b67565b90506000613a298261291e87516001600160601b031690565b9050611a05818561237d565b600080806000198587098587029250828110838203039150508060001415613a6f5760008411613a6457600080fd5b5082900490506118e2565b808411613a7b57600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b600080613af484613b67565b90506000613a298261291e87613e41565b600080613b1184613b67565b90506000613a298261291e87602001516001600160601b031690565b60006119828260600151613e6e565b600080613b4d8888888888886128a0565b90506000613b5b8989613b05565b90506129f1818361492b565b60006119828260e0015161ffff166124e0565b6000821580613b87575081155b613b9b57613b96848385613a35565b6121fc565b509192915050565b60008083118015613bb75750600160ff1b83105b613c035760405162461bcd60e51b815260206004820152601b60248201527f4669786564506f696e743a2061206f7574206f6620626f756e6473000000000060448201526064016106ae565b600082118015613c165750600160ff1b82105b613c625760405162461bcd60e51b815260206004820152601b60248201527f4669786564506f696e743a2062206f7574206f6620626f756e6473000000000060448201526064016106ae565b82826000613c708383613f33565b9050600080821215613c855781600003613c87565b815b90506000613c9a6124548361271061237d565b9050613ca681846149d8565b98975050505050505050565b600081613cc85750670de0b6b3a7640000611982565b82613cd557506000611982565b613ce6600160ff1b84106006613e33565b82613d0c770bce5086492111aea88f4bb1ca6bcf584181ea8059f7653284106007613e33565b826000670c7d713b49da000083138015613d2d5750670f43fc2c04ee000083125b15613d64576000613d3d84613fed565b9050670de0b6b3a764000080820784020583670de0b6b3a764000083050201915050613d72565b81613d6e8461410c565b0290505b670de0b6b3a76400009005613daa680238fd42c5cf03ffff198212801590613da3575068070c1cc73b00c800008213155b6008613e33565b6106ca816135fa565b6000806121fc83856149c1565b60008063ffffffff8311156123485763ffffffff6118e2565b6000806001600160bf1b03198312613e0c576001600160bf1b038313613dff57826118e2565b6001600160bf1b036118e2565b6001600160bf1b03199392505050565b600080821215613e2f5781600003611982565b5090565b816118b7576118b7816144b6565b600080613e5583516001600160601b031690565b90506000613e6284614509565b90506121fc8282612ca8565b600080613e87670de0b6b3a7640000600285900b614c6e565b90506956d225004ee68c3fffff198112158015613eae575069fe1c215e8f838e0000008113155b613ef65760405162461bcd60e51b81526020600482015260196024820152784f564c56313a207469636b206f7574206f6620626f756e647360381b60448201526064016106ae565b6000613f0182613e1c565b90506000821215613f2157613b96611787670de111a6b7de400083614518565b6121fc670de111a6b7de40008261330c565b600080670c7d713b49da000083138015613f545750670f43fc2c04ee000083125b15613f6957613f6283613fed565b9050613f7f565b670de0b6b3a7640000613f7b8461410c565b0290505b6000670c7d713b49da000085138015613f9f5750670f43fc2c04ee000085125b15613fb457613fad85613fed565b9050613fca565b670de0b6b3a7640000613fc68661410c565b0290505b81670de0b6b3a7640000820281613fe357613fe3614c44565b0595945050505050565b670de0b6b3a7640000026000806a0c097ce7bc90715b34b9f160241b808401906ec097ce7bc90715b34b9f0fffffffff198501028161402e5761402e614c44565b05905060006a0c097ce7bc90715b34b9f160241b82800205905081806a0c097ce7bc90715b34b9f160241b81840205915060038205016a0c097ce7bc90715b34b9f160241b82840205915060058205016a0c097ce7bc90715b34b9f160241b82840205915060078205016a0c097ce7bc90715b34b9f160241b82840205915060098205016a0c097ce7bc90715b34b9f160241b828402059150600b8205016a0c097ce7bc90715b34b9f160241b828402059150600d8205016a0c097ce7bc90715b34b9f160241b828402059150600f82050160020295945050505050565b6000670de0b6b3a764000082121561414d57614144826a0c097ce7bc90715b34b9f160241b8161413e5761413e614c44565b0561410c565b60000392915050565b60007e1600ef3172e58d2e933ec884fde10064c63b5372d805e203c0000000000000831261419e57770195e54c5dd42177f53a27172fa9ec630262827000000000830592506806f05b59d3b2000000015b73011798004d755d3c8bc8e03204cf44619e00000083126141d6576b1425982cf597cd205cef7380830592506803782dace9d9000000015b606492830292026e01855144814a7ff805980ff0084000831261421e576e01855144814a7ff805980ff008400068056bc75e2d63100000840205925068ad78ebc5ac62000000015b6b02df0ab5a80a22c61ab5a7008312614259576b02df0ab5a80a22c61ab5a70068056bc75e2d6310000084020592506856bc75e2d631000000015b693f1fce3da636ea5cf850831261429057693f1fce3da636ea5cf85068056bc75e2d631000008402059250682b5e3af16b18800000015b690127fa27722cc06cc5e283126142c757690127fa27722cc06cc5e268056bc75e2d6310000084020592506815af1d78b58c400000015b68280e60114edb805d0383126142fc5768280e60114edb805d0368056bc75e2d631000008402059250680ad78ebc5ac6200000015b680ebc5fb41746121110831261432757680ebc5fb4174612111068056bc75e2d631000009384020592015b6808f00f760a4b2db55d831261435c576808f00f760a4b2db55d68056bc75e2d6310000084020592506802b5e3af16b1880000015b6806f5f17757889379378312614391576806f5f177578893793768056bc75e2d63100000840205925068015af1d78b58c40000015b6806248f33704b28660383126143c5576806248f33704b28660368056bc75e2d63100000840205925067ad78ebc5ac620000015b6805c548670b9510e7ac83126143f9576805c548670b9510e7ac68056bc75e2d6310000084020592506756bc75e2d6310000015b600068056bc75e2d63100000840168056bc75e2d63100000808603028161442257614422614c44565b059050600068056bc75e2d63100000828002059050818068056bc75e2d63100000818402059150600382050168056bc75e2d63100000828402059150600582050168056bc75e2d63100000828402059150600782050168056bc75e2d63100000828402059150600982050168056bc75e2d63100000828402059150600b820501600202606485820105979650505050505050565b62461bcd60e51b6000908152602060045260076024526642414c23000030600a808404818106603090810160081b95839006959095019082900491820690940160101b939093010160c81b604452606490fd5b60006119828260400151613e6e565b600081158061452e5750670de0b6b3a764000083145b156145425750670de0b6b3a7640000611982565b8261454f57506000611982565b670de0b6b3a7640000821415614566575081611982565b614579670de0b6b3a76400006002614b9c565b82141561458a5761337e838461237d565b61459d670de0b6b3a76400006004614b9c565b8214156145bc5760006145b0848561237d565b90506123c4818261237d565b60006145c88484613cb2565b905060006145db6124548361271061237d565b90506133f582826139dc565b634e487b7160e01b600052604160045260246000fd5b8015158114612fb357600080fd5b600061010080838503121561461f57600080fd5b6040519081019067ffffffffffffffff82118183101715614642576146426145e7565b81604052809250833581526020840135602082015260408401356040820152606084013560608201526080840135608082015260a084013560a082015260c084013560c082015260e08401359150614699826145fd565b60e0015292915050565b60008061012083850312156146b757600080fd5b6146c1848461460b565b94610100939093013593505050565b6000806000606084860312156146e557600080fd5b505081359360208301359350604090920135919050565b60006020828403121561470e57600080fd5b5035919050565b6000610100828403121561472857600080fd5b61197f838361460b565b6000806000806080858703121561474857600080fd5b84359350602085013592506040850135614761816145fd565b9396929550929360600135925050565b60006101e080838503121561478557600080fd5b83601f84011261479457600080fd5b60405181810181811067ffffffffffffffff821117156147b6576147b66145e7565b6040529083019080858311156147cb57600080fd5b845b838110156147e55780358252602091820191016147cd565b509095945050505050565b6000806040838503121561480357600080fd5b8235600f811061481257600080fd5b946020939093013593505050565b6000806040838503121561483357600080fd5b50508035926020909101359150565b6001600160a01b0381168114612fb357600080fd5b6000806040838503121561486a57600080fd5b823561481281614842565b803563ffffffff81168114611c9357600080fd5b600080828403608081121561489d57600080fd5b60608112156148ab57600080fd5b506040516060810181811067ffffffffffffffff821117156148cf576148cf6145e7565b6040526148db84614875565b81526148e960208501614875565b602082015260408401358060170b811461490257600080fd5b6040820152946060939093013593505050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561493e5761493e614915565b500190565b60208082526012908201527109eac98ac6274e6d8d2e0e0c2ceca7cdac2f60731b604082015260600190565b6020808252600f908201526e27ab262b189d1039b43aba3237bbb760891b604082015260600190565b6020808252600f908201526e27ab262b189d10b837b9b4ba34b7b760891b604082015260600190565b6000828210156149d3576149d3614915565b500390565b60008083128015600160ff1b8501841216156149f6576149f6614915565b6001600160ff1b0384018313811615614a1157614a11614915565b50500390565b60006001600160f01b0383811690831681811015614a3757614a37614915565b039392505050565b600060208284031215614a5157600080fd5b81516118e2816145fd565b600060208284031215614a6e57600080fd5b81516118e281614842565b600060208284031215614a8b57600080fd5b5051919050565b6000600019821415614aa657614aa6614915565b5060010190565b6020808252600f908201526e4f564c56313a2021666163746f727960881b604082015260600190565b6000610100808385031215614aea57600080fd5b6040519081019067ffffffffffffffff82118183101715614b0d57614b0d6145e7565b81604052835181526020840151602082015260408401516040820152606084015160608201526080840151608082015260a084015160a082015260c084015160c082015260e08401519150614b61826145fd565b60e08101919091529392505050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615614bb657614bb6614915565b500290565b60208082526027908201527f4f564c56313a206d6178206c657620696d6d6564696174656c79206c6971756960408201526664617461626c6560c81b606082015260800190565b60208082526022908201527f4f564c56313a2070726963652064726966742065786365656473206d61782065604082015261078760f41b606082015260800190565b634e487b7160e01b600052601260045260246000fd5b600082614c6957614c69614c44565b500490565b60006001600160ff1b0381841382841380821686840486111615614c9457614c94614915565b600160ff1b6000871282811687830589121615614cb357614cb3614915565b60008712925087820587128484161615614ccf57614ccf614915565b87850587128184161615614ce557614ce5614915565b505050929093029392505050565b600082614d0257614d02614c44565b600160ff1b821460001984141615614d1c57614d1c614915565b500590565b600063ffffffff83811690831681811015614a3757614a37614915565b600080821280156001600160ff1b0384900385131615614d6057614d60614915565b600160ff1b8390038412811615614d7957614d79614915565b5050019056fea2646970667358221220ee478acafbb18cfc986294a7b7b8431a058e742dfd924976abd552d038da8a6264736f6c634300080a0033
Deployed Bytecode Sourcemap
101566:40391:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102583:22;;;;;;;;;160:25:1;;;148:2;133:18;102583:22:0;;;;;;;;102612:27;;;;;;129267:553;;;;;;:::i;:::-;;:::i;103209:27::-;;;;;;102290:29;;;;;;;;-1:-1:-1;;;;;1880:32:1;;;1862:51;;1850:2;1835:18;102290:29:0;1716:203:1;111271:5528:0;;;;;;:::i;:::-;;:::i;:::-;;102996:59;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;102996:59:0;;;;-1:-1:-1;;;102996:59:0;;;;;;-1:-1:-1;;;102996:59:0;;;;;;;-1:-1:-1;;;102996:59:0;;;;;;-1:-1:-1;;;102996:59:0;;;;;;;;-1:-1:-1;;;102996:59:0;;;;-1:-1:-1;;;;;102996:59:0;;;;;;;;;;;;;-1:-1:-1;;;;;2810:15:1;;;2792:34;;2862:15;;;;2857:2;2842:18;;2835:43;2925:1;2914:21;;;2894:18;;;2887:49;;;;2972:21;;;;2967:2;2952:18;;2945:49;3038:14;3031:22;3025:3;3010:19;;3003:51;3098:14;;3091:22;3085:3;3070:19;;3063:51;-1:-1:-1;;;;;3151:32:1;3145:3;3130:19;;3123:61;3233:6;3221:19;3215:3;3200:19;;3193:48;2734:3;2719:19;102996:59:0;2430:817:1;141129:825:0;;;;;;:::i;:::-;;:::i;121861:870::-;;;;;;:::i;:::-;;:::i;:::-;;;3829:14:1;;3822:22;3804:41;;3792:2;3777:18;121861:870:0;3664:187:1;106955:4253:0;;;;;;:::i;:::-;;:::i;105479:1432::-;;;;;;:::i;:::-;;:::i;102883:46::-;;;;;;;;;;-1:-1:-1;;;102883:46:0;;;;;;-1:-1:-1;;;102883:46:0;;;;;;;;;;5299:10:1;5336:15;;;5318:34;;5388:15;;;;5383:2;5368:18;;5361:43;5451:2;5440:22;5420:18;;;5413:50;5277:2;5262:18;102883:46:0;5093:376:1;102555:21:0;;;;;;135412:336;;;;;;:::i;:::-;;:::i;127514:206::-;;;;;;:::i;:::-;;:::i;128630:569::-;;;;;;:::i;:::-;;:::i;128420:142::-;;;;;;:::i;:::-;;:::i;127865:391::-;;;;;;:::i;:::-;;:::i;102439:25::-;;;;;;:::i;:::-;;:::i;122942:2137::-;;;;;;:::i;:::-;;:::i;:::-;;;;6246:25:1;;;6302:2;6287:18;;6280:34;;;;6219:18;122942:2137:0;6072:248:1;121160:454:0;;;:::i;:::-;;;;;;6461:4:1;6503:3;6492:9;6488:19;6480:27;;6540:6;6534:13;6523:9;6516:32;6604:4;6596:6;6592:17;6586:24;6579:4;6568:9;6564:20;6557:54;6667:4;6659:6;6655:17;6649:24;6642:4;6631:9;6627:20;6620:54;6730:4;6722:6;6718:17;6712:24;6705:4;6694:9;6690:20;6683:54;6793:4;6785:6;6781:17;6775:24;6768:4;6757:9;6753:20;6746:54;6856:4;6848:6;6844:17;6838:24;6831:4;6820:9;6816:20;6809:54;6919:4;6911:6;6907:17;6901:24;6894:4;6883:9;6879:20;6872:54;6996:4;6988:6;6984:17;6978:24;6971:32;6964:40;6957:4;6946:9;6942:20;6935:70;6325:686;;;;;102234:36:0;;;;;102699:49;;;;;;;;;;-1:-1:-1;;;102699:49:0;;;;;;-1:-1:-1;;;102699:49:0;;;;;;116856:4149;;;;;;:::i;:::-;;:::i;125209:571::-;;;;;;:::i;:::-;;:::i;103316:22::-;;;;;;;;;102341:32;;;;;103140:34;;;;;;126121:673;;;;;;:::i;:::-;;:::i;102791:49::-;;;;;;;;;;-1:-1:-1;;;102791:49:0;;;;;;-1:-1:-1;;;102791:49:0;;;;;;126922:472;;;;;;:::i;:::-;;:::i;102646:28::-;;;;;;140848:89;;;:::i;129267:553::-;129342:12;129374:62;129383:4;:25;;;129410:4;:25;;;129374:8;:62::i;:::-;129367:69;-1:-1:-1;129522:13:0;129538:33;129522:13;129549:21;129538:10;:33::i;:::-;129522:49;-1:-1:-1;129582:13:0;129598:33;129582:13;129609:21;129598:10;:33::i;:::-;129582:49;-1:-1:-1;129642:11:0;129664:19;129582:49;129676:6;129664:11;:19::i;:::-;129656:27;;:5;:27;:::i;:::-;129642:41;;102201:5;129702:3;:26;129694:57;;;;-1:-1:-1;;;129694:57:0;;;;;;;:::i;:::-;;;;;;;;;129771:23;129782:11;:3;:9;:11::i;:::-;129771:4;;:10;:23::i;:::-;129764:30;129267:553;-1:-1:-1;;;;;;129267:553:0:o;111271:5528::-;103617:10;;;;103616:11;103608:39;;;;-1:-1:-1;;;103608:39:0;;;;;;;:::i;:::-;101986:4:::1;111419:8;:15;;111411:46;;;::::0;-1:-1:-1;;;111411:46:0;;9848:2:1;111411:46:0::1;::::0;::::1;9830:21:1::0;9887:2;9867:18;;;9860:30;-1:-1:-1;;;9906:18:1;;;9899:48;9964:18;;111411:46:0::1;9646:342:1::0;111411:46:0::1;111601:41;:24;:8;:22;:24::i;:::-;:39;;;:41::i;:::-;111590:52;;111672:1;111661:8;:12;111653:43;;;::::0;-1:-1:-1;;;111653:43:0;;10195:2:1;111653:43:0::1;::::0;::::1;10177:21:1::0;10234:2;10214:18;;;10207:30;-1:-1:-1;;;10253:18:1;;;10246:48;10311:18;;111653:43:0::1;9993:342:1::0;111653:43:0::1;111709:13;111733:12:::0;111756:13:::1;111780:18:::0;111908:23:::1;111934:8;:6;:8::i;:::-;111908:34:::0;-1:-1:-1;111997:24:0::1;112024:37;:9;112038:10;112050::::0;112024:13:::1;:37::i;:::-;111997:64;;112084:12;:3;:10;:12::i;:::-;112076:40;;;;-1:-1:-1::0;;;112076:40:0::1;;;;;;;:::i;:::-;112171:21;112195:3;:10;;;:29;;112217:7;;112195:29;;;112208:6;;112195:29;112171:53;;112239:27;112269:3;:10;;;:41;;112297:13;;112269:41;;;112282:12;;112269:41;112239:71;;112425:393;112464:13;112500:19;112542:18;112555:4;112542:12;:18::i;:::-;112617:37;:6;112628:25;112617:10;:37::i;:::-;112677:53;:6;112688:41;112677:10;:53::i;:::-;112753:46;:6;112764:34;112753:10;:46::i;:::-;112425:3:::0;;:393;;;;;:16:::1;:393::i;:::-;112424:394;112398:474;;;::::0;-1:-1:-1;;;112398:474:0;;10886:2:1;112398:474:0::1;::::0;::::1;10868:21:1::0;10925:2;10905:18;;;10898:30;-1:-1:-1;;;10944:18:1;;;10937:48;11002:18;;112398:474:0::1;10684:342:1::0;112398:474:0::1;113201:13;113217:160;113250:75;113279:4:::0;113285:39:::1;113201:13:::0;113296:27:::1;113285:10;:39::i;113250:75::-;113344:18;113357:4;113344:12;:18::i;113217:160::-;113201:176;;113400:3;:10;;;:574;;113712:262;113738:4;113765:190;113810:4;113841:59;113855:8;113865:13;113880:19;113841:3;:13;;:59;;;;;;:::i;:::-;113927:5;113765:18;:190::i;113712:262::-;113400:574;;;113430:262;113456:4;113483:190;113528:4;113559:59;113573:8;113583:13;113598:19;113559:3;:13;;:59;;;;;;:::i;:::-;113645:5;113483:18;:190::i;113430:262::-;113392:582;;114083:3;:10;;;:54;;114127:10;114118:5;:19;;114083:54;;;114105:10;114096:5;:19;;114083:54;114075:85;;;;-1:-1:-1::0;;;114075:85:0::1;;;;;;;:::i;:::-;114300:17;114320:37;114300:17:::0;114331:25:::1;114320:10;:37::i;:::-;114300:57:::0;-1:-1:-1;114380:73:0::1;:3:::0;114390:8;114400:13;114415:19;114436:5;114300:57;114380:9:::1;:73::i;:::-;114372:81:::0;-1:-1:-1;114475:18:0::1;:3:::0;114484:8;114475::::1;:18::i;:::-;114468:25:::0;-1:-1:-1;114569:22:0::1;114594:42;114569:22:::0;114605:30:::1;114594:10;:42::i;:::-;114569:67:::0;-1:-1:-1;114664:211:0::1;:3:::0;114697:8;114724:13;114756:19;114794:5;114818:9;114569:67;114664:14:::1;:211::i;:::-;114651:224;;114903:27;114912:10;114924:5;114903:8;:27::i;:::-;114890:40;;115190:3;:10;;;115186:473;;;115230:116;115268:59;:3:::0;115282:8;115292:13;115307:19;115268:13:::1;:59::i;:::-;115230:6;::::0;;:15:::1;:116::i;:::-;115221:6;:125:::0;115381:29:::1;:3:::0;115401:8;115381:19:::1;:29::i;:::-;115365:12;;:45;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;115186:473:0::1;::::0;-1:-1:-1;115186:473:0::1;;115461:117;115500:59;:3:::0;115514:8;115524:13;115539:19;115500:13:::1;:59::i;:::-;115461:7;::::0;;:16:::1;:117::i;:::-;115451:7;:127:::0;115614:29:::1;:3:::0;115634:8;115614:19:::1;:29::i;:::-;115597:13;;:46;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;115186:473:0::1;115800:49;115820:28;115843:4:::0;115827:5;115820:28:::1;:::i;:::-;115800:19;:49::i;:::-;-1:-1:-1::0;116027:29:0::1;:3:::0;116047:8;116027:19:::1;:29::i;:::-;116003:3;:12;;:54;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;116003:54:0::1;::::0;;-1:-1:-1;116096:38:0::1;:3:::0;116125:8;116096:28:::1;:38::i;:::-;116072:3;:21;;:62;;;;;;;;;::::0;::::1;116149:42;116163:10;116175;116187:3;116149:9;:13;;:42;;;;;;:::i;:::-;111843:4360;;;;;;;116257:10;-1:-1:-1::0;;;;;116250:77:0::1;;116269:10;116281:8;116314:4;116298:5;116291:28;;;;:::i;:::-;116250:77;::::0;;11898:25:1;;;11954:2;11939:18;;11932:34;;;;11982:18;;;11975:34;12040:2;12025:18;;12018:34;;;11885:3;11870:19;116250:77:0::1;;;;;;;116403:4;116394:5;:13;116390:138;;-1:-1:-1::0;;;;;116424:3:0::1;:8;;116441:4;116448:12;116456:4:::0;116448:5;:12:::1;:::i;:::-;116424:37;::::0;-1:-1:-1;;;;;;116424:37:0::1;::::0;;;;;;-1:-1:-1;;;;;12255:32:1;;;116424:37:0::1;::::0;::::1;12237:51:1::0;12304:18;;;12297:34;12210:18;;116424:37:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;116390:138;;;-1:-1:-1::0;;;;;116494:3:0::1;:8;;116503:12;116510:5:::0;116503:4;:12:::1;:::i;:::-;116494:22;;;;;;;;;;;;;160:25:1::0;;148:2;133:18;;14:177;116494:22:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;116390:138;-1:-1:-1::0;;;;;116612:3:0::1;:12;;116625:10;116637:18;116645:10:::0;116637:5;:18:::1;:::i;:::-;116612:44;::::0;-1:-1:-1;;;;;;116612:44:0::1;::::0;;;;;;-1:-1:-1;;;;;12255:32:1;;;116612:44:0::1;::::0;::::1;12237:51:1::0;12304:18;;;12297:34;12210:18;;116612:44:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;116724:3;-1:-1:-1::0;;;;;116724:12:0::1;;116755:7;-1:-1:-1::0;;;;;116737:39:0::1;;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;116724:67;::::0;-1:-1:-1;;;;;;116724:67:0::1;::::0;;;;;;-1:-1:-1;;;;;12255:32:1;;;116724:67:0::1;::::0;::::1;12237:51:1::0;12304:18;;;12297:34;;;12210:18;;116724:67:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;111400:5399;;;;111271:5528:::0;;;:::o;141129:825::-;103759:10;;;;103751:39;;;;-1:-1:-1;;;103751:39:0;;13050:2:1;103751:39:0;;;13032:21:1;13089:2;13069:18;;;13062:30;-1:-1:-1;;;13108:18:1;;;13101:46;13164:18;;103751:39:0;12848:340:1;103751:39:0;141242:24:::1;141269:37;:9;141283:10;141295::::0;141269:13:::1;:37::i;:::-;141242:64;;141325:12;:3;:10;:12::i;:::-;141317:40;;;;-1:-1:-1::0;;;141317:40:0::1;;;;;;;:::i;:::-;101986:4;141430:16;141478:18;:3:::0;101986:4;141478:8:::1;:18::i;:::-;141523:28;::::0;-1:-1:-1;;;141523:28:0;;141545:4:::1;141523:28;::::0;::::1;1862:51:1::0;141463:33:0;;-1:-1:-1;141514:44:0::1;::::0;-1:-1:-1;;;;;141523:3:0::1;:13;::::0;::::1;::::0;1835:18:1;;141523:28:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;141553:4;141514:8;:44::i;:::-;141688:1;141664:21;::::0;::::1;:25:::0;141507:51;-1:-1:-1;141700:42:0::1;:9;141714:10;141726::::0;141664:3;141700:13:::1;:42::i;:::-;141792:47;::::0;;6246:25:1;;;6302:2;6287:18;;6280:34;;;141810:10:0::1;::::0;141792:47:::1;::::0;6219:18:1;141792:47:0::1;;;;;;;141916:30;::::0;-1:-1:-1;;;141916:30:0;;141929:10:::1;141916:30;::::0;::::1;12237:51:1::0;12304:18;;;12297:34;;;141916:3:0::1;-1:-1:-1::0;;;;;141916:12:0::1;::::0;::::1;::::0;12210:18:1;;141916:30:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;141197:757;;;141129:825:::0;:::o;121861:870::-;122043:12;;121928:4;;;122090:26;101986:4;122043:12;122090:11;:26::i;:::-;122268:25;;;;122324:27;;;;122066:50;;-1:-1:-1;122268:25:0;122366:14;;;:31;;-1:-1:-1;122384:13:0;;122366:31;122362:127;;;-1:-1:-1;122472:5:0;;121861:870;-1:-1:-1;;;;;121861:870:0:o;122362:127::-;122623:10;122636:25;:8;122651:9;122636:14;:25::i;:::-;122623:38;;122686:13;122680:2;:19;;:42;;;;;122709:13;122703:2;:19;;122680:42;122672:51;121861:870;-1:-1:-1;;;;;;;121861:870:0:o;106955:4253::-;103617:10;;107114:19;;103617:10;;103616:11;103608:39;;;;-1:-1:-1;;;103608:39:0;;;;;;;:::i;:::-;101986:4:::1;107154:8;:15;;107146:41;;;::::0;-1:-1:-1;;;107146:41:0;;13584:2:1;107146:41:0::1;::::0;::::1;13566:21:1::0;13623:2;13603:18;;;13596:30;-1:-1:-1;;;13642:18:1;;;13635:43;13695:18;;107146:41:0::1;13382:337:1::0;107146:41:0::1;107218:39;:6;107229:27;107218:10;:39::i;:::-;107206:8;:51;;107198:77;;;::::0;-1:-1:-1;;;107198:77:0;;13926:2:1;107198:77:0::1;::::0;::::1;13908:21:1::0;13965:2;13945:18;;;13938:30;-1:-1:-1;;;13984:18:1;;;13977:43;14037:18;;107198:77:0::1;13724:337:1::0;107198:77:0::1;107308:41;:6;107319:29;107308:10;:41::i;:::-;107294:10;:55;;107286:88;;;::::0;-1:-1:-1;;;107286:88:0;;14268:2:1;107286:88:0::1;::::0;::::1;14250:21:1::0;14307:2;14287:18;;;14280:30;-1:-1:-1;;;14326:18:1;;;14319:50;14386:18;;107286:88:0::1;14066:344:1::0;107286:88:0::1;107387:10;107408:12:::0;107431:13:::1;107455:18:::0;107583:23:::1;107609:8;:6;:8::i;:::-;107583:34:::0;-1:-1:-1;107772:16:0::1;107791:26;:10:::0;107808:8;107791:16:::1;:26::i;:::-;107772:45;;107832:16;107851:18;107864:4;107851:12;:18::i;:::-;107832:37;;107889:34;107904:8;107914;107889:14;:34::i;:::-;107884:39;;108021:1;108016:2;:6;108008:30;;;::::0;-1:-1:-1;;;108008:30:0;;14617:2:1;108008:30:0::1;::::0;::::1;14599:21:1::0;14656:2;14636:18;;;14629:30;-1:-1:-1;;;14675:18:1;;;14668:41;14726:18;;108008:30:0::1;14415:335:1::0;108008:30:0::1;108191:21;108202:10:::0;108191:8;:21:::1;:::i;:::-;108184:28:::0;-1:-1:-1;108240:58:0::1;108255:42;:6;108266:30;108255:10;:42::i;:::-;108240:8:::0;;:14:::1;:58::i;:::-;108227:71:::0;-1:-1:-1;108460:13:0::1;108476:150;108509:75;108538:4:::0;108544:39:::1;108460:13:::0;108555:27:::1;108544:10;:39::i;108509:75::-;108603:8;108476:14;:150::i;:::-;108460:166;;108831:6;:138;;108923:46;108927:4;108933:35;108952:4;108958:2;108962:5;108933:18;:35::i;108923:46::-;108831:138;;;108857:46;108861:4;108867:35;108886:4;108892:2;108896:5;108867:18;:35::i;108857:46::-;108823:146;;109078:6;:50;;109118:10;109109:5;:19;;109078:50;;;109096:10;109087:5;:19;;109078:50;109070:81;;;;-1:-1:-1::0;;;109070:81:0::1;;;;;;;:::i;:::-;109306:16;109325:37;109344:2;109348:5;109355:6;109325:18;:37::i;:::-;109306:56;;109503:24;109530:495;;;;;;;;109587:8;-1:-1:-1::0;;;;;109530:495:0::1;;;;;109680:4;-1:-1:-1::0;;;;;109530:495:0::1;;;;;109713:26;109730:8;109713:16;:26::i;:::-;109530:495;;;;;;109769:23;109786:5;109769:16;:23::i;:::-;109530:495;;::::0;;;::::1;;;::::0;::::1;::::0;-1:-1:-1;109530:495:0;;;;-1:-1:-1;;;;;109530:495:0;::::1;::::0;;;;;;109990:19:::1;101986:4;109990:17;:19::i;:::-;109530:495;;::::0;;109503:522;-1:-1:-1;110067:413:0::1;110106:6:::0;:25:::1;;110124:7;;110106:25;;;110115:6;;110106:25;110154:6;:37;;110178:13;;110154:37;;;110163:12;;110154:37;110214:8:::0;110279:37:::1;:6;110290:25;110279:10;:37::i;:::-;110339:53;:6;110350:41;110339:10;:53::i;:::-;110415:46;:6;110426:34;110415:10;:46::i;:::-;110067:3:::0;;:413;;;;;:16:::1;:413::i;:::-;110066:414;110040:494;;;::::0;-1:-1:-1;;;110040:494:0;;10886:2:1;110040:494:0::1;::::0;::::1;10868:21:1::0;10925:2;10905:18;;;10898:30;-1:-1:-1;;;10944:18:1;;;10937:48;11002:18;;110040:494:0::1;10684:342:1::0;110040:494:0::1;110610:15;::::0;;-1:-1:-1;110640:43:0::1;:9;110654:10;110610:15:::0;110679:3;110640:13:::1;:43::i;:::-;110698:15;:17:::0;;;:15:::1;:17;::::0;::::1;:::i;:::-;::::0;;;-1:-1:-1;;110773:55:0::1;::::0;;15148:25:1;;;15204:2;15189:18;;15182:34;;;15232:18;;;15225:34;;;15302:14;;15295:22;15290:2;15275:18;;15268:50;15349:3;15334:19;;15327:35;;;110779:10:0::1;::::0;-1:-1:-1;110773:55:0::1;::::0;-1:-1:-1;15135:3:1;15120:19;;-1:-1:-1;110773:55:0::1;::::0;-1:-1:-1;;;14895:473:1;110773:55:0::1;;;;;;;;-1:-1:-1::0;;;;;110997:3:0::1;:16;;111014:10;111034:4;111041:23;111054:10:::0;111041;:23:::1;:::i;:::-;110997:68;::::0;-1:-1:-1;;;;;;110997:68:0::1;::::0;;;;;;-1:-1:-1;;;;;15631:15:1;;;110997:68:0::1;::::0;::::1;15613:34:1::0;15683:15;;;;15663:18;;;15656:43;15715:18;;;15708:34;15548:18;;110997:68:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;111133:3;-1:-1:-1::0;;;;;111133:12:0::1;;111164:7;-1:-1:-1::0;;;;;111146:39:0::1;;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;111133:67;::::0;-1:-1:-1;;;;;;111133:67:0::1;::::0;;;;;;-1:-1:-1;;;;;12255:32:1;;;111133:67:0::1;::::0;::::1;12237:51:1::0;12304:18;;;12297:34;;;12210:18;;111133:67:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;107135:4073;;;;106955:4253:::0;;;;;;:::o;105479:1432::-;103449:10;-1:-1:-1;;;;;103463:7:0;103449:21;;103441:49;;;;-1:-1:-1;;;103441:49:0;;;;;;;:::i;:::-;105594:23:::1;105635:4;-1:-1:-1::0;;;;;105620:27:0::1;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;105594:55;;105689:1;105668:18;105681:4;105668:12;:18::i;:::-;:22;105660:46;;;::::0;-1:-1:-1;;;105660:46:0;;17250:2:1;105660:46:0::1;::::0;::::1;17232:21:1::0;17289:2;17269:18;;;17262:30;-1:-1:-1;;;17308:18:1;;;17301:41;17359:18;;105660:46:0::1;17048:335:1::0;105660:46:0::1;105739:15;105717:19;:37:::0;105826:45;;::::1;::::0;105899:39;;::::1;::::0;105986:83;;::::1;::::0;106110:52;;::::1;::::0;106228:127:::1;106275:61;106310:25;106110:52:::0;101986:4:::1;106310:25;:::i;:::-;106275:26:::0;;:34:::1;:61::i;:::-;106262:10;106266:6:::0;106262:1:::1;:10;:::i;:::-;:74;;;;:::i;:::-;101986:4;::::0;106228:11:::1;:127::i;:::-;106195:12;:160;;106173:249;;;;-1:-1:-1::0;;;106173:249:0::1;;;;;;;:::i;:::-;106467:54:::0;;::::1;::::0;106578:16:::1;::::0;::::1;::::0;102201:5:::1;::::0;106554:40:::1;::::0;106467:54;106554:40:::1;:::i;:::-;:63;106532:147;;;;-1:-1:-1::0;;;106532:147:0::1;;;;;;;:::i;:::-;106690:75;106705:36;106743:21;106690:14;:75::i;:::-;106815:9;106810:94;106834:14;106830:1;:18;106810:94;;;106882:7;106890:1;106882:10;;;;;;;:::i;:::-;;;;;106870:6;106877:1;106870:9;;;;;;;:::i;:::-;;:22:::0;106850:3;::::1;::::0;::::1;:::i;:::-;;;;106810:94;;135412:336:::0;103449:10;-1:-1:-1;;;;;103463:7:0;103449:21;;103441:49;;;;-1:-1:-1;;;103441:49:0;;;;;;;:::i;:::-;135576:13:::1;:11;:13::i;:::-;135640:28;135656:4;135662:5;135640:15;:28::i;:::-;135679:27;135694:4;135700:5;135679:14;:27::i;:::-;135717:23;:6;135728:4:::0;135734:5;135717:10:::1;:23::i;:::-;135412:336:::0;;:::o;127514:206::-;127583:7;;127619:33;127583:7;127630:21;127619:10;:33::i;:::-;127603:49;;127670:42;127684:4;:27;;;127670:5;:13;;:42;;;;:::i;:::-;127663:49;127514:206;-1:-1:-1;;;127514:206:0:o;128630:569::-;128705:12;128737:62;128746:4;:25;;;128773:4;:25;;;128737:8;:62::i;:::-;128730:69;-1:-1:-1;128885:13:0;128901:33;128885:13;128912:21;128901:10;:33::i;:::-;128885:49;-1:-1:-1;128945:13:0;128961:33;128945:13;128972:21;128961:10;:33::i;:::-;128945:49;-1:-1:-1;129005:11:0;129027:19;128945:49;129039:6;129027:11;:19::i;:::-;129019:27;;:5;:27;:::i;:::-;129005:41;;102201:5;129065:3;:26;129057:57;;;;-1:-1:-1;;;129057:57:0;;;;;;;:::i;:::-;129134:38;129147:24;129159:11;:3;:9;:11::i;129147:24::-;129134:4;;:12;:38::i;128420:142::-;128501:7;128528:26;:8;128545;128528:16;:26::i;:::-;128521:33;;128420:142;;;;;:::o;127865:391::-;127933:7;;127980:44;127933:7;127991:32;127980:10;:44::i;:::-;127953:71;;128035:14;128079:16;101986:4;128053;:16;;;:22;;;;:::i;:::-;128052:43;;;;:::i;:::-;128035:60;-1:-1:-1;128106:13:0;128122:33;128106:13;128133:21;128122:10;:33::i;:::-;128106:49;-1:-1:-1;128173:75:0;128240:7;101986:4;128240:1;:7;:::i;:::-;128173:58;128224:6;128173:42;128187:4;:27;;;128173:5;:13;;:42;;;;:::i;:::-;:50;;:58::i;:75::-;128166:82;127865:391;-1:-1:-1;;;;;127865:391:0:o;102439:25::-;;;;;;;;;;;;;;;-1:-1:-1;102439:25:0;:::o;122942:2137::-;123087:7;;;123134:28;123149:13;123134:12;:28;:::i;:::-;123116:46;-1:-1:-1;123173:19:0;123195:28;123210:13;123195:12;:28;:::i;:::-;123173:50;-1:-1:-1;123234:19:0;123256:33;:13;123276:12;123256:19;:33::i;:::-;123234:55;-1:-1:-1;123391:12:0;;;:32;;-1:-1:-1;123407:16:0;;123391:32;123387:101;;;123448:12;123462:13;123440:36;;;;;;;;;123387:101;123633:21;;123715:11;123683:29;123633:21;;123683:10;:29::i;:::-;123679:33;;:1;:33;:::i;:::-;:47;;;;:::i;:::-;123665:61;;102201:5;123741:3;:26;123737:112;;;123800:24;123812:11;:3;:9;:11::i;123800:24::-;123784:40;;123737:112;124166:21;124190:28;:11;124210:7;124190:19;:28::i;:::-;124166:52;-1:-1:-1;124229:17:0;124268:120;124337:36;124359:13;;124337:21;:36::i;:::-;124331:42;;101986:4;124331:42;:::i;:::-;124268:36;124290:13;;124268:21;:36::i;:120::-;124249:139;;101986:4;124249:139;:::i;:::-;124229:159;-1:-1:-1;124477:43:0;124493:26;124511:7;124517:1;101986:4;124511:7;:::i;:::-;124493:9;;:17;:26::i;:::-;124477:7;;:15;:43::i;:::-;124467:53;-1:-1:-1;124676:34:0;:11;124696:13;124676:19;:34::i;:::-;124662:48;-1:-1:-1;124916:1:0;124891:21;124662:48;124891:7;:21;:::i;:::-;124890:27;;;;:::i;:::-;124875:42;-1:-1:-1;124932:17:0;;124928:97;;124982:31;:11;125000:12;124982:17;:31::i;:::-;124966:47;;124928:97;125043:12;125057:13;125035:36;;;;;;;;;;;122942:2137;;;;;;;:::o;121160:454::-;121194:18;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121194:18:0;121298:13;:11;:13::i;:::-;121430:23;121471:4;-1:-1:-1;;;;;121456:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;121430:55;;121504:17;121516:4;121504:11;:17::i;:::-;121496:41;;;;-1:-1:-1;;;121496:41:0;;17250:2:1;121496:41:0;;;17232:21:1;17289:2;17269:18;;;17262:30;-1:-1:-1;;;17308:18:1;;;17301:41;17359:18;;121496:41:0;17048:335:1;121496:41:0;121602:4;121160:454;-1:-1:-1;121160:454:0:o;116856:4149::-;103617:10;;;;103616:11;103608:39;;;;-1:-1:-1;;;103608:39:0;;;;;;;:::i;:::-;116942:13:::1;::::0;;;;;;117225:32:::1;:9;117239:5:::0;117246:10;117225:13:::1;:32::i;:::-;117198:59;;117280:12;:3;:10;:12::i;:::-;117272:40;;;;-1:-1:-1::0;;;117272:40:0::1;;;;;;;:::i;:::-;117379:23;117405:8;:6;:8::i;:::-;117379:34;;117468:21;117492:3;:10;;;:29;;117514:7;;117492:29;;;117505:6;;117492:29;117468:53;;117536:27;117566:3;:10;;;:41;;117594:13;;117566:41;;;117579:12;;117566:41;117536:71:::0;-1:-1:-1;117622:17:0::1;117642:37;117622:17:::0;117653:25:::1;117642:10;:37::i;:::-;117622:57:::0;-1:-1:-1;101986:4:0::1;117977:18;117990:4:::0;117977:12:::1;:18::i;:::-;117969:26:::0;-1:-1:-1;118085:318:0::1;118124:13:::0;118160:19;117969:26;118230:9;118262:53:::1;:6;118273:41;118262:10;:53::i;:::-;118338:46;:6;118349:34;118338:10;:46::i;:::-;118085:3:::0;;:318;;;;;:16:::1;:318::i;:::-;118059:399;;;::::0;-1:-1:-1;;;118059:399:0;;19095:2:1;118059:399:0::1;::::0;::::1;19077:21:1::0;19134:2;19114:18;;;19107:30;-1:-1:-1;;;19153:18:1;;;19146:49;19212:18;;118059:399:0::1;18893:343:1::0;118059:399:0::1;118606:73;:3:::0;118616:8;118626:13;118641:19;118662:5;118669:9;118606::::1;:73::i;:::-;118598:81:::0;-1:-1:-1;118701:18:0::1;:3:::0;118710:8;118701::::1;:18::i;:::-;118694:25:::0;-1:-1:-1;118868:61:0::1;118882:46;:6;118893:34;118882:10;:46::i;:::-;118868:5:::0;;:13:::1;:61::i;:::-;118851:78:::0;-1:-1:-1;118962:22:0::1;118851:78:::0;118962:5;:22:::1;:::i;:::-;118944:40:::0;-1:-1:-1;119147:110:0::1;119189:53;:6;119200:41;119189:10;:53::i;119147:110::-;119132:125:::0;-1:-1:-1;119272:31:0::1;119132:125:::0;119272:31;::::1;:::i;:::-;;;119541:3;:10;;;119537:473;;;119581:116;119619:59;:3:::0;119633:8;119643:13;119658:19;119619:13:::1;:59::i;119581:116::-;119572:6;:125:::0;119732:29:::1;:3:::0;119752:8;119732:19:::1;:29::i;:::-;119716:12;;:45;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;119537:473:0::1;::::0;-1:-1:-1;119537:473:0::1;;119812:117;119851:59;:3:::0;119865:8;119875:13;119890:19;119851:13:::1;:59::i;119812:117::-;119802:7;:127:::0;119965:29:::1;:3:::0;119985:8;119965:19:::1;:29::i;:::-;119948:13;;:46;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;119537:473:0::1;120075:72;120133:12:::0;120095:28:::1;120118:4:::0;120102:5;120095:28:::1;:::i;:::-;:51;;;;:::i;120075:72::-;-1:-1:-1::0;120254:4:0::1;120237:14;::::0;::::1;:21:::0;;120273:12:::1;::::0;::::1;:16:::0;;;120304:21:::1;::::0;::::1;:25:::0;120344:37:::1;:9;120358:5:::0;120365:10;120237:3;120344:13:::1;:37::i;:::-;117145:3248;;;;;;120492:5;-1:-1:-1::0;;;;;120443:176:0::1;120467:10;-1:-1:-1::0;;;;;120443:176:0::1;;120512:10;120575:12;120560:4;120544:5;120537:28;;;;:::i;:::-;:51;;;;:::i;:::-;120443:176;::::0;;19441:25:1;;;19497:2;19482:18;;19475:34;;;;19525:18;;19518:34;;;19429:2;19414:18;120443:176:0::1;;;;;;;-1:-1:-1::0;;;;;120693:3:0::1;:8;;120717:12:::0;120702::::1;120709:5:::0;120702:4;:12:::1;:::i;:::-;:27;;;;:::i;:::-;120693:37;;;;;;;;;;;;;160:25:1::0;;148:2;133:18;;14:177;120693:37:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;120813:40:0::1;::::0;-1:-1:-1;;;120813:40:0;;120826:10:::1;120813:40;::::0;::::1;12237:51:1::0;12304:18;;;12297:34;;;120813:3:0::1;-1:-1:-1::0;;;;;120813:12:0::1;::::0;-1:-1:-1;120813:12:0::1;::::0;-1:-1:-1;12210:18:1;;120813:40:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;120925:3;-1:-1:-1::0;;;;;120925:12:0::1;;120956:7;-1:-1:-1::0;;;;;120938:39:0::1;;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;120925:72;::::0;-1:-1:-1;;;;;;120925:72:0::1;::::0;;;;;;-1:-1:-1;;;;;12255:32:1;;;120925:72:0::1;::::0;::::1;12237:51:1::0;12304:18;;;12297:34;;;12210:18;;120925:72:0::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;116931:4074;;;;;;116856:4149:::0;;:::o;125209:571::-;125485:48;;;;;;;;125519:14;125485:48;;;;;;;-1:-1:-1;;;125485:48:0;;;;;;;;-1:-1:-1;;;125485:48:0;;;;;;;;;;;;125283:7;;;;125575:48;;125283:7;;125586:36;;125575:10;:48;:::i;:::-;125544:79;-1:-1:-1;125645:60:0;:8;125664:15;125544:79;125703:1;125645:18;:60::i;:::-;125634:71;;125722:29;125737:8;125747:3;125722:14;:29::i;:::-;125716:35;125209:571;-1:-1:-1;;;;125209:571:0:o;126121:673::-;126239:7;126264:13;126287:21;:8;57421:16;;;57414:24;;;57323:123;126287:21;126264:45;-1:-1:-1;126320:32:0;126355:52;126320:32;126366:40;126355:10;:52::i;:::-;126320:87;;126439:24;126422:6;:42;126418:178;;126488:3;126481:10;;;;;;126418:178;126523:36;126534:24;126523:1;:36;:::i;:::-;126513:6;:46;126509:87;;126583:1;126576:8;;;;;;126509:87;126665:18;126696:49;126704:6;126720:24;126696:23;:49::i;:::-;126686:7;101986:4;126686:1;:7;:::i;:::-;:59;;;;:::i;:::-;126665:80;-1:-1:-1;126763:23:0;:3;126665:80;126763:11;:23::i;126922:472::-;127046:7;127075:4;:15;;;127071:295;;;127189:34;127198:3;127203:19;127217:4;127203:13;:19::i;:::-;127189:8;:34::i;:::-;127183:40;;127321:33;127330:3;127335:18;127348:4;127335:12;:18::i;127321:33::-;127315:39;;127071:295;-1:-1:-1;127383:3:0;126922:472;-1:-1:-1;126922:472:0:o;140848:89::-;103617:10;;;;103616:11;103608:39;;;;-1:-1:-1;;;103608:39:0;;;;;;;:::i;:::-;103449:10:::1;-1:-1:-1::0;;;;;103463:7:0::1;103449:21;;103441:49;;;;-1:-1:-1::0;;;103441:49:0::1;;;;;;;:::i;:::-;140912:10:::2;:17:::0;;-1:-1:-1;;140912:17:0::2;140925:4;140912:17;::::0;;140848:89::o;77828:107::-;77886:7;77918:1;77913;:6;;:14;;77926:1;77913:14;;;-1:-1:-1;77922:1:0;;77828:107;-1:-1:-1;77828:107:0:o;70579:133::-;70658:7;70685:4;70698;70690:13;;;;;;;;:::i;:::-;70685:19;;;;;;;:::i;:::-;;;;70579:133;-1:-1:-1;;;70579:133:0:o;45221:560::-;45281:7;;45319:5;45323:1;45319;:5;:::i;:::-;45301:23;-1:-1:-1;45339:12:0;45335:439;;45375:1;45368:8;;;;;45335:439;44063:4;45739:11;45749:1;45739:7;:11;:::i;:::-;45738:19;;;;:::i;:::-;45737:25;;45761:1;45737:25;:::i;:::-;45730:32;;;;;49896:394;49945:7;49969:6;49965:49;;-1:-1:-1;44063:4:0;;49896:394;-1:-1:-1;49896:394:0:o;49965:49::-;-1:-1:-1;;;50032:1:0;:10;50024:50;;;;-1:-1:-1;;;50024:50:0;;20323:2:1;50024:50:0;;;20305:21:1;20362:2;20342:18;;;20335:30;20401:29;20381:18;;;20374:57;20448:18;;50024:50:0;20121:351:1;50024:50:0;50112:1;50087:15;50147:24;50112:1;50147:14;:24::i;:::-;50125:47;;50183:16;50202:42;50206:34;50212:3;44239:5;50206;:34::i;:::-;50242:1;50202:3;:42::i;:::-;50183:61;;50264:18;50268:3;50273:8;50264:3;:18::i;6534:277::-;6595:6;;6632:16;6182:3;6115:4;6632:16;:::i;:::-;6614:34;-1:-1:-1;6659:14:0;6676:15;6614:34;6676:5;:15;:::i;:::-;6659:32;-1:-1:-1;6720:16:0;6710:26;;;6702:69;;;;-1:-1:-1;;;6702:69:0;;20679:2:1;6702:69:0;;;20661:21:1;20718:2;20698:18;;;20691:30;20757:32;20737:18;;;20730:60;20807:18;;6702:69:0;20477:354:1;6284:173:0;6345:7;;6386:16;6182:3;6115:4;6386:16;:::i;:::-;6365:37;-1:-1:-1;6421:27:0;6365:37;6421:14;;;:27;:::i;87766:234::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87963:27:0;;21009:15:1;;;;-1:-1:-1;;21005:53:1;87963:27:0;;;20993:66:1;21075:12;;;;21068:28;;;;87963:27:0;;;;;;;;;;21112:12:1;;;87963:27:0;;;87953:38;;;;;;;;;87948:44;;;;;;;;;87936:56;;;;;;;;-1:-1:-1;;;;;87936:56:0;;;;;-1:-1:-1;;;87936:56:0;;;;;;;-1:-1:-1;;;87936:56:0;;;;;;;;;;-1:-1:-1;;;87936:56:0;;;;;;;;-1:-1:-1;;;87936:56:0;;;;;;;;;;;;;-1:-1:-1;;;87936:56:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;87936:56:0;;;;;;;;;;;;;;;;;21112:12:1;87766:234:0:o;89688:145::-;89745:12;89779:4;:15;;;89778:16;:46;;;;-1:-1:-1;;89798:22:0;;;:26;;;;;89688:145::o;129989:175::-;130058:12;130090:66;130103:4;:25;;;130130:4;:25;;;130090:12;:66::i;100375:1059::-;100664:9;86748:4;100664:9;100748:31;100764:4;86748;100748:15;:31::i;:::-;100719:60;;100796:4;:15;;;:46;;;-1:-1:-1;100815:22:0;;;;:27;;;100796:46;100792:222;;;100997:5;100990:12;;;;;;100792:222;101026:11;101040:171;101060:4;101079:8;101102:13;101130:19;101164:12;101191:9;101040:5;:171::i;:::-;101026:185;-1:-1:-1;101222:25:0;101250:51;:18;101275:25;101250:24;:51::i;:::-;101222:79;-1:-1:-1;101312:22:0;101337:31;:3;101349:18;101337:11;:31::i;:::-;101312:56;-1:-1:-1;101392:34:0;101312:56;101392:17;:34;:::i;:::-;101386:40;;;;100375:1059;-1:-1:-1;;;;;;;;;;;;100375:1059:0:o;95534:418::-;95707:7;95727:16;95746:31;95762:4;95768:8;95746:15;:31::i;:::-;95727:50;-1:-1:-1;95792:13:0;;;:35;;-1:-1:-1;95809:18:0;;95792:35;:63;;;-1:-1:-1;95831:24:0;;95792:63;95788:77;;;95864:1;95857:8;;;;;95788:77;95883:61;95899:8;95909:13;95924:19;95883:15;:61::i;131166:694::-;131364:51;;;;;;;;131398:17;131364:51;;;;;;;-1:-1:-1;;;131364:51:0;;;;;;;;-1:-1:-1;;;131364:51:0;;;;;;;;;;;;131299:7;;;;131448:17;;:6;;131461:3;;131448:12;:17;:::i;:::-;131653:16;;;;131426:40;;-1:-1:-1;131617:60:0;;:8;;131636:15;;131426:40;131617:18;:60::i;:::-;131733:28;;:17;:28;;;;;;;;;;;;;;-1:-1:-1;;131733:28:0;;;;;;;-1:-1:-1;;;131733:28:0;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;131733:28:0;;;;;;;;-1:-1:-1;57414:24:0;;131815:37;131166:694;-1:-1:-1;;;;;;131166:694:0:o;130318:::-;130516:51;;;;;;;;130550:17;130516:51;;;;;;;-1:-1:-1;;;130516:51:0;;;;;;;;-1:-1:-1;;;130516:51:0;;;;;;;;;;;;130451:7;;;;130600:17;;:6;;130613:3;;130600:12;:17;:::i;:::-;130805:16;;;;130578:40;;-1:-1:-1;130769:60:0;;:8;;130788:15;;130578:40;130769:18;:60::i;:::-;130885:28;;:17;:28;;;;;;;;;;;;;;-1:-1:-1;;130885:28:0;;;;;;;-1:-1:-1;;;130885:28:0;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;130885:28:0;;;;;;;;-1:-1:-1;57414:24:0;;130982:21;57323:123;96776:2009;97004:12;97029:20;97052:25;97062:4;97068:8;97052:9;:25::i;:::-;97029:48;;97088:26;97117:31;97133:4;97139:8;97117:15;:31::i;:::-;97088:60;;97159:15;97177:27;97189:4;97195:8;97177:11;:27::i;:::-;97159:45;;97217:20;97240:61;97250:4;97256:8;97266:13;97281:19;97240:9;:61::i;:::-;97217:84;;97312:21;97336:16;97347:4;97336:10;:16::i;:::-;97312:40;;97683:4;:11;;;97679:1099;;;98013:161;98044:32;:12;98063;98044:18;:32::i;:::-;98099:56;98139:15;98145:9;86748:4;98139:15;:::i;:::-;98099:33;:12;98118:13;98099:18;:33::i;:::-;:39;;:56::i;98013:161::-;97935:58;97980:12;97935:38;:18;97960:12;97935:24;:38::i;:::-;:44;;:58::i;:::-;:239;;;;:::i;:::-;97911:263;-1:-1:-1;98223:58:0;98247:33;:12;98266:13;98247:18;:33::i;:::-;98237:43;;:7;:43;:::i;:::-;98223:4;;:13;:58::i;:::-;98216:65;;97679:1099;;;98627:33;:12;98646:13;98627:18;:33::i;:::-;98549:58;98594:12;98549:38;:18;98574:12;98549:24;:38::i;:58::-;:111;;;;:::i;:::-;98525:135;-1:-1:-1;98709:57:0;98733:32;:12;98752;98733:18;:32::i;98709:57::-;98702:64;;97679:1099;97018:1767;;;;;96776:2009;;;;;;;;:::o;96032:408::-;96105:7;96125:26;96154:31;96170:4;96176:8;96154:15;:31::i;:::-;96125:60;;96196:15;96214:27;96226:4;96232:8;96214:11;:27::i;:::-;96196:45;-1:-1:-1;96343:18:0;96382:25;96343:18;96196:45;96382:16;:25::i;99617:567::-;99883:19;99915;99937:181;99967:4;99986:8;100009:13;100037:19;100071:12;100098:9;99937:15;:181::i;:::-;99915:203;-1:-1:-1;100143:33:0;99915:203;100161:14;100143:17;:33::i;:::-;100129:47;99617:567;-1:-1:-1;;;;;;;;;99617:567:0:o;78011:106::-;78069:7;78100:1;78096;:5;:13;;78108:1;78096:13;;44922:139;44985:7;45005:9;45021:1;45017;:5;:17;;45033:1;45017:17;;;45025:5;45029:1;45025;:5;:::i;94457:281::-;94541:7;94561:28;94592:15;94602:4;89106:13;;;-1:-1:-1;;;;;89098:22:0;;89012:116;94592:15;94561:46;-1:-1:-1;94692:38:0;94561:46;94721:8;94692:28;:38::i;132011:693::-;132135:48;;;;;;;;132169:14;132135:48;;;;;;;-1:-1:-1;;;132135:48:0;;;;;;;;-1:-1:-1;;;132135:48:0;;;;;;;;;;;;132071:6;;;;132361:48;;132071:6;;132372:36;;132361:10;:48;:::i;:::-;132330:79;-1:-1:-1;132431:64:0;:8;132450:15;132330:79;132489:5;132431:18;:64::i;:::-;132551:25;;:14;:25;;;;;;;;;;;;;;-1:-1:-1;;132551:25:0;;;;;;;-1:-1:-1;;;132551:25:0;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;132551:25:0;;;;;;;;-1:-1:-1;;;57414:24:0;;132651:21;57323:123;90417:357;90544:6;86748:4;90576:15;:22;;90568:53;;;;-1:-1:-1;;;90568:53:0;;9848:2:1;90568:53:0;;;9830:21:1;9887:2;9867:18;;;9860:30;-1:-1:-1;;;9906:18:1;;;9899:48;9964:18;;90568:53:0;9646:342:1;90568:53:0;90632:25;90660:55;90693:21;90699:15;86748:4;90693:21;:::i;:::-;90660:24;90679:4;90660:18;:24::i;:55::-;90632:83;;90733:33;:17;:31;:33::i;88064:227::-;88243:27;;-1:-1:-1;;21013:2:1;21009:15;;;21005:53;88243:27:0;;;20993:66:1;21075:12;;;21068:28;;;88275:8:0;;88228:4;;:44;;21112:12:1;;88243:27:0;;;;;;-1:-1:-1;;88243:27:0;;;;;;88233:38;;88243:27;88233:38;;;;88228:44;;;;;;;;;;;;-1:-1:-1;88228:44:0;:55;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;88228:55:0;;;-1:-1:-1;;;;;;88228:55:0;;;;;;;-1:-1:-1;;;88228:55:0;;;;;;;;;;;;-1:-1:-1;;;;88228:55:0;-1:-1:-1;;;88228:55:0;;;;;-1:-1:-1;;;;88228:55:0;;-1:-1:-1;;;88228:55:0;;;;;;;;;-1:-1:-1;;;;;88228:55:0;;;-1:-1:-1;;;88228:55:0;;;;;-1:-1:-1;;;;;88228:55:0;;-1:-1:-1;;;88228:55:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;88228:55:0;;;;-1:-1:-1;;;;88064:227:0:o;45789:231::-;45851:7;45875:6;45871:142;;-1:-1:-1;45905:1:0;45898:8;;45871:142;45939:17;45959:7;44063:4;45959:1;:7;:::i;:::-;45939:27;-1:-1:-1;45988:13:0;46000:1;45939:27;45988:13;:::i;46028:562::-;46088:7;46112:6;46108:475;;-1:-1:-1;46142:1:0;46135:8;;46108:475;46176:17;46196:7;44063:4;46196:1;:7;:::i;:::-;46176:27;-1:-1:-1;46565:1:0;46548:13;46560:1;46176:27;46548:13;:::i;134009:1195::-;134128:17;134192:21;134216:6;:25;;134234:7;;134216:25;;;134225:6;;134216:25;134192:49;;134252:27;134282:6;:37;;134306:13;;134282:37;;;134291:12;;134282:37;134252:67;;134364:16;134383:61;134405:2;134409:13;134424:19;134383:21;:61::i;:::-;134364:80;-1:-1:-1;134515:19:0;134532:2;134515:19;;:::i;:::-;;-1:-1:-1;134545:31:0;134568:8;134545:31;;:::i;:::-;;;134697:22;134722:37;134753:5;134722:30;:37::i;:::-;134697:62;;134795:14;134778:13;:31;;134770:56;;;;-1:-1:-1;;;134770:56:0;;21337:2:1;134770:56:0;;;21319:21:1;21376:2;21356:18;;;21349:30;-1:-1:-1;;;21395:18:1;;;21388:42;21447:18;;134770:56:0;21135:336:1;134770:56:0;134908:6;134904:216;;;134931:6;:22;;;134968:12;:34;;;134904:216;;;135035:7;:23;;;135073:13;:35;;;134904:216;-1:-1:-1;135188:8:0;134009:1195;-1:-1:-1;;;;;;134009:1195:0:o;55511:382::-;55570:5;;55605:25;:5;55051:9;55605:13;:25::i;:::-;55588:42;;-1:-1:-1;;55649:7:0;:23;;:50;;;;;55107:6;55676:7;:23;;55649:50;55641:88;;;;-1:-1:-1;;;55641:88:0;;21678:2:1;55641:88:0;;;21660:21:1;21717:2;21697:18;;;21690:30;-1:-1:-1;;;21736:18:1;;;21729:55;21801:18;;55641:88:0;21476:349:1;55641:88:0;55863:21;55001:4;55863:7;:21;:::i;140184:501::-;140384:36;140376:4;:44;;;;;;;;:::i;:::-;;140372:306;;;140437:23;140478:4;-1:-1:-1;;;;;140463:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;140597:16;;;;140437:55;;-1:-1:-1;140539:5:0;;140507:29;;140573:40;;140539:5;140573:40;:::i;:::-;140559:54;;140643:11;:3;:9;:11::i;:::-;140628:12;:26;-1:-1:-1;;;140184:501:0;;:::o;132845:917::-;132946:19;132986;;132968:15;:37;;;;:::i;:::-;132946:59;-1:-1:-1;133020:15:0;;133016:739;;133144:7;;133135:6;;:16;133111:21;133135:16;133189:35;;133217:7;;133189:35;;;133208:6;;133189:35;133166:58;;133239:21;133263:16;:35;;133292:6;;133263:35;;;133282:7;;133263:35;133239:59;;133345:122;133378:12;133409:13;133441:11;133345:14;:122::i;:::-;133313:154;;-1:-1:-1;133313:154:0;-1:-1:-1;133521:16:0;:47;;133555:13;133521:47;;;133540:12;133521:47;133512:6;:56;133593:16;:47;;133628:12;133593:47;;;133612:13;133593:47;133583:7;:57;-1:-1:-1;;133728:15:0;133706:19;:37;-1:-1:-1;133016:739:0;132876:886;132845:917::o;135830:4241::-;136181:21;136173:4;:29;;;;;;;;:::i;:::-;;136169:671;;;136236:5;136219:14;136278:39;136219:14;136289:27;136278:10;:39::i;:::-;136256:61;-1:-1:-1;136332:33:0;136368:85;136332:33;136397:41;136368:10;:85::i;:::-;136332:121;-1:-1:-1;136468:26:0;136497:46;136468:26;136508:34;136497:10;:46::i;:::-;136468:75;-1:-1:-1;136620:133:0;136671:59;136705:24;136468:75;101986:4;136705:24;:::i;136671:59::-;136658:10;136662:6;136658:1;:10;:::i;136620:133::-;136584:11;:169;;136558:270;;;;-1:-1:-1;;;136558:270:0;;;;;;;:::i;:::-;136204:636;;;;136169:671;137116:27;137108:4;:35;;;;;;;;:::i;:::-;;137104:671;;;137183:5;137160:20;137219:33;137160:20;137230:21;137219:10;:33::i;:::-;137203:49;-1:-1:-1;137267:33:0;137303:85;137267:33;137332:41;137303:10;:85::i;:::-;137267:121;-1:-1:-1;137403:26:0;137432:46;137403:26;137443:34;137432:10;:46::i;:::-;137403:75;-1:-1:-1;137556:132:0;137606:59;137640:24;137403:75;101986:4;137640:24;:::i;137556:132::-;137519:12;:169;;137493:270;;;;-1:-1:-1;;;137493:270:0;;;;;;;:::i;:::-;137145:630;;;;137104:671;138036:41;138028:4;:49;;;;;;;;:::i;:::-;;138024:639;;;138131:5;138094:34;138167:33;138094:34;138178:21;138167:10;:33::i;:::-;138151:49;-1:-1:-1;138215:19:0;138237:39;138215:19;138248:27;138237:10;:39::i;:::-;138215:61;-1:-1:-1;138291:26:0;138320:46;138291:26;138331:34;138320:10;:46::i;:::-;138291:75;-1:-1:-1;138443:133:0;138493:60;138528:24;138291:75;101986:4;138528:24;:::i;:::-;138493:26;;:34;:60::i;138443:133::-;138407:11;:169;;138381:270;;;;-1:-1:-1;;;138381:270:0;;;;;;;:::i;:::-;138079:584;;;;138024:639;138931:34;138923:4;:42;;;;;;;;:::i;:::-;;138919:671;;;139012:5;138982:27;139048:33;138982:27;139059:21;139048:10;:33::i;:::-;139032:49;-1:-1:-1;139096:19:0;139118:39;139096:19;139129:27;139118:10;:39::i;:::-;139096:61;-1:-1:-1;139172:33:0;139208:85;139172:33;139237:41;139208:10;:85::i;:::-;139172:121;-1:-1:-1;139370:133:0;139420:60;139454:25;139460:19;101986:4;139454:25;:::i;:::-;139420;;:33;:60::i;139370:133::-;139334:11;:169;;139308:270;;;;-1:-1:-1;;;139308:270:0;;;;;;;:::i;:::-;138967:623;;;;138919:671;139718:36;139710:4;:44;;;;;;;;:::i;:::-;;139706:358;;;139771:23;139812:4;-1:-1:-1;;;;;139797:27:0;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;139943:16;;;;139771:55;;-1:-1:-1;139873:5:0;;102201;;139919:40;;139873:5;139919:40;:::i;:::-;:63;139893:159;;;;-1:-1:-1;;;139893:159:0;;;;;;;:::i;:::-;139756:308;;135830:4241;;:::o;70793:160::-;70940:5;70918:4;70931;70923:13;;;;;;;;:::i;:::-;70918:19;;;;;;;:::i;:::-;;:27;-1:-1:-1;;;70793:160:0:o;45069:144::-;45131:7;;45169:5;45173:1;45169;:5;:::i;:::-;45151:23;-1:-1:-1;45192:13:0;44063:4;45151:23;45192:13;:::i;46836:945::-;46898:7;47131:6;;;:18;;;44063:4;47141:1;:8;47131:18;47127:647;;;-1:-1:-1;44063:4:0;47166:10;;47127:647;47198:6;47194:580;;-1:-1:-1;47228:1:0;47221:8;;47194:580;44063:4;47251:1;:8;47247:527;;;-1:-1:-1;47283:1:0;47276:8;;47247:527;44127:7;44063:4;44127:1;:7;:::i;:::-;47306:1;:8;47302:472;;;47338:13;47346:1;47349;47338:7;:13::i;:::-;47331:20;;;;47302:472;44174:7;44063:4;44174:1;:7;:::i;:::-;47373:1;:9;47369:405;;;47399:14;47416:13;47424:1;47427;47416:7;:13::i;:::-;47399:30;;47451:23;47459:6;47467;47451:7;:23::i;47369:405::-;47507:11;47521:20;47536:1;47539;47521:14;:20::i;:::-;47507:34;;47556:16;47575:42;47579:34;47585:3;44239:5;47579;:34::i;47575:42::-;47556:61;;47644:8;47638:3;:14;47634:129;;;47680:1;47673:8;;;;;;47634:129;47729:18;47733:3;47738:8;47729:3;:18::i;:::-;47722:25;;;;;;57588:2425;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;57930:14:0;;-1:-1:-1;;57800:9:0;;57915:29;;;;;;;;;:161;;58061:14;;58053:23;;;;;58013:37;;58030:20;;-1:-1:-1;;;58013:37:0;:::i;:::-;:63;;;;:::i;:::-;57915:161;;;57982:14;;57968:28;;:11;:28;:::i;:::-;57960:37;;57915:161;58116:11;;;;57902:174;;-1:-1:-1;58108:20:0;;58087:18;58164:16;58116:4;57421:16;;;57414:24;;;57323:123;58164:16;58139:41;;58203:10;58197:2;:16;;:35;;;-1:-1:-1;58217:15:0;;58197:35;58193:354;;;58347:188;;;;;;;;58390:11;58347:188;;;;;;58432:24;:6;:22;:24::i;:::-;58347:188;;;;;;58492:23;:5;:21;:23::i;:::-;58347:188;;;;;58323:212;;;;;;;;58193:354;58868:10;58841:15;58854:2;58868:10;58841:15;:::i;:::-;58816:41;;:15;:41;:::i;:::-;58815:64;;;;:::i;:::-;58797:82;-1:-1:-1;58945:21:0;58969:23;58987:5;58797:82;58969:23;:::i;:::-;58945:47;-1:-1:-1;59007:19:0;59003:313;;59138:166;;;;;;;;59181:11;59138:166;;;;;;59223:24;:6;:22;:24::i;:::-;59138:166;;;;59283:1;59138:166;;;;;59114:190;-1:-1:-1;59114:190:0;;-1:-1:-1;;;;;59114:190:0;59003:313;59640:10;59653:21;:15;:19;:21::i;:::-;59640:34;;59685:10;59698:11;:5;:9;:11::i;:::-;59685:24;-1:-1:-1;59720:17:0;59782:7;59685:24;59782:2;:7;:::i;:::-;59766:11;59771:6;59766:2;:11;:::i;:::-;59747:15;59760:2;59747:10;:15;:::i;:::-;59741:22;;:2;:22;:::i;:::-;:36;;;;:::i;:::-;59740:50;;;;:::i;:::-;59720:70;;59821:184;;;;;;;;59860:11;59821:184;;;;;;59898:27;:9;:25;:27::i;:::-;59821:184;;;;;;59957:32;:14;:30;:32::i;:::-;59821:184;;;;59801:204;57588:2425;-1:-1:-1;;;;;;;;;;;;;57588:2425:0:o;27580:5970::-;27626:6;27645:89;-1:-1:-1;;27654:1:0;:25;;:54;;;;;22694:6;27683:1;:25;;27654:54;11770:1;27645:8;:89::i;:::-;27780:1;27776;:5;27772:378;;;28126:7;28131:1;28130:2;;28126:3;:7::i;:::-;-1:-1:-1;;;28106:27:0;;;;;:::i;:::-;;;27580:5970;-1:-1:-1;;27580:5970:0:o;27772:378::-;29530:14;23143:21;29563:1;:7;29559:260;;-1:-1:-1;;;29591:7:0;;;;23200:56;29559:260;;;23309:20;29655:1;:7;29651:168;;-1:-1:-1;;;29683:7:0;;;;23365:28;29651:168;;;-1:-1:-1;29772:1:0;29651:168;29990:3;29985:8;;;;;22089:4;23477:22;30266:7;;30262:107;;-1:-1:-1;;30294:7:0;;;;22089:4;23535:34;30331:12;;30330:23;30320:33;;30262:107;23608:22;30387:1;:7;30383:107;;-1:-1:-1;;30415:7:0;;;;22089:4;23666:27;30452:12;;30451:23;30441:33;;30383:107;23732:21;30508:1;:7;30504:107;;-1:-1:-1;;30536:7:0;;;;22089:4;23789:24;30573:12;;30572:23;30562:33;;30504:107;23852:21;30629:1;:7;30625:107;;-1:-1:-1;;30657:7:0;;;;22089:4;23909:22;30694:12;;30693:23;30683:33;;30625:107;23970:21;30750:1;:7;30746:107;;-1:-1:-1;;30778:7:0;;;;22089:4;24027:21;30815:12;;30814:23;30804:33;;30746:107;24087:21;30871:1;:7;30867:107;;-1:-1:-1;;30899:7:0;;;;24087:21;24144;30936:12;;30935:23;30925:33;;30867:107;24204:20;30992:1;:7;30988:107;;-1:-1:-1;;31020:7:0;;;;22089:4;24261:21;31057:12;;31056:23;31046:33;;30988:107;24321:20;31113:1;:7;31109:107;;-1:-1:-1;;31141:7:0;;;;22089:4;24378:21;31178:12;;31177:23;31167:33;;31109:107;22089:4;31792:17;;;;;;32094:1;;32072:8;;;32071:19;32070:25;32110:17;;;;32070:25;-1:-1:-1;32175:1:0;22089:4;32153:8;;;32152:19;32151:25;32191:17;;;;32151:25;-1:-1:-1;32256:1:0;22089:4;32234:8;;;32233:19;32232:25;32272:17;;;;32232:25;-1:-1:-1;32337:1:0;22089:4;32315:8;;;32314:19;32313:25;32353:17;;;;32313:25;-1:-1:-1;32418:1:0;22089:4;32396:8;;;32395:19;32394:25;32434:17;;;;32394:25;-1:-1:-1;32499:1:0;22089:4;32477:8;;;32476:19;32475:25;32515:17;;;;32475:25;-1:-1:-1;32580:1:0;22089:4;32558:8;;;32557:19;32556:25;32596:17;;;;32556:25;-1:-1:-1;32661:1:0;22089:4;32639:8;;;32638:19;32637:25;32677:17;;;;32637:25;-1:-1:-1;32742:2:0;22089:4;32720:8;;;32719:19;32718:26;32759:17;;;;32718:26;-1:-1:-1;32824:2:0;22089:4;32802:8;;;32801:19;32800:26;32841:17;;;;32800:26;-1:-1:-1;32906:2:0;22089:4;32884:8;;;32883:19;32882:26;32923:17;;;;32882:26;-1:-1:-1;33528:3:0;22089:4;33484:19;;;33483:30;33482:42;;33481:50;;27580:5970;-1:-1:-1;;;;;;27580:5970:0:o;44426:195::-;44484:7;;44589:5;44593:1;44589;:5;:::i;78236:156::-;78298:7;78373:11;78383:1;78374:5;;;78373:11;:::i;:::-;78363:21;;78364:5;;;78363:21;:::i;93433:307::-;93517:7;93537:25;93565:24;93584:4;93565:18;:24::i;:::-;93537:52;;93600:28;93631:47;93660:17;93631:22;93648:4;88669:20;-1:-1:-1;;;;;88661:29:0;;88568:130;93631:47;93600:78;-1:-1:-1;93696:36:0;93600:78;93723:8;93696:26;:36::i;1016:4221::-;1132:14;;;-1:-1:-1;;1705:1:0;1702;1695:20;1749:1;1746;1742:9;1733:18;;1805:5;1801:2;1798:13;1790:5;1786:2;1782:14;1778:34;1769:43;;;1910:5;1919:1;1910:10;1906:209;;;1963:1;1949:11;:15;1941:24;;;;;;-1:-1:-1;2026:23:0;;;;-1:-1:-1;2086:13:0;;1906:209;2258:5;2244:11;:19;2236:28;;;;;;2573:17;2659:11;2656:1;2653;2646:25;3062:12;3078:15;;;3077:31;;3217:22;;;;;4112:1;4093;:15;;4092:21;;4359:17;;;4355:21;;4348:28;4422:17;;;4418:21;;4411:28;4486:17;;;4482:21;;4475:28;4550:17;;;4546:21;;4539:28;4614:17;;;4610:21;;4603:28;4679:17;;;4675:21;;;4668:28;3640:12;;;;3636:23;;;3661:1;3632:31;2808:20;;;2797:32;;;3701:12;;;;2856:21;;;;3366:16;;;;3692:21;;;;5179:11;;;;;-1:-1:-1;;1016:4221:0;;;;;:::o;93946:297::-;94024:7;94044:25;94072:24;94091:4;94072:18;:24::i;:::-;94044:52;;94107:29;94139:41;94162:17;94139:16;94150:4;94139:10;:16::i;94927:291::-;95007:7;95027:25;95055:24;95074:4;95055:18;:24::i;:::-;95027:52;;95090:24;95117:43;95142:17;95117:18;95130:4;88873:16;;;-1:-1:-1;;;;;88865:25:0;;88776:122;91688:147;91749:19;91795:32;91812:4;:14;;;91795:16;:32::i;98919:577::-;99157:24;99194:16;99213:171;99233:4;99252:8;99275:13;99303:19;99337:12;99364:9;99213:5;:171::i;:::-;99194:190;;99395:15;99413:27;99425:4;99431:8;99413:11;:27::i;:::-;99395:45;-1:-1:-1;99470:18:0;99395:45;99470:8;:18;:::i;89217:142::-;89285:7;89312:39;:4;:22;;;:37;;;:39::i;92172:330::-;92315:17;92358:18;;;:46;;-1:-1:-1;92380:24:0;;92358:46;92357:137;;92439:55;92455:2;92459:19;92480:13;92439:15;:55::i;:::-;92357:137;;;-1:-1:-1;92421:2:0;;92345:149;-1:-1:-1;;92172:330:0:o;50577:640::-;50639:6;50670:1;50666;:5;:19;;;;;-1:-1:-1;;;50675:1:0;:10;50666:19;50658:59;;;;-1:-1:-1;;;50658:59:0;;22726:2:1;50658:59:0;;;22708:21:1;22765:2;22745:18;;;22738:30;22804:29;22784:18;;;22777:57;22851:18;;50658:59:0;22524:351:1;50658:59:0;50740:1;50736;:5;:19;;;;;-1:-1:-1;;;50745:1:0;:10;50736:19;50728:59;;;;-1:-1:-1;;;50728:59:0;;23082:2:1;50728:59:0;;;23064:21:1;23121:2;23101:18;;;23094:30;23160:29;23140:18;;;23133:57;23207:18;;50728:59:0;22880:351:1;50728:59:0;50820:1;50854;50800:10;50880:25;50820:1;50854;50880:14;:25::i;:::-;50867:38;;50994:14;51068:1;51061:3;:8;;:21;;51079:3;51078:4;;51061:21;;;51072:3;51061:21;51044:39;;51105:16;51124:45;51128:37;51134:6;44239:5;51128;:37::i;51124:45::-;51105:64;-1:-1:-1;51187:22:0;51105:64;51187:3;:22;:::i;:::-;51180:29;50577:640;-1:-1:-1;;;;;;;;50577:640:0:o;24882:2477::-;24940:7;24989:6;24985:146;;-1:-1:-1;21895:4:0;25093:22;;24985:146;25151:6;25147:55;;-1:-1:-1;25185:1:0;25178:8;;25147:55;25599:44;-1:-1:-1;;;25608:1:0;:10;11607:1;25599:8;:44::i;:::-;25683:1;26061:57;23060:24;26070:23;;11659:1;26061:8;:57::i;:::-;26158:1;26133:15;22943:13;26215:28;-1:-1:-1;26215:60:0;;;;-1:-1:-1;22999:13:0;26247:28;;26215:60;26211:793;;;26296:14;26313:16;26320:8;26313:6;:16::i;:::-;26296:33;-1:-1:-1;21895:4:0;26848:16;;;26847:29;;26846:61;26814:8;21895:4;26773:7;:16;26772:50;:135;26756:152;;26277:647;26211:793;;;26980:8;26964:13;26968:8;26964:3;:13::i;:::-;:24;26949:39;;26211:793;21895:4;27018:22;;27125:165;-1:-1:-1;;27152:36:0;-1:-1:-1;27152:36:0;;;:76;;;22694:6;27192:12;:36;;27152:76;11717:1;27125:8;:165::i;:::-;27322:17;27326:12;27322:3;:17::i;44629:195::-;44687:7;;44792:5;44796:1;44792;:5;:::i;52815:194::-;52878:6;;52924:16;52915:25;;;52914:62;;52960:16;52914:62;;53139:266;53201:6;;-1:-1:-1;;;;;;53238:24:0;;:133;;-1:-1:-1;;;;;53311:24:0;;:59;;53364:5;53238:133;;53311:59;-1:-1:-1;;;;;53238:133:0;;;-1:-1:-1;;;;;;53220:151:0;53139:266;-1:-1:-1;;;53139:266:0:o;54527:218::-;54573:7;54715:1;54710;:6;;:15;;54724:1;54723:2;;54710:15;;;-1:-1:-1;54719:1:0;54527:218::o;7753:103::-;7823:9;7818:34;;7834:18;7842:9;7834:7;:18::i;92835:200::-;92895:7;92915:9;92927:22;92944:4;88669:20;-1:-1:-1;;;;;88661:29:0;;88568:130;92927:22;92915:34;;92960:11;92974:21;92990:4;92974:15;:21::i;:::-;92960:35;-1:-1:-1;93013:14:0;:1;92960:35;93013:9;:14::i;56237:484::-;56293:7;;56444:26;55001:4;56444:12;;;;:26;:::i;:::-;56427:43;;-1:-1:-1;;56489:7:0;:23;;:50;;;;;55107:6;56516:7;:23;;56489:50;56481:88;;;;-1:-1:-1;;;56481:88:0;;21678:2:1;56481:88:0;;;21660:21:1;21717:2;21697:18;;;21690:30;-1:-1:-1;;;21736:18:1;;;21729:55;21801:18;;56481:88:0;21476:349:1;56481:88:0;56582:11;56604:13;:7;:11;:13::i;:::-;56582:36;;56648:1;56637:7;:12;;:75;;56678:34;56690:21;55051:9;56707:3;56690:16;:21::i;56637:75::-;56652:23;55051:9;56671:3;56652:18;:23::i;33670:940::-;33731:6;;22943:13;34041:24;-1:-1:-1;34041:52:0;;;;-1:-1:-1;22999:13:0;34069:24;;34041:52;34037:184;;;34124:12;34131:4;34124:6;:12::i;:::-;34114:22;;34037:184;;;21895:4;34187:9;34191:4;34187:3;:9::i;:::-;:18;34177:28;;34037:184;34237:13;22943;34269:23;-1:-1:-1;34269:50:0;;;;-1:-1:-1;22999:13:0;34296:23;;34269:50;34265:178;;;34349:11;34356:3;34349:6;:11::i;:::-;34340:20;;34265:178;;;21895:4;34410:8;34414:3;34410;:8::i;:::-;:17;34401:26;;34265:178;34584:7;21895:4;34565:6;:15;34564:27;;;;;:::i;:::-;;;33670:940;-1:-1:-1;;;;;33670:940:0:o;41051:1921::-;21895:4;41363:11;41099:6;;-1:-1:-1;;;41800:10:0;;;;-1:-1:-1;;41775:10:0;;41774:21;41800:10;41773:38;;;;:::i;:::-;;;-1:-1:-1;41826:16:0;-1:-1:-1;;;41846:5:0;;;41845:16;;-1:-1:-1;41966:1:0;;-1:-1:-1;;;42203:15:0;;;42202:26;;-1:-1:-1;42262:1:0;42202:26;42256:7;42243:20;-1:-1:-1;;;42287:15:0;;;42286:26;;-1:-1:-1;42346:1:0;42286:26;42340:7;42327:20;-1:-1:-1;;;42371:15:0;;;42370:26;;-1:-1:-1;42430:1:0;42370:26;42424:7;42411:20;-1:-1:-1;;;42455:15:0;;;42454:26;;-1:-1:-1;42514:1:0;42454:26;42508:7;42495:20;-1:-1:-1;;;42539:15:0;;;42538:26;;-1:-1:-1;42598:2:0;42538:26;42592:8;42579:21;-1:-1:-1;;;42624:15:0;;;42623:26;;-1:-1:-1;42683:2:0;42623:26;42677:8;42664:21;-1:-1:-1;;;42709:15:0;;;42708:26;;-1:-1:-1;42768:2:0;42708:26;42762:8;42749:21;42952:1;42940:13;;;-1:-1:-1;;;;;41051:1921:0:o;35246:5531::-;35291:6;21895:4;35339:1;:10;35335:407;;;35699:26;35723:1;-1:-1:-1;;;35723:1:0;35703:21;;;;:::i;:::-;;35699:3;:26::i;:::-;35698:27;;;35246:5531;-1:-1:-1;;35246:5531:0:o;35335:407::-;37140:10;37178:11;37173:16;;37169:129;;23200:56;37210:7;;;-1:-1:-1;23143:21:0;37273:9;37169:129;37323:11;37318:16;;37314:129;;23365:28;37355:7;;;-1:-1:-1;23309:20:0;37418:9;37314:129;37592:3;37610:8;;;;37585:10;23535:34;37757:7;;37753:97;;23535:34;22089:4;37790:10;;37789:17;;-1:-1:-1;23477:22:0;37825:9;37753:97;23666:27;37870:1;:7;37866:97;;23666:27;22089:4;37903:10;;37902:17;;-1:-1:-1;23608:22:0;37938:9;37866:97;23789:24;37983:1;:7;37979:97;;23789:24;22089:4;38016:10;;38015:17;;-1:-1:-1;23732:21:0;38051:9;37979:97;23909:22;38096:1;:7;38092:97;;23909:22;22089:4;38129:10;;38128:17;;-1:-1:-1;23852:21:0;38164:9;38092:97;24027:21;38209:1;:7;38205:97;;24027:21;22089:4;38242:10;;38241:17;;-1:-1:-1;23970:21:0;38277:9;38205:97;24144:21;38322:1;:7;38318:97;;24144:21;22089:4;38355:10;;;38354:17;;38390:9;38318:97;24261:21;38435:1;:7;38431:97;;24261:21;22089:4;38468:10;;38467:17;;-1:-1:-1;24204:20:0;38503:9;38431:97;24378:21;38548:1;:7;38544:97;;24378:21;22089:4;38581:10;;38580:17;;-1:-1:-1;24321:20:0;38616:9;38544:97;24497:21;38661:1;:8;38657:100;;24497:21;22089:4;38695:10;;38694:18;;-1:-1:-1;24439:20:0;38731:10;38657:100;24616:21;38777:1;:8;38773:100;;24616:21;22089:4;38811:10;;38810:18;;-1:-1:-1;24559:19:0;38847:10;38773:100;39412:8;22089:4;39450:1;:10;22089:4;;39425:1;:10;39424:21;39423:38;;;;;:::i;:::-;;;-1:-1:-1;39476:16:0;22089:4;39496:5;;;39495:16;;-1:-1:-1;39616:1:0;;22089:4;39853:15;;;39852:26;;-1:-1:-1;39912:1:0;39852:26;39906:7;39893:20;22089:4;39937:15;;;39936:26;;-1:-1:-1;39996:1:0;39936:26;39990:7;39977:20;22089:4;40021:15;;;40020:26;;-1:-1:-1;40080:1:0;40020:26;40074:7;40061:20;22089:4;40105:15;;;40104:26;;-1:-1:-1;40164:1:0;40104:26;40158:7;40145:20;22089:4;40189:15;;;40188:26;;-1:-1:-1;40248:2:0;40188:26;40242:8;40229:21;40439:1;40426:14;40755:3;40736:15;;;40735:23;;35246:5531;-1:-1:-1;;;;;;;35246:5531:0:o;7968:3260::-;-1:-1:-1;;;10558:3:0;10551:79;;;10771:66;10765:4;10758:80;10915:1;10909:4;10902:15;9951:73;9120:2;9155:18;;;9201;;;9125:4;9197:29;;;9992:1;9988:14;9105:18;;;;9977:26;;;;9251:18;;;;9299;;;9295:29;;;10009:2;10005:17;9973:50;;;;9951:73;9933:3;9915:120;10984:4;10977:26;11214:3;;11204:14;91256:146;91322:17;91364:30;91381:4;:12;;;91364:16;:30::i;48025:834::-;48085:7;48318:6;;;:18;;;44063:4;48328:1;:8;48318:18;48314:538;;;-1:-1:-1;44063:4:0;48353:10;;48314:538;48385:6;48381:471;;-1:-1:-1;48415:1:0;48408:8;;48381:471;44063:4;48438:1;:8;48434:418;;;-1:-1:-1;48470:1:0;48463:8;;48434:418;44127:7;44063:4;44127:1;:7;:::i;:::-;48493:1;:8;48489:363;;;48525:11;48531:1;48534;48525:5;:11::i;48489:363::-;44174:7;44063:4;44174:1;:7;:::i;:::-;48558:1;:9;48554:298;;;48584:14;48601:11;48607:1;48610;48601:5;:11::i;:::-;48584:28;;48634:21;48640:6;48648;48634:5;:21::i;48554:298::-;48688:11;48702:20;48717:1;48720;48702:14;:20::i;:::-;48688:34;;48737:16;48756:42;48760:34;48766:3;44239:5;48760;:34::i;48756:42::-;48737:61;;48822:18;48826:3;48831:8;48822:3;:18::i;196:127:1:-;257:10;252:3;248:20;245:1;238:31;288:4;285:1;278:15;312:4;309:1;302:15;328:118;414:5;407:13;400:21;393:5;390:32;380:60;;436:1;433;426:12;451:964;502:5;532:6;575:2;563:9;558:3;554:19;550:28;547:48;;;591:1;588;581:12;547:48;624:2;618:9;654:15;;;;699:18;684:34;;720:22;;;681:62;678:88;;;746:18;;:::i;:::-;786:10;782:2;775:22;815:6;806:15;;858:9;845:23;837:6;830:39;930:2;919:9;915:18;902:32;897:2;889:6;885:15;878:57;996:2;985:9;981:18;968:32;963:2;955:6;951:15;944:57;1062:2;1051:9;1047:18;1034:32;1029:2;1021:6;1017:15;1010:57;1129:3;1118:9;1114:19;1101:33;1095:3;1087:6;1083:16;1076:59;1197:3;1186:9;1182:19;1169:33;1163:3;1155:6;1151:16;1144:59;1265:3;1254:9;1250:19;1237:33;1231:3;1223:6;1219:16;1212:59;1323:3;1312:9;1308:19;1295:33;1280:48;;1337:30;1359:7;1337:30;:::i;:::-;1395:3;1383:16;1376:33;451:964;;-1:-1:-1;;451:964:1:o;1420:291::-;1510:6;1518;1571:3;1559:9;1550:7;1546:23;1542:33;1539:53;;;1588:1;1585;1578:12;1539:53;1611:42;1645:7;1634:9;1611:42;:::i;:::-;1601:52;1700:3;1685:19;;;;1672:33;;-1:-1:-1;;;1420:291:1:o;1924:316::-;2001:6;2009;2017;2070:2;2058:9;2049:7;2045:23;2041:32;2038:52;;;2086:1;2083;2076:12;2038:52;-1:-1:-1;;2109:23:1;;;2179:2;2164:18;;2151:32;;-1:-1:-1;2230:2:1;2215:18;;;2202:32;;1924:316;-1:-1:-1;1924:316:1:o;2245:180::-;2304:6;2357:2;2345:9;2336:7;2332:23;2328:32;2325:52;;;2373:1;2370;2363:12;2325:52;-1:-1:-1;2396:23:1;;2245:180;-1:-1:-1;2245:180:1:o;3437:222::-;3518:6;3571:3;3559:9;3550:7;3546:23;3542:33;3539:53;;;3588:1;3585;3578:12;3539:53;3611:42;3645:7;3634:9;3611:42;:::i;3856:446::-;3939:6;3947;3955;3963;4016:3;4004:9;3995:7;3991:23;3987:33;3984:53;;;4033:1;4030;4023:12;3984:53;4069:9;4056:23;4046:33;;4126:2;4115:9;4111:18;4098:32;4088:42;;4180:2;4169:9;4165:18;4152:32;4193:28;4215:5;4193:28;:::i;:::-;3856:446;;;;-1:-1:-1;4240:5:1;;4292:2;4277:18;4264:32;;-1:-1:-1;;3856:446:1:o;4307:781::-;4390:6;4421:3;4465:2;4453:9;4444:7;4440:23;4436:32;4433:52;;;4481:1;4478;4471:12;4433:52;4530:7;4523:4;4512:9;4508:20;4504:34;4494:62;;4552:1;4549;4542:12;4494:62;4585:2;4579:9;4627:2;4619:6;4615:15;4696:6;4684:10;4681:22;4660:18;4648:10;4645:34;4642:62;4639:88;;;4707:18;;:::i;:::-;4743:2;4736:22;4807:18;;;;4778:6;4837:19;;;4834:39;;;4869:1;4866;4859:12;4834:39;4893:9;4911:146;4927:6;4922:3;4919:15;4911:146;;;4995:17;;4983:30;;5042:4;5033:14;;;;4944;4911:146;;;-1:-1:-1;5076:6:1;;4307:781;-1:-1:-1;;;;;4307:781:1:o;5474:340::-;5557:6;5565;5618:2;5606:9;5597:7;5593:23;5589:32;5586:52;;;5634:1;5631;5624:12;5586:52;5673:9;5660:23;5712:2;5705:5;5702:13;5692:41;;5729:1;5726;5719:12;5692:41;5752:5;5804:2;5789:18;;;;5776:32;;-1:-1:-1;;;5474:340:1:o;5819:248::-;5887:6;5895;5948:2;5936:9;5927:7;5923:23;5919:32;5916:52;;;5964:1;5961;5954:12;5916:52;-1:-1:-1;;5987:23:1;;;6057:2;6042:18;;;6029:32;;-1:-1:-1;5819:248:1:o;7248:131::-;-1:-1:-1;;;;;7323:31:1;;7313:42;;7303:70;;7369:1;7366;7359:12;7384:315;7452:6;7460;7513:2;7501:9;7492:7;7488:23;7484:32;7481:52;;;7529:1;7526;7519:12;7481:52;7568:9;7555:23;7587:31;7612:5;7587:31;:::i;7704:163::-;7771:20;;7831:10;7820:22;;7810:33;;7800:61;;7857:1;7854;7847:12;7872:813;7966:6;7974;8018:9;8009:7;8005:23;8048:3;8044:2;8040:12;8037:32;;;8065:1;8062;8055:12;8037:32;8089:4;8085:2;8081:13;8078:33;;;8107:1;8104;8097:12;8078:33;;8140:2;8134:9;8182:4;8174:6;8170:17;8253:6;8241:10;8238:22;8217:18;8205:10;8202:34;8199:62;8196:88;;;8264:18;;:::i;:::-;8300:2;8293:22;8339:28;8357:9;8339:28;:::i;:::-;8331:6;8324:44;8401:37;8434:2;8423:9;8419:18;8401:37;:::i;:::-;8396:2;8388:6;8384:15;8377:62;8489:2;8478:9;8474:18;8461:32;8537:5;8533:2;8522:21;8515:5;8512:32;8502:60;;8558:1;8555;8548:12;8502:60;8590:2;8578:15;;8571:30;8582:6;8673:4;8658:20;;;;8645:34;;-1:-1:-1;;;7872:813:1:o;8690:127::-;8751:10;8746:3;8742:20;8739:1;8732:31;8782:4;8779:1;8772:15;8806:4;8803:1;8796:15;8822:128;8862:3;8893:1;8889:6;8886:1;8883:13;8880:39;;;8899:18;;:::i;:::-;-1:-1:-1;8935:9:1;;8822:128::o;8955:342::-;9157:2;9139:21;;;9196:2;9176:18;;;9169:30;-1:-1:-1;;;9230:2:1;9215:18;;9208:48;9288:2;9273:18;;8955:342::o;9302:339::-;9504:2;9486:21;;;9543:2;9523:18;;;9516:30;-1:-1:-1;;;9577:2:1;9562:18;;9555:45;9632:2;9617:18;;9302:339::o;10340:::-;10542:2;10524:21;;;10581:2;10561:18;;;10554:30;-1:-1:-1;;;10615:2:1;10600:18;;10593:45;10670:2;10655:18;;10340:339::o;11031:125::-;11071:4;11099:1;11096;11093:8;11090:34;;;11104:18;;:::i;:::-;-1:-1:-1;11141:9:1;;11031:125::o;11161:267::-;11200:4;11229:9;;;11254:10;;-1:-1:-1;;;11273:19:1;;11266:27;;11250:44;11247:70;;;11297:18;;:::i;:::-;-1:-1:-1;;;;;11344:27:1;;11337:35;;11329:44;;11326:70;;;11376:18;;:::i;:::-;-1:-1:-1;;11413:9:1;;11161:267::o;11433:231::-;11473:4;-1:-1:-1;;;;;11571:10:1;;;;11541;;11593:12;;;11590:38;;;11608:18;;:::i;:::-;11645:13;;11433:231;-1:-1:-1;;;11433:231:1:o;12342:245::-;12409:6;12462:2;12450:9;12441:7;12437:23;12433:32;12430:52;;;12478:1;12475;12468:12;12430:52;12510:9;12504:16;12529:28;12551:5;12529:28;:::i;12592:251::-;12662:6;12715:2;12703:9;12694:7;12690:23;12686:32;12683:52;;;12731:1;12728;12721:12;12683:52;12763:9;12757:16;12782:31;12807:5;12782:31;:::i;13193:184::-;13263:6;13316:2;13304:9;13295:7;13291:23;13287:32;13284:52;;;13332:1;13329;13322:12;13284:52;-1:-1:-1;13355:16:1;;13193:184;-1:-1:-1;13193:184:1:o;14755:135::-;14794:3;-1:-1:-1;;14815:17:1;;14812:43;;;14835:18;;:::i;:::-;-1:-1:-1;14882:1:1;14871:13;;14755:135::o;15753:339::-;15955:2;15937:21;;;15994:2;15974:18;;;15967:30;-1:-1:-1;;;16028:2:1;16013:18;;16006:45;16083:2;16068:18;;15753:339::o;16097:946::-;16189:6;16220:3;16264:2;16252:9;16243:7;16239:23;16235:32;16232:52;;;16280:1;16277;16270:12;16232:52;16313:2;16307:9;16343:15;;;;16388:18;16373:34;;16409:22;;;16370:62;16367:88;;;16435:18;;:::i;:::-;16475:10;16471:2;16464:22;16516:9;16510:16;16502:6;16495:32;16581:2;16570:9;16566:18;16560:25;16555:2;16547:6;16543:15;16536:50;16640:2;16629:9;16625:18;16619:25;16614:2;16606:6;16602:15;16595:50;16699:2;16688:9;16684:18;16678:25;16673:2;16665:6;16661:15;16654:50;16759:3;16748:9;16744:19;16738:26;16732:3;16724:6;16720:16;16713:52;16820:3;16809:9;16805:19;16799:26;16793:3;16785:6;16781:16;16774:52;16881:3;16870:9;16866:19;16860:26;16854:3;16846:6;16842:16;16835:52;16930:3;16919:9;16915:19;16909:26;16896:39;;16944:28;16966:5;16944:28;:::i;:::-;17000:3;16988:16;;16981:31;;;;16992:6;16097:946;-1:-1:-1;;;16097:946:1:o;17388:127::-;17449:10;17444:3;17440:20;17437:1;17430:31;17480:4;17477:1;17470:15;17504:4;17501:1;17494:15;17520:127;17581:10;17576:3;17572:20;17569:1;17562:31;17612:4;17609:1;17602:15;17636:4;17633:1;17626:15;17652:168;17692:7;17758:1;17754;17750:6;17746:14;17743:1;17740:21;17735:1;17728:9;17721:17;17717:45;17714:71;;;17765:18;;:::i;:::-;-1:-1:-1;17805:9:1;;17652:168::o;17825:403::-;18027:2;18009:21;;;18066:2;18046:18;;;18039:30;18105:34;18100:2;18085:18;;18078:62;-1:-1:-1;;;18171:2:1;18156:18;;18149:37;18218:3;18203:19;;17825:403::o;18233:398::-;18435:2;18417:21;;;18474:2;18454:18;;;18447:30;18513:34;18508:2;18493:18;;18486:62;-1:-1:-1;;;18579:2:1;18564:18;;18557:32;18621:3;18606:19;;18233:398::o;18636:127::-;18697:10;18692:3;18688:20;18685:1;18678:31;18728:4;18725:1;18718:15;18752:4;18749:1;18742:15;18768:120;18808:1;18834;18824:35;;18839:18;;:::i;:::-;-1:-1:-1;18873:9:1;;18768:120::o;19563:553::-;19602:7;-1:-1:-1;;;;;19672:9:1;;;19700;;;19725:11;;;19744:10;;;19738:17;;19721:35;19718:61;;;19759:18;;:::i;:::-;-1:-1:-1;;;19835:1:1;19828:9;;19853:11;;;19873;;;19866:19;;19849:37;19846:63;;;19889:18;;:::i;:::-;19935:1;19932;19928:9;19918:19;;19982:1;19978:2;19973:11;19970:1;19966:19;19961:2;19957;19953:11;19949:37;19946:63;;;19989:18;;:::i;:::-;20054:1;20050:2;20045:11;20042:1;20038:19;20033:2;20029;20025:11;20021:37;20018:63;;;20061:18;;:::i;:::-;-1:-1:-1;;;20101:9:1;;;;;19563:553;-1:-1:-1;;;19563:553:1:o;21830:193::-;21869:1;21895;21885:35;;21900:18;;:::i;:::-;-1:-1:-1;;;21936:18:1;;-1:-1:-1;;21956:13:1;;21932:38;21929:64;;;21973:18;;:::i;:::-;-1:-1:-1;22007:10:1;;21830:193::o;22028:221::-;22067:4;22096:10;22156;;;;22126;;22178:12;;;22175:38;;;22193:18;;:::i;22254:265::-;22293:3;22321:9;;;22346:10;;-1:-1:-1;;;;;22365:27:1;;;22358:35;;22342:52;22339:78;;;22397:18;;:::i;:::-;-1:-1:-1;;;22444:19:1;;;22437:27;;22429:36;;22426:62;;;22468:18;;:::i;:::-;-1:-1:-1;;22504:9:1;;22254:265::o
Swarm Source
ipfs://ee478acafbb18cfc986294a7b7b8431a058e742dfd924976abd552d038da8a62
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.