Overview
ETH Balance
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
18307860 | 9 mins ago | 0 ETH | ||||
18307838 | 10 mins ago | 0 ETH | ||||
18307838 | 10 mins ago | 0 ETH | ||||
18307769 | 13 mins ago | 1 wei | ||||
18307769 | 13 mins ago | 0 ETH | ||||
18307768 | 13 mins ago | 1 wei | ||||
18307768 | 13 mins ago | 0 ETH | ||||
18307767 | 13 mins ago | 1 wei | ||||
18307767 | 13 mins ago | 0 ETH | ||||
18307549 | 22 mins ago | 3 wei | ||||
18307549 | 22 mins ago | 0 ETH | ||||
18307310 | 32 mins ago | 0 ETH | ||||
18306816 | 52 mins ago | 3 wei | ||||
18306816 | 52 mins ago | 0 ETH | ||||
18306687 | 57 mins ago | 5 wei | ||||
18306608 | 1 hr ago | 5 wei | ||||
18306558 | 1 hr ago | 5 wei | ||||
18306550 | 1 hr ago | 1 wei | ||||
18306550 | 1 hr ago | 0 ETH | ||||
18306540 | 1 hr ago | 1 wei | ||||
18306540 | 1 hr ago | 0 ETH | ||||
18306299 | 1 hr ago | 1 wei | ||||
18306299 | 1 hr ago | 0 ETH | ||||
18306299 | 1 hr ago | 1 wei | ||||
18306299 | 1 hr ago | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
PythUpgradable
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity)
/** *Submitted for verification at lineascan.build/ on 2023-07-26 */ pragma solidity ^0.8.0; // SPDX-License-Identifier: Apache-2 /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. * * @notice This is the **unsafe** version of BytesLib which removed all the checks (out of bound, ...) * to be more gas efficient. */ library UnsafeBytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore( 0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. ) ) } return tempBytes; } function concatStorage( bytes storage _preBytes, bytes memory _postBytes ) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div( and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2 ) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add( add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)) ) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add( add( add(_bytes, lengthmod), mul(0x20, iszero(lengthmod)) ), _start ) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress( bytes memory _bytes, uint256 _start ) internal pure returns (address) { address tempAddress; assembly { tempAddress := div( mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000 ) } return tempAddress; } function toUint8( bytes memory _bytes, uint256 _start ) internal pure returns (uint8) { uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16( bytes memory _bytes, uint256 _start ) internal pure returns (uint16) { uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32( bytes memory _bytes, uint256 _start ) internal pure returns (uint32) { uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64( bytes memory _bytes, uint256 _start ) internal pure returns (uint64) { uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96( bytes memory _bytes, uint256 _start ) internal pure returns (uint96) { uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128( bytes memory _bytes, uint256 _start ) internal pure returns (uint128) { uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256( bytes memory _bytes, uint256 _start ) internal pure returns (uint256) { uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32( bytes memory _bytes, uint256 _start ) internal pure returns (bytes32) { bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div( and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2 ) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for { } eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } } contract PythStructs { // A price with a degree of uncertainty, represented as a price +- a confidence interval. // // The confidence interval roughly corresponds to the standard error of a normal distribution. // Both the price and confidence are stored in a fixed-point numeric representation, // `x * (10^expo)`, where `expo` is the exponent. // // Please refer to the documentation at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how // to how this price safely. struct Price { // Price int64 price; // Confidence interval around the price uint64 conf; // Price exponent int32 expo; // Unix timestamp describing when the price was published uint publishTime; } // PriceFeed represents a current aggregate price from pyth publisher feeds. struct PriceFeed { // The price ID. bytes32 id; // Latest available price Price price; // Latest available exponentially-weighted moving average price Price emaPrice; } } interface IPythEvents { /// @dev Emitted when the price feed with `id` has received a fresh update. /// @param id The Pyth Price Feed ID. /// @param publishTime Publish time of the given price update. /// @param price Price of the given price update. /// @param conf Confidence interval of the given price update. event PriceFeedUpdate( bytes32 indexed id, uint64 publishTime, int64 price, uint64 conf ); /// @dev Emitted when a batch price update is processed successfully. /// @param chainId ID of the source chain that the batch price update comes from. /// @param sequenceNumber Sequence number of the batch price update. event BatchPriceFeedUpdate(uint16 chainId, uint64 sequenceNumber); } interface IPyth is IPythEvents { /// @notice Returns the period (in seconds) that a price feed is considered valid since its publish time function getValidTimePeriod() external view returns (uint validTimePeriod); /// @notice Returns the price and confidence interval. /// @dev Reverts if the price has not been updated within the last `getValidTimePeriod()` seconds. /// @param id The Pyth Price Feed ID of which to fetch the price and confidence interval. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getPrice( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the exponentially-weighted moving average price and confidence interval. /// @dev Reverts if the EMA price is not available. /// @param id The Pyth Price Feed ID of which to fetch the EMA price and confidence interval. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getEmaPrice( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the price of a price feed without any sanity checks. /// @dev This function returns the most recent price update in this contract without any recency checks. /// This function is unsafe as the returned price update may be arbitrarily far in the past. /// /// Users of this function should check the `publishTime` in the price to ensure that the returned price is /// sufficiently recent for their application. If you are considering using this function, it may be /// safer / easier to use either `getPrice` or `getPriceNoOlderThan`. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getPriceUnsafe( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the price that is no older than `age` seconds of the current time. /// @dev This function is a sanity-checked version of `getPriceUnsafe` which is useful in /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently /// recently. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getPriceNoOlderThan( bytes32 id, uint age ) external view returns (PythStructs.Price memory price); /// @notice Returns the exponentially-weighted moving average price of a price feed without any sanity checks. /// @dev This function returns the same price as `getEmaPrice` in the case where the price is available. /// However, if the price is not recent this function returns the latest available price. /// /// The returned price can be from arbitrarily far in the past; this function makes no guarantees that /// the returned price is recent or useful for any particular application. /// /// Users of this function should check the `publishTime` in the price to ensure that the returned price is /// sufficiently recent for their application. If you are considering using this function, it may be /// safer / easier to use either `getEmaPrice` or `getEmaPriceNoOlderThan`. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getEmaPriceUnsafe( bytes32 id ) external view returns (PythStructs.Price memory price); /// @notice Returns the exponentially-weighted moving average price that is no older than `age` seconds /// of the current time. /// @dev This function is a sanity-checked version of `getEmaPriceUnsafe` which is useful in /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently /// recently. /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely. function getEmaPriceNoOlderThan( bytes32 id, uint age ) external view returns (PythStructs.Price memory price); /// @notice Update price feeds with given update messages. /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling /// `getUpdateFee` with the length of the `updateData` array. /// Prices will be updated if they are more recent than the current stored prices. /// The call will succeed even if the update is not the most recent. /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid. /// @param updateData Array of price update data. function updatePriceFeeds(bytes[] calldata updateData) external payable; /// @notice Wrapper around updatePriceFeeds that rejects fast if a price update is not necessary. A price update is /// necessary if the current on-chain publishTime is older than the given publishTime. It relies solely on the /// given `publishTimes` for the price feeds and does not read the actual price update publish time within `updateData`. /// /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling /// `getUpdateFee` with the length of the `updateData` array. /// /// `priceIds` and `publishTimes` are two arrays with the same size that correspond to senders known publishTime /// of each priceId when calling this method. If all of price feeds within `priceIds` have updated and have /// a newer or equal publish time than the given publish time, it will reject the transaction to save gas. /// Otherwise, it calls updatePriceFeeds method to update the prices. /// /// @dev Reverts if update is not needed or the transferred fee is not sufficient or the updateData is invalid. /// @param updateData Array of price update data. /// @param priceIds Array of price ids. /// @param publishTimes Array of publishTimes. `publishTimes[i]` corresponds to known `publishTime` of `priceIds[i]` function updatePriceFeedsIfNecessary( bytes[] calldata updateData, bytes32[] calldata priceIds, uint64[] calldata publishTimes ) external payable; /// @notice Returns the required fee to update an array of price updates. /// @param updateData Array of price update data. /// @return feeAmount The required fee in Wei. function getUpdateFee( bytes[] calldata updateData ) external view returns (uint feeAmount); /// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published /// within `minPublishTime` and `maxPublishTime`. /// /// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price; /// otherwise, please consider using `updatePriceFeeds`. This method does not store the price updates on-chain. /// /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling /// `getUpdateFee` with the length of the `updateData` array. /// /// /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is /// no update for any of the given `priceIds` within the given time range. /// @param updateData Array of price update data. /// @param priceIds Array of price ids. /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`. /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`. /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order). function parsePriceFeedUpdates( bytes[] calldata updateData, bytes32[] calldata priceIds, uint64 minPublishTime, uint64 maxPublishTime ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds); } library PythErrors { // Function arguments are invalid (e.g., the arguments lengths mismatch) // Signature: 0xa9cb9e0d error InvalidArgument(); // Update data is coming from an invalid data source. // Signature: 0xe60dce71 error InvalidUpdateDataSource(); // Update data is invalid (e.g., deserialization error) // Signature: 0xe69ffece error InvalidUpdateData(); // Insufficient fee is paid to the method. // Signature: 0x025dbdd4 error InsufficientFee(); // There is no fresh update, whereas expected fresh updates. // Signature: 0xde2c57fa error NoFreshUpdate(); // There is no price feed found within the given range or it does not exists. // Signature: 0x45805f5d error PriceFeedNotFoundWithinRange(); // Price feed not found or it is not pushed on-chain yet. // Signature: 0x14aebe68 error PriceFeedNotFound(); // Requested price is stale. // Signature: 0x19abf40e error StalePrice(); // Given message is not a valid Wormhole VAA. // Signature: 0x2acbe915 error InvalidWormholeVaa(); // Governance message is invalid (e.g., deserialization error). // Signature: 0x97363b35 error InvalidGovernanceMessage(); // Governance message is not for this contract. // Signature: 0x63daeb77 error InvalidGovernanceTarget(); // Governance message is coming from an invalid data source. // Signature: 0x360f2d87 error InvalidGovernanceDataSource(); // Governance message is old. // Signature: 0x88d1b847 error OldGovernanceMessage(); // The wormhole address to set in SetWormholeAddress governance is invalid. // Signature: 0x13d3ed82 error InvalidWormholeAddressToSet(); } abstract contract AbstractPyth is IPyth { /// @notice Returns the price feed with given id. /// @dev Reverts if the price does not exist. /// @param id The Pyth Price Feed ID of which to fetch the PriceFeed. function queryPriceFeed( bytes32 id ) public view virtual returns (PythStructs.PriceFeed memory priceFeed); /// @notice Returns true if a price feed with the given id exists. /// @param id The Pyth Price Feed ID of which to check its existence. function priceFeedExists( bytes32 id ) public view virtual returns (bool exists); function getValidTimePeriod() public view virtual override returns (uint validTimePeriod); function getPrice( bytes32 id ) external view virtual override returns (PythStructs.Price memory price) { return getPriceNoOlderThan(id, getValidTimePeriod()); } function getEmaPrice( bytes32 id ) external view virtual override returns (PythStructs.Price memory price) { return getEmaPriceNoOlderThan(id, getValidTimePeriod()); } function getPriceUnsafe( bytes32 id ) public view virtual override returns (PythStructs.Price memory price) { PythStructs.PriceFeed memory priceFeed = queryPriceFeed(id); return priceFeed.price; } function getPriceNoOlderThan( bytes32 id, uint age ) public view virtual override returns (PythStructs.Price memory price) { price = getPriceUnsafe(id); if (diff(block.timestamp, price.publishTime) > age) revert PythErrors.StalePrice(); return price; } function getEmaPriceUnsafe( bytes32 id ) public view virtual override returns (PythStructs.Price memory price) { PythStructs.PriceFeed memory priceFeed = queryPriceFeed(id); return priceFeed.emaPrice; } function getEmaPriceNoOlderThan( bytes32 id, uint age ) public view virtual override returns (PythStructs.Price memory price) { price = getEmaPriceUnsafe(id); if (diff(block.timestamp, price.publishTime) > age) revert PythErrors.StalePrice(); return price; } function diff(uint x, uint y) internal pure returns (uint) { if (x > y) { return x - y; } else { return y - x; } } // Access modifier is overridden to public to be able to call it locally. function updatePriceFeeds( bytes[] calldata updateData ) public payable virtual override; function updatePriceFeedsIfNecessary( bytes[] calldata updateData, bytes32[] calldata priceIds, uint64[] calldata publishTimes ) external payable virtual override { if (priceIds.length != publishTimes.length) revert PythErrors.InvalidArgument(); for (uint i = 0; i < priceIds.length; i++) { if ( !priceFeedExists(priceIds[i]) || queryPriceFeed(priceIds[i]).price.publishTime < publishTimes[i] ) { updatePriceFeeds(updateData); return; } } revert PythErrors.NoFreshUpdate(); } function parsePriceFeedUpdates( bytes[] calldata updateData, bytes32[] calldata priceIds, uint64 minPublishTime, uint64 maxPublishTime ) external payable virtual override returns (PythStructs.PriceFeed[] memory priceFeeds); } /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. * * @notice This is the **unsafe** version of BytesLib which removed all the checks (out of bound, ...) * to be more gas efficient. */ library UnsafeCalldataBytesLib { function slice( bytes calldata _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes calldata) { return _bytes[_start:_start + _length]; } function sliceFrom( bytes calldata _bytes, uint256 _start ) internal pure returns (bytes calldata) { return _bytes[_start:_bytes.length]; } function toAddress( bytes calldata _bytes, uint256 _start ) internal pure returns (address) { address tempAddress; assembly { tempAddress := shr(96, calldataload(add(_bytes.offset, _start))) } return tempAddress; } function toUint8( bytes calldata _bytes, uint256 _start ) internal pure returns (uint8) { uint8 tempUint; assembly { tempUint := shr(248, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint16( bytes calldata _bytes, uint256 _start ) internal pure returns (uint16) { uint16 tempUint; assembly { tempUint := shr(240, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint32( bytes calldata _bytes, uint256 _start ) internal pure returns (uint32) { uint32 tempUint; assembly { tempUint := shr(224, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint64( bytes calldata _bytes, uint256 _start ) internal pure returns (uint64) { uint64 tempUint; assembly { tempUint := shr(192, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint96( bytes calldata _bytes, uint256 _start ) internal pure returns (uint96) { uint96 tempUint; assembly { tempUint := shr(160, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint128( bytes calldata _bytes, uint256 _start ) internal pure returns (uint128) { uint128 tempUint; assembly { tempUint := shr(128, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint256( bytes calldata _bytes, uint256 _start ) internal pure returns (uint256) { uint256 tempUint; assembly { tempUint := calldataload(add(_bytes.offset, _start)) } return tempUint; } function toBytes32( bytes calldata _bytes, uint256 _start ) internal pure returns (bytes32) { bytes32 tempBytes32; assembly { tempBytes32 := calldataload(add(_bytes.offset, _start)) } return tempBytes32; } } interface Structs { struct Provider { uint16 chainId; uint16 governanceChainId; bytes32 governanceContract; } struct GuardianSet { address[] keys; uint32 expirationTime; } struct Signature { bytes32 r; bytes32 s; uint8 v; uint8 guardianIndex; } struct VM { uint8 version; uint32 timestamp; uint32 nonce; uint16 emitterChainId; bytes32 emitterAddress; uint64 sequence; uint8 consistencyLevel; bytes payload; uint32 guardianSetIndex; Signature[] signatures; bytes32 hash; } } interface IWormhole is Structs { event LogMessagePublished( address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel ); function publishMessage( uint32 nonce, bytes memory payload, uint8 consistencyLevel ) external payable returns (uint64 sequence); function parseAndVerifyVM( bytes calldata encodedVM ) external view returns (Structs.VM memory vm, bool valid, string memory reason); function verifyVM( Structs.VM memory vm ) external view returns (bool valid, string memory reason); function verifySignatures( bytes32 hash, Structs.Signature[] memory signatures, Structs.GuardianSet memory guardianSet ) external pure returns (bool valid, string memory reason); function parseVM( bytes memory encodedVM ) external pure returns (Structs.VM memory vm); function getGuardianSet( uint32 index ) external view returns (Structs.GuardianSet memory); function getCurrentGuardianSetIndex() external view returns (uint32); function getGuardianSetExpiry() external view returns (uint32); function governanceActionIsConsumed( bytes32 hash ) external view returns (bool); function isInitialized(address impl) external view returns (bool); function chainId() external view returns (uint16); function governanceChainId() external view returns (uint16); function governanceContract() external view returns (bytes32); function messageFee() external view returns (uint256); } /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore( 0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. ) ) } return tempBytes; } function concatStorage( bytes storage _preBytes, bytes memory _postBytes ) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div( and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2 ) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add( add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)) ) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add( add( add(_bytes, lengthmod), mul(0x20, iszero(lengthmod)) ), _start ) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress( bytes memory _bytes, uint256 _start ) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div( mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000 ) } return tempAddress; } function toUint8( bytes memory _bytes, uint256 _start ) internal pure returns (uint8) { require(_bytes.length >= _start + 1, "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16( bytes memory _bytes, uint256 _start ) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32( bytes memory _bytes, uint256 _start ) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64( bytes memory _bytes, uint256 _start ) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96( bytes memory _bytes, uint256 _start ) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128( bytes memory _bytes, uint256 _start ) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256( bytes memory _bytes, uint256 _start ) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32( bytes memory _bytes, uint256 _start ) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div( and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2 ) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for { } eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } } contract PythInternalStructs { using BytesLib for bytes; struct PriceInfo { // slot 1 uint64 publishTime; int32 expo; int64 price; uint64 conf; // slot 2 int64 emaPrice; uint64 emaConf; } struct DataSource { uint16 chainId; bytes32 emitterAddress; } } contract PythDeprecatedStructs { // Structs related to the _deprecatedLatestPriceInfoV1 enum DeprecatedPriceStatusV1 { UNKNOWN, TRADING, HALTED, AUCTION } struct DeprecatedPriceFeedV1 { // The price ID. bytes32 id; // Product account key. bytes32 productId; // The current price. int64 price; // Confidence interval around the price. uint64 conf; // Price exponent. int32 expo; // Status of price. DeprecatedPriceStatusV1 status; // Maximum number of allowed publishers that can contribute to a price. uint32 maxNumPublishers; // Number of publishers that made up current aggregate. uint32 numPublishers; // Exponentially moving average price. int64 emaPrice; // Exponentially moving average confidence interval. uint64 emaConf; // Unix timestamp describing when the price was published uint64 publishTime; // Price of previous price with TRADING status int64 prevPrice; // Confidence interval of previous price with TRADING status uint64 prevConf; // Unix timestamp describing when the previous price with TRADING status was published uint64 prevPublishTime; } struct DeprecatedPriceInfoV1 { uint256 attestationTime; uint256 arrivalTime; uint256 arrivalBlock; DeprecatedPriceFeedV1 priceFeed; } // Structs related to the _deprecatedLatestPriceInfoV2 struct DeprecatedPriceV2 { // Price int64 price; // Confidence interval around the price uint64 conf; // Price exponent int32 expo; // Unix timestamp describing when the price was published uint publishTime; } // PriceFeed represents a current aggregate price from pyth publisher feeds. struct DeprecatedPriceFeedV2 { // The price ID. bytes32 id; // Latest available price DeprecatedPriceV2 price; // Latest available exponentially-weighted moving average price DeprecatedPriceV2 emaPrice; } struct DeprecatedPriceInfoV2 { uint256 attestationTime; uint256 arrivalTime; uint256 arrivalBlock; DeprecatedPriceFeedV2 priceFeed; } } contract PythStorage { struct State { address wormhole; uint16 _deprecatedPyth2WormholeChainId; // Replaced by validDataSources/isValidDataSource bytes32 _deprecatedPyth2WormholeEmitter; // Ditto // After a backward-incompatible change in PriceFeed this mapping got deprecated. mapping(bytes32 => PythDeprecatedStructs.DeprecatedPriceInfoV1) _deprecatedLatestPriceInfoV1; // For tracking all active emitter/chain ID pairs PythInternalStructs.DataSource[] validDataSources; // (chainId, emitterAddress) => isValid; takes advantage of // constant-time mapping lookup for VM verification mapping(bytes32 => bool) isValidDataSource; uint singleUpdateFeeInWei; /// Maximum acceptable time period before price is considered to be stale. /// This includes attestation delay, block time, and potential clock drift /// between the source/target chains. uint validTimePeriodSeconds; // Governance data source. VAA messages from this source can change this contract // state. e.g., upgrade the contract, change the valid data sources, and more. PythInternalStructs.DataSource governanceDataSource; // Sequence number of the last executed governance message. Any governance message // with a lower or equal sequence number will be discarded. This prevents double-execution, // and also makes sure that messages are executed in the right order. uint64 lastExecutedGovernanceSequence; // After a backward-incompatible change in PriceFeed this mapping got deprecated. mapping(bytes32 => PythDeprecatedStructs.DeprecatedPriceInfoV2) _deprecatedLatestPriceInfoV2; // Index of the governance data source, increased each time the governance data source // changes. uint32 governanceDataSourceIndex; // Mapping of cached price information // priceId => PriceInfo mapping(bytes32 => PythInternalStructs.PriceInfo) latestPriceInfo; } } contract PythState { PythStorage.State _state; } contract PythGetters is PythState { function wormhole() public view returns (IWormhole) { return IWormhole(_state.wormhole); } function latestPriceInfo( bytes32 priceId ) internal view returns (PythInternalStructs.PriceInfo memory info) { return _state.latestPriceInfo[priceId]; } function latestPriceInfoPublishTime( bytes32 priceId ) public view returns (uint64) { return _state.latestPriceInfo[priceId].publishTime; } function hashDataSource( PythInternalStructs.DataSource memory ds ) public pure returns (bytes32) { return keccak256(abi.encodePacked(ds.chainId, ds.emitterAddress)); } function isValidDataSource( uint16 dataSourceChainId, bytes32 dataSourceEmitterAddress ) public view returns (bool) { return _state.isValidDataSource[ keccak256( abi.encodePacked( dataSourceChainId, dataSourceEmitterAddress ) ) ]; } function isValidGovernanceDataSource( uint16 governanceChainId, bytes32 governanceEmitterAddress ) public view returns (bool) { return _state.governanceDataSource.chainId == governanceChainId && _state.governanceDataSource.emitterAddress == governanceEmitterAddress; } function chainId() public view returns (uint16) { return wormhole().chainId(); } function lastExecutedGovernanceSequence() public view returns (uint64) { return _state.lastExecutedGovernanceSequence; } function validDataSources() public view returns (PythInternalStructs.DataSource[] memory) { return _state.validDataSources; } function governanceDataSource() public view returns (PythInternalStructs.DataSource memory) { return _state.governanceDataSource; } function singleUpdateFeeInWei() public view returns (uint) { return _state.singleUpdateFeeInWei; } function validTimePeriodSeconds() public view returns (uint) { return _state.validTimePeriodSeconds; } function governanceDataSourceIndex() public view returns (uint32) { return _state.governanceDataSourceIndex; } } contract PythSetters is PythState { function setWormhole(address wh) internal { _state.wormhole = payable(wh); } function setLatestPriceInfo( bytes32 priceId, PythInternalStructs.PriceInfo memory info ) internal { _state.latestPriceInfo[priceId] = info; } function setSingleUpdateFeeInWei(uint fee) internal { _state.singleUpdateFeeInWei = fee; } function setValidTimePeriodSeconds(uint validTimePeriodSeconds) internal { _state.validTimePeriodSeconds = validTimePeriodSeconds; } function setGovernanceDataSource( PythInternalStructs.DataSource memory newDataSource ) internal { _state.governanceDataSource = newDataSource; } function setLastExecutedGovernanceSequence(uint64 sequence) internal { _state.lastExecutedGovernanceSequence = sequence; } function setGovernanceDataSourceIndex(uint32 newIndex) internal { _state.governanceDataSourceIndex = newIndex; } } /** * @dev This library provides methods to construct and verify Merkle Tree proofs efficiently. * */ library MerkleTree { uint8 constant MERKLE_LEAF_PREFIX = 0; uint8 constant MERKLE_NODE_PREFIX = 1; uint8 constant MERKLE_EMPTY_LEAF_PREFIX = 2; function hash(bytes memory input) internal pure returns (bytes20) { return bytes20(keccak256(input)); } function emptyLeafHash() internal pure returns (bytes20) { return hash(abi.encodePacked(MERKLE_EMPTY_LEAF_PREFIX)); } function leafHash(bytes memory data) internal pure returns (bytes20) { return hash(abi.encodePacked(MERKLE_LEAF_PREFIX, data)); } function nodeHash( bytes20 childA, bytes20 childB ) internal pure returns (bytes20) { if (childA > childB) { (childA, childB) = (childB, childA); } return hash(abi.encodePacked(MERKLE_NODE_PREFIX, childA, childB)); } /// @notice Verify Merkle Tree proof for given leaf data based on data on memory. /// @dev To optimize gas usage, this method doesn't take the proof as a bytes array /// but rather takes the encoded proof and the offset of the proof in the /// encoded proof array possibly containing multiple proofs. Also, the method /// does not perform any check on the boundry of the `encodedProof` and the /// `proofOffset` parameters. It is the caller's responsibility to ensure /// that the `encodedProof` is long enough to contain the proof and the /// `proofOffset` is not out of bound. function isProofValid( bytes calldata encodedProof, uint proofOffset, bytes20 root, bytes calldata leafData ) internal pure returns (bool valid, uint endOffset) { unchecked { bytes20 currentDigest = MerkleTree.leafHash(leafData); uint8 proofSize = UnsafeCalldataBytesLib.toUint8( encodedProof, proofOffset ); proofOffset += 1; for (uint i = 0; i < proofSize; i++) { bytes20 siblingDigest = bytes20( UnsafeCalldataBytesLib.toAddress(encodedProof, proofOffset) ); proofOffset += 20; currentDigest = MerkleTree.nodeHash( currentDigest, siblingDigest ); } valid = currentDigest == root; endOffset = proofOffset; } } /// @notice Construct Merkle Tree proofs for given list of messages. /// @dev This function is only used for testing purposes and is not efficient /// for production use-cases. /// /// This method creates a merkle tree with leaf size of (2^depth) with the /// messages as leafs (in the same given order) and returns the root digest /// and the proofs for each message. If the number of messages is not a power /// of 2, the tree is padded with empty messages. function constructProofs( bytes[] memory messages, uint8 depth ) internal pure returns (bytes20 root, bytes[] memory proofs) { require((1 << depth) >= messages.length, "depth too small"); bytes20[] memory tree = new bytes20[]((1 << (depth + 1))); // The tree is structured as follows: // 1 // 2 3 // 4 5 6 7 // ... // In this structure the parent of node x is x//2 and the children // of node x are x*2 and x*2 + 1. Also, the sibling of the node x // is x^1. The root is at index 1 and index 0 is not used. // Filling the leaf hashes bytes20 cachedEmptyLeafHash = emptyLeafHash(); for (uint i = 0; i < (1 << depth); i++) { if (i < messages.length) { tree[(1 << depth) + i] = leafHash(messages[i]); } else { tree[(1 << depth) + i] = cachedEmptyLeafHash; } } // Filling the node hashes from bottom to top for (uint k = depth; k > 0; k--) { uint level = k - 1; uint levelNumNodes = (1 << level); for (uint i = 0; i < levelNumNodes; i++) { uint id = (1 << level) + i; tree[id] = nodeHash(tree[id * 2], tree[id * 2 + 1]); } } root = tree[1]; proofs = new bytes[](messages.length); for (uint i = 0; i < messages.length; i++) { // depth is the number of sibling nodes in the path from the leaf to the root proofs[i] = abi.encodePacked(depth); uint idx = (1 << depth) + i; // This loop iterates through the leaf and its parents // and keeps adding the sibling of the current node to the proof. while (idx > 1) { proofs[i] = abi.encodePacked( proofs[i], tree[idx ^ 1] // Sibling of this node ); // Jump to parent idx /= 2; } } } } abstract contract PythAccumulator is PythGetters, PythSetters, AbstractPyth { uint32 constant ACCUMULATOR_MAGIC = 0x504e4155; // Stands for PNAU (Pyth Network Accumulator Update) uint32 constant ACCUMULATOR_WORMHOLE_MAGIC = 0x41555756; // Stands for AUWV (Accumulator Update Wormhole Verficiation) uint8 constant MINIMUM_ALLOWED_MINOR_VERSION = 0; uint8 constant MAJOR_VERSION = 1; enum UpdateType { WormholeMerkle } enum MessageType { PriceFeed } // This method is also used by batch attestation but moved here // as the batch attestation will deprecate soon. function parseAndVerifyPythVM( bytes calldata encodedVm ) internal view returns (IWormhole.VM memory vm) { { bool valid; (vm, valid, ) = wormhole().parseAndVerifyVM(encodedVm); if (!valid) revert PythErrors.InvalidWormholeVaa(); } if (!isValidDataSource(vm.emitterChainId, vm.emitterAddress)) revert PythErrors.InvalidUpdateDataSource(); } function extractUpdateTypeFromAccumulatorHeader( bytes calldata accumulatorUpdate ) internal pure returns (uint offset, UpdateType updateType) { unchecked { offset = 0; { uint32 magic = UnsafeCalldataBytesLib.toUint32( accumulatorUpdate, offset ); offset += 4; if (magic != ACCUMULATOR_MAGIC) revert PythErrors.InvalidUpdateData(); uint8 majorVersion = UnsafeCalldataBytesLib.toUint8( accumulatorUpdate, offset ); offset += 1; if (majorVersion != MAJOR_VERSION) revert PythErrors.InvalidUpdateData(); uint8 minorVersion = UnsafeCalldataBytesLib.toUint8( accumulatorUpdate, offset ); offset += 1; // Minor versions are forward compatible, so we only check // that the minor version is not less than the minimum allowed if (minorVersion < MINIMUM_ALLOWED_MINOR_VERSION) revert PythErrors.InvalidUpdateData(); // This field ensure that we can add headers in the future // without breaking the contract (future compatibility) uint8 trailingHeaderSize = UnsafeCalldataBytesLib.toUint8( accumulatorUpdate, offset ); offset += 1; // We use another offset for the trailing header and in the end add the // offset by trailingHeaderSize to skip the future headers. // // An example would be like this: // uint trailingHeaderOffset = offset // uint x = UnsafeBytesLib.ToUint8(accumulatorUpdate, trailingHeaderOffset) // trailingHeaderOffset += 1 offset += trailingHeaderSize; } updateType = UpdateType( UnsafeCalldataBytesLib.toUint8(accumulatorUpdate, offset) ); offset += 1; if (accumulatorUpdate.length < offset) revert PythErrors.InvalidUpdateData(); } } function extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedFromAccumulatorUpdate( bytes calldata accumulatorUpdate, uint encodedOffset ) internal view returns ( uint offset, bytes20 digest, uint8 numUpdates, bytes calldata encoded ) { unchecked { encoded = UnsafeCalldataBytesLib.slice( accumulatorUpdate, encodedOffset, accumulatorUpdate.length - encodedOffset ); offset = 0; uint16 whProofSize = UnsafeCalldataBytesLib.toUint16( encoded, offset ); offset += 2; { bytes memory encodedPayload; { IWormhole.VM memory vm = parseAndVerifyPythVM( UnsafeCalldataBytesLib.slice( encoded, offset, whProofSize ) ); offset += whProofSize; // TODO: Do we need to emit an update for accumulator update? If so what should we emit? // emit AccumulatorUpdate(vm.chainId, vm.sequence); encodedPayload = vm.payload; } uint payloadOffset = 0; { uint32 magic = UnsafeBytesLib.toUint32( encodedPayload, payloadOffset ); payloadOffset += 4; if (magic != ACCUMULATOR_WORMHOLE_MAGIC) revert PythErrors.InvalidUpdateData(); UpdateType updateType = UpdateType( UnsafeBytesLib.toUint8(encodedPayload, payloadOffset) ); ++payloadOffset; if (updateType != UpdateType.WormholeMerkle) revert PythErrors.InvalidUpdateData(); // This field is not used // uint64 slot = UnsafeBytesLib.toUint64(encodedPayload, payloadoffset); payloadOffset += 8; // This field is not used // uint32 ringSize = UnsafeBytesLib.toUint32(encodedPayload, payloadoffset); payloadOffset += 4; digest = bytes20( UnsafeBytesLib.toAddress(encodedPayload, payloadOffset) ); payloadOffset += 20; // We don't check equality to enable future compatibility. if (payloadOffset > encodedPayload.length) revert PythErrors.InvalidUpdateData(); } } numUpdates = UnsafeCalldataBytesLib.toUint8(encoded, offset); offset += 1; } } function parseWormholeMerkleHeaderNumUpdates( bytes calldata wormholeMerkleUpdate, uint offset ) internal pure returns (uint8 numUpdates) { uint16 whProofSize = UnsafeCalldataBytesLib.toUint16( wormholeMerkleUpdate, offset ); offset += 2; offset += whProofSize; numUpdates = UnsafeCalldataBytesLib.toUint8( wormholeMerkleUpdate, offset ); } function extractPriceInfoFromMerkleProof( bytes20 digest, bytes calldata encoded, uint offset ) internal pure returns ( uint endOffset, PythInternalStructs.PriceInfo memory priceInfo, bytes32 priceId ) { unchecked { bytes calldata encodedMessage; uint16 messageSize = UnsafeCalldataBytesLib.toUint16( encoded, offset ); offset += 2; encodedMessage = UnsafeCalldataBytesLib.slice( encoded, offset, messageSize ); offset += messageSize; bool valid; (valid, endOffset) = MerkleTree.isProofValid( encoded, offset, digest, encodedMessage ); if (!valid) { revert PythErrors.InvalidUpdateData(); } MessageType messageType = MessageType( UnsafeCalldataBytesLib.toUint8(encodedMessage, 0) ); if (messageType == MessageType.PriceFeed) { (priceInfo, priceId) = parsePriceFeedMessage(encodedMessage, 1); } else { revert PythErrors.InvalidUpdateData(); } return (endOffset, priceInfo, priceId); } } function parsePriceFeedMessage( bytes calldata encodedPriceFeed, uint offset ) private pure returns ( PythInternalStructs.PriceInfo memory priceInfo, bytes32 priceId ) { unchecked { priceId = UnsafeCalldataBytesLib.toBytes32( encodedPriceFeed, offset ); offset += 32; priceInfo.price = int64( UnsafeCalldataBytesLib.toUint64(encodedPriceFeed, offset) ); offset += 8; priceInfo.conf = UnsafeCalldataBytesLib.toUint64( encodedPriceFeed, offset ); offset += 8; priceInfo.expo = int32( UnsafeCalldataBytesLib.toUint32(encodedPriceFeed, offset) ); offset += 4; // Publish time is i64 in some environments due to the standard in that // environment. This would not cause any problem because since the signed // integer is represented in two's complement, the value would be the same // in both cases (for a million year at least) priceInfo.publishTime = UnsafeCalldataBytesLib.toUint64( encodedPriceFeed, offset ); offset += 8; // We do not store this field because it is not used on the latest feed queries. // uint64 prevPublishTime = UnsafeBytesLib.toUint64(encodedPriceFeed, offset); offset += 8; priceInfo.emaPrice = int64( UnsafeCalldataBytesLib.toUint64(encodedPriceFeed, offset) ); offset += 8; priceInfo.emaConf = UnsafeCalldataBytesLib.toUint64( encodedPriceFeed, offset ); offset += 8; if (offset > encodedPriceFeed.length) revert PythErrors.InvalidUpdateData(); } } function updatePriceInfosFromAccumulatorUpdate( bytes calldata accumulatorUpdate ) internal returns (uint8 numUpdates) { ( uint encodedOffset, UpdateType updateType ) = extractUpdateTypeFromAccumulatorHeader(accumulatorUpdate); if (updateType != UpdateType.WormholeMerkle) { revert PythErrors.InvalidUpdateData(); } uint offset; bytes20 digest; bytes calldata encoded; ( offset, digest, numUpdates, encoded ) = extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedFromAccumulatorUpdate( accumulatorUpdate, encodedOffset ); unchecked { for (uint i = 0; i < numUpdates; i++) { PythInternalStructs.PriceInfo memory priceInfo; bytes32 priceId; (offset, priceInfo, priceId) = extractPriceInfoFromMerkleProof( digest, encoded, offset ); uint64 latestPublishTime = latestPriceInfoPublishTime(priceId); if (priceInfo.publishTime > latestPublishTime) { setLatestPriceInfo(priceId, priceInfo); emit PriceFeedUpdate( priceId, priceInfo.publishTime, priceInfo.price, priceInfo.conf ); } } } if (offset != encoded.length) revert PythErrors.InvalidUpdateData(); } } abstract contract Pyth is PythGetters, PythSetters, AbstractPyth, PythAccumulator { function _initialize( address wormhole, uint16[] calldata dataSourceEmitterChainIds, bytes32[] calldata dataSourceEmitterAddresses, uint16 governanceEmitterChainId, bytes32 governanceEmitterAddress, uint64 governanceInitialSequence, uint validTimePeriodSeconds, uint singleUpdateFeeInWei ) internal { setWormhole(wormhole); if ( dataSourceEmitterChainIds.length != dataSourceEmitterAddresses.length ) revert PythErrors.InvalidArgument(); for (uint i = 0; i < dataSourceEmitterChainIds.length; i++) { PythInternalStructs.DataSource memory ds = PythInternalStructs .DataSource( dataSourceEmitterChainIds[i], dataSourceEmitterAddresses[i] ); if (PythGetters.isValidDataSource(ds.chainId, ds.emitterAddress)) revert PythErrors.InvalidArgument(); _state.isValidDataSource[hashDataSource(ds)] = true; _state.validDataSources.push(ds); } { PythInternalStructs.DataSource memory ds = PythInternalStructs .DataSource(governanceEmitterChainId, governanceEmitterAddress); PythSetters.setGovernanceDataSource(ds); PythSetters.setLastExecutedGovernanceSequence( governanceInitialSequence ); } PythSetters.setValidTimePeriodSeconds(validTimePeriodSeconds); PythSetters.setSingleUpdateFeeInWei(singleUpdateFeeInWei); } function updatePriceBatchFromVm(bytes calldata encodedVm) private { parseAndProcessBatchPriceAttestation( parseAndVerifyBatchAttestationVM(encodedVm) ); } function updatePriceFeeds( bytes[] calldata updateData ) public payable override { uint totalNumUpdates = 0; for (uint i = 0; i < updateData.length; ) { if ( updateData[i].length > 4 && UnsafeCalldataBytesLib.toUint32(updateData[i], 0) == ACCUMULATOR_MAGIC ) { totalNumUpdates += updatePriceInfosFromAccumulatorUpdate( updateData[i] ); } else { updatePriceBatchFromVm(updateData[i]); totalNumUpdates += 1; } unchecked { i++; } } uint requiredFee = getTotalFee(totalNumUpdates); if (msg.value < requiredFee) revert PythErrors.InsufficientFee(); } /// This method is deprecated, please use the `getUpdateFee(bytes[])` instead. function getUpdateFee( uint updateDataSize ) public view returns (uint feeAmount) { return singleUpdateFeeInWei() * updateDataSize; } function getUpdateFee( bytes[] calldata updateData ) public view override returns (uint feeAmount) { uint totalNumUpdates = 0; for (uint i = 0; i < updateData.length; i++) { if ( updateData[i].length > 4 && UnsafeCalldataBytesLib.toUint32(updateData[i], 0) == ACCUMULATOR_MAGIC ) { ( uint offset, UpdateType updateType ) = extractUpdateTypeFromAccumulatorHeader(updateData[i]); if (updateType != UpdateType.WormholeMerkle) { revert PythErrors.InvalidUpdateData(); } totalNumUpdates += parseWormholeMerkleHeaderNumUpdates( updateData[i], offset ); } else { totalNumUpdates += 1; } } return getTotalFee(totalNumUpdates); } function verifyPythVM( IWormhole.VM memory vm ) private view returns (bool valid) { return isValidDataSource(vm.emitterChainId, vm.emitterAddress); } function parseAndProcessBatchPriceAttestation( IWormhole.VM memory vm ) internal { // Most of the math operations below are simple additions. // In the places that there is more complex operation there is // a comment explaining why it is safe. Also, byteslib // operations have proper require. unchecked { bytes memory encoded = vm.payload; ( uint index, uint nAttestations, uint attestationSize ) = parseBatchAttestationHeader(encoded); // Deserialize each attestation for (uint j = 0; j < nAttestations; j++) { ( PythInternalStructs.PriceInfo memory info, bytes32 priceId ) = parseSingleAttestationFromBatch( encoded, index, attestationSize ); // Respect specified attestation size for forward-compat index += attestationSize; // Store the attestation uint64 latestPublishTime = latestPriceInfoPublishTime(priceId); if (info.publishTime > latestPublishTime) { setLatestPriceInfo(priceId, info); emit PriceFeedUpdate( priceId, info.publishTime, info.price, info.conf ); } } emit BatchPriceFeedUpdate(vm.emitterChainId, vm.sequence); } } function parseSingleAttestationFromBatch( bytes memory encoded, uint index, uint attestationSize ) internal pure returns (PythInternalStructs.PriceInfo memory info, bytes32 priceId) { unchecked { // NOTE: We don't advance the global index immediately. // attestationIndex is an attestation-local offset used // for readability and easier debugging. uint attestationIndex = 0; // Unused bytes32 product id attestationIndex += 32; priceId = UnsafeBytesLib.toBytes32( encoded, index + attestationIndex ); attestationIndex += 32; info.price = int64( UnsafeBytesLib.toUint64(encoded, index + attestationIndex) ); attestationIndex += 8; info.conf = UnsafeBytesLib.toUint64( encoded, index + attestationIndex ); attestationIndex += 8; info.expo = int32( UnsafeBytesLib.toUint32(encoded, index + attestationIndex) ); attestationIndex += 4; info.emaPrice = int64( UnsafeBytesLib.toUint64(encoded, index + attestationIndex) ); attestationIndex += 8; info.emaConf = UnsafeBytesLib.toUint64( encoded, index + attestationIndex ); attestationIndex += 8; { // Status is an enum (encoded as uint8) with the following values: // 0 = UNKNOWN: The price feed is not currently updating for an unknown reason. // 1 = TRADING: The price feed is updating as expected. // 2 = HALTED: The price feed is not currently updating because trading in the product has been halted. // 3 = AUCTION: The price feed is not currently updating because an auction is setting the price. uint8 status = UnsafeBytesLib.toUint8( encoded, index + attestationIndex ); attestationIndex += 1; // Unused uint32 numPublishers attestationIndex += 4; // Unused uint32 numPublishers attestationIndex += 4; // Unused uint64 attestationTime attestationIndex += 8; info.publishTime = UnsafeBytesLib.toUint64( encoded, index + attestationIndex ); attestationIndex += 8; if (status == 1) { // status == TRADING attestationIndex += 24; } else { // If status is not trading then the latest available price is // the previous price info that are passed here. // Previous publish time info.publishTime = UnsafeBytesLib.toUint64( encoded, index + attestationIndex ); attestationIndex += 8; // Previous price info.price = int64( UnsafeBytesLib.toUint64( encoded, index + attestationIndex ) ); attestationIndex += 8; // Previous confidence info.conf = UnsafeBytesLib.toUint64( encoded, index + attestationIndex ); attestationIndex += 8; } } if (attestationIndex > attestationSize) revert PythErrors.InvalidUpdateData(); } } // This is an overwrite of the same method in AbstractPyth.sol // to be more gas efficient. function updatePriceFeedsIfNecessary( bytes[] calldata updateData, bytes32[] calldata priceIds, uint64[] calldata publishTimes ) external payable override { if (priceIds.length != publishTimes.length) revert PythErrors.InvalidArgument(); for (uint i = 0; i < priceIds.length; ) { // If the price does not exist, then the publish time is zero and // this condition will work fine. if (latestPriceInfoPublishTime(priceIds[i]) < publishTimes[i]) { updatePriceFeeds(updateData); return; } unchecked { i++; } } revert PythErrors.NoFreshUpdate(); } // This is an overwrite of the same method in AbstractPyth.sol // to be more gas efficient. It cannot move to PythGetters as it // is overwriting the interface. Even indirect calling of a similar // method from PythGetter has some gas overhead. function getPriceUnsafe( bytes32 id ) public view override returns (PythStructs.Price memory price) { PythInternalStructs.PriceInfo storage info = _state.latestPriceInfo[id]; price.publishTime = info.publishTime; price.expo = info.expo; price.price = info.price; price.conf = info.conf; if (price.publishTime == 0) revert PythErrors.PriceFeedNotFound(); } // This is an overwrite of the same method in AbstractPyth.sol // to be more gas efficient. It cannot move to PythGetters as it // is overwriting the interface. Even indirect calling of a similar // method from PythGetter has some gas overhead. function getEmaPriceUnsafe( bytes32 id ) public view override returns (PythStructs.Price memory price) { PythInternalStructs.PriceInfo storage info = _state.latestPriceInfo[id]; price.publishTime = info.publishTime; price.expo = info.expo; price.price = info.emaPrice; price.conf = info.emaConf; if (price.publishTime == 0) revert PythErrors.PriceFeedNotFound(); } function parseBatchAttestationHeader( bytes memory encoded ) internal pure returns (uint index, uint nAttestations, uint attestationSize) { unchecked { index = 0; // Check header { uint32 magic = UnsafeBytesLib.toUint32(encoded, index); index += 4; if (magic != 0x50325748) revert PythErrors.InvalidUpdateData(); uint16 versionMajor = UnsafeBytesLib.toUint16(encoded, index); index += 2; if (versionMajor != 3) revert PythErrors.InvalidUpdateData(); // This value is only used as the check below which currently // never reverts // uint16 versionMinor = UnsafeBytesLib.toUint16(encoded, index); index += 2; // This check is always false as versionMinor is 0, so it is commented. // in the future that the minor version increases this will have effect. // if(versionMinor < 0) revert InvalidUpdateData(); uint16 hdrSize = UnsafeBytesLib.toUint16(encoded, index); index += 2; // NOTE(2022-04-19): Currently, only payloadId comes after // hdrSize. Future extra header fields must be read using a // separate offset to respect hdrSize, i.e.: // // uint hdrIndex = 0; // bpa.header.payloadId = UnsafeBytesLib.toUint8(encoded, index + hdrIndex); // hdrIndex += 1; // // bpa.header.someNewField = UnsafeBytesLib.toUint32(encoded, index + hdrIndex); // hdrIndex += 4; // // // Skip remaining unknown header bytes // index += bpa.header.hdrSize; uint8 payloadId = UnsafeBytesLib.toUint8(encoded, index); // Skip remaining unknown header bytes index += hdrSize; // Payload ID of 2 required for batch headerBa if (payloadId != 2) revert PythErrors.InvalidUpdateData(); } // Parse the number of attestations nAttestations = UnsafeBytesLib.toUint16(encoded, index); index += 2; // Parse the attestation size attestationSize = UnsafeBytesLib.toUint16(encoded, index); index += 2; // Given the message is valid the arithmetic below should not overflow, and // even if it overflows then the require would fail. if (encoded.length != (index + (attestationSize * nAttestations))) revert PythErrors.InvalidUpdateData(); } } function parseAndVerifyBatchAttestationVM( bytes calldata encodedVm ) internal view returns (IWormhole.VM memory vm) { { bool valid; (vm, valid, ) = wormhole().parseAndVerifyVM(encodedVm); if (!valid) revert PythErrors.InvalidWormholeVaa(); } if (!verifyPythVM(vm)) revert PythErrors.InvalidUpdateDataSource(); } function parsePriceFeedUpdates( bytes[] calldata updateData, bytes32[] calldata priceIds, uint64 minPublishTime, uint64 maxPublishTime ) external payable override returns (PythStructs.PriceFeed[] memory priceFeeds) { { uint requiredFee = getUpdateFee(updateData); if (msg.value < requiredFee) revert PythErrors.InsufficientFee(); } unchecked { priceFeeds = new PythStructs.PriceFeed[](priceIds.length); for (uint i = 0; i < updateData.length; i++) { if ( updateData[i].length > 4 && UnsafeCalldataBytesLib.toUint32(updateData[i], 0) == ACCUMULATOR_MAGIC ) { uint offset; { UpdateType updateType; ( offset, updateType ) = extractUpdateTypeFromAccumulatorHeader( updateData[i] ); if (updateType != UpdateType.WormholeMerkle) { revert PythErrors.InvalidUpdateData(); } } bytes20 digest; uint8 numUpdates; bytes calldata encoded; ( offset, digest, numUpdates, encoded ) = extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedFromAccumulatorUpdate( updateData[i], offset ); for (uint j = 0; j < numUpdates; j++) { PythInternalStructs.PriceInfo memory info; bytes32 priceId; ( offset, info, priceId ) = extractPriceInfoFromMerkleProof( digest, encoded, offset ); { // check whether caller requested for this data uint k = findIndexOfPriceId(priceIds, priceId); // If priceFeed[k].id != 0 then it means that there was a valid // update for priceIds[k] and we don't need to process this one. if (k == priceIds.length || priceFeeds[k].id != 0) { continue; } uint publishTime = uint(info.publishTime); // Check the publish time of the price is within the given range // and only fill the priceFeedsInfo if it is. // If is not, default id value of 0 will still be set and // this will allow other updates for this price id to be processed. if ( publishTime >= minPublishTime && publishTime <= maxPublishTime ) { fillPriceFeedFromPriceInfo( priceFeeds, k, priceId, info, publishTime ); } } } if (offset != encoded.length) revert PythErrors.InvalidUpdateData(); } else { bytes memory encoded; { IWormhole.VM memory vm = parseAndVerifyBatchAttestationVM( updateData[i] ); encoded = vm.payload; } /** Batch price logic */ // TODO: gas optimization ( uint index, uint nAttestations, uint attestationSize ) = parseBatchAttestationHeader(encoded); // Deserialize each attestation for (uint j = 0; j < nAttestations; j++) { // NOTE: We don't advance the global index immediately. // attestationIndex is an attestation-local offset used // for readability and easier debugging. uint attestationIndex = 0; // Unused bytes32 product id attestationIndex += 32; bytes32 priceId = UnsafeBytesLib.toBytes32( encoded, index + attestationIndex ); // check whether caller requested for this data uint k = findIndexOfPriceId(priceIds, priceId); // If priceFeed[k].id != 0 then it means that there was a valid // update for priceIds[k] and we don't need to process this one. if (k == priceIds.length || priceFeeds[k].id != 0) { index += attestationSize; continue; } ( PythInternalStructs.PriceInfo memory info, ) = parseSingleAttestationFromBatch( encoded, index, attestationSize ); uint publishTime = uint(info.publishTime); // Check the publish time of the price is within the given range // and only fill the priceFeedsInfo if it is. // If is not, default id value of 0 will still be set and // this will allow other updates for this price id to be processed. if ( publishTime >= minPublishTime && publishTime <= maxPublishTime ) { fillPriceFeedFromPriceInfo( priceFeeds, k, priceId, info, publishTime ); } index += attestationSize; } } } for (uint k = 0; k < priceIds.length; k++) { if (priceFeeds[k].id == 0) { revert PythErrors.PriceFeedNotFoundWithinRange(); } } } } function getTotalFee( uint totalNumUpdates ) private view returns (uint requiredFee) { return totalNumUpdates * singleUpdateFeeInWei(); } function findIndexOfPriceId( bytes32[] calldata priceIds, bytes32 targetPriceId ) private pure returns (uint index) { uint k = 0; for (; k < priceIds.length; k++) { if (priceIds[k] == targetPriceId) { break; } } return k; } function fillPriceFeedFromPriceInfo( PythStructs.PriceFeed[] memory priceFeeds, uint k, bytes32 priceId, PythInternalStructs.PriceInfo memory info, uint publishTime ) private pure { priceFeeds[k].id = priceId; priceFeeds[k].price.price = info.price; priceFeeds[k].price.conf = info.conf; priceFeeds[k].price.expo = info.expo; priceFeeds[k].price.publishTime = publishTime; priceFeeds[k].emaPrice.price = info.emaPrice; priceFeeds[k].emaPrice.conf = info.emaConf; priceFeeds[k].emaPrice.expo = info.expo; priceFeeds[k].emaPrice.publishTime = publishTime; } function queryPriceFeed( bytes32 id ) public view override returns (PythStructs.PriceFeed memory priceFeed) { // Look up the latest price info for the given ID PythInternalStructs.PriceInfo memory info = latestPriceInfo(id); if (info.publishTime == 0) revert PythErrors.PriceFeedNotFound(); priceFeed.id = id; priceFeed.price.price = info.price; priceFeed.price.conf = info.conf; priceFeed.price.expo = info.expo; priceFeed.price.publishTime = uint(info.publishTime); priceFeed.emaPrice.price = info.emaPrice; priceFeed.emaPrice.conf = info.emaConf; priceFeed.emaPrice.expo = info.expo; priceFeed.emaPrice.publishTime = uint(info.publishTime); } function priceFeedExists(bytes32 id) public view override returns (bool) { return (latestPriceInfoPublishTime(id) != 0); } function getValidTimePeriod() public view override returns (uint) { return validTimePeriodSeconds(); } function version() public pure returns (string memory) { return "1.3.0"; } } /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } } /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822ProxiableUpgradeable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); } /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); } /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } } /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967UpgradeUpgradeable is Initializable { function __ERC1967Upgrade_init() internal onlyInitializing { } function __ERC1967Upgrade_init_unchained() internal onlyInitializing { } // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { _functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) { require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed"); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable { function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeTo(address newImplementation) external virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; } /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; } /** * @dev `PythGovernanceInstructions` defines a set of structs and parsing functions * for Pyth governance instructions. */ contract PythGovernanceInstructions { using BytesLib for bytes; // Magic is `PTGM` encoded as a 4 byte data: Pyth Governance Message uint32 constant MAGIC = 0x5054474d; enum GovernanceModule { Executor, // 0 Target // 1 } GovernanceModule constant MODULE = GovernanceModule.Target; enum GovernanceAction { UpgradeContract, // 0 AuthorizeGovernanceDataSourceTransfer, // 1 SetDataSources, // 2 SetFee, // 3 SetValidPeriod, // 4 RequestGovernanceDataSourceTransfer, // 5 SetWormholeAddress // 6 } struct GovernanceInstruction { GovernanceModule module; GovernanceAction action; uint16 targetChainId; bytes payload; } struct UpgradeContractPayload { address newImplementation; } struct AuthorizeGovernanceDataSourceTransferPayload { // Transfer governance control over this contract to another data source. // The claimVaa field is a VAA created by the new data source; using a VAA prevents mistakes // in the handoff by ensuring that the new data source can send VAAs (i.e., is not an invalid address). bytes claimVaa; } struct RequestGovernanceDataSourceTransferPayload { // Governance data source index is used to prevent replay attacks // So a claimVaa cannot be used twice. uint32 governanceDataSourceIndex; } struct SetDataSourcesPayload { PythInternalStructs.DataSource[] dataSources; } struct SetFeePayload { uint newFee; } struct SetValidPeriodPayload { uint newValidPeriod; } struct SetWormholeAddressPayload { address newWormholeAddress; } /// @dev Parse a GovernanceInstruction function parseGovernanceInstruction( bytes memory encodedInstruction ) public pure returns (GovernanceInstruction memory gi) { uint index = 0; uint32 magic = encodedInstruction.toUint32(index); if (magic != MAGIC) revert PythErrors.InvalidGovernanceMessage(); index += 4; uint8 modNumber = encodedInstruction.toUint8(index); gi.module = GovernanceModule(modNumber); index += 1; if (gi.module != MODULE) revert PythErrors.InvalidGovernanceTarget(); uint8 actionNumber = encodedInstruction.toUint8(index); gi.action = GovernanceAction(actionNumber); index += 1; gi.targetChainId = encodedInstruction.toUint16(index); index += 2; // As solidity performs math operations in a checked mode // if the length of the encoded instruction be smaller than index // it will revert. So we don't need any extra check. gi.payload = encodedInstruction.slice( index, encodedInstruction.length - index ); } /// @dev Parse a UpgradeContractPayload (action 1) with minimal validation function parseUpgradeContractPayload( bytes memory encodedPayload ) public pure returns (UpgradeContractPayload memory uc) { uint index = 0; uc.newImplementation = address(encodedPayload.toAddress(index)); index += 20; if (encodedPayload.length != index) revert PythErrors.InvalidGovernanceMessage(); } /// @dev Parse a AuthorizeGovernanceDataSourceTransferPayload (action 2) with minimal validation function parseAuthorizeGovernanceDataSourceTransferPayload( bytes memory encodedPayload ) public pure returns (AuthorizeGovernanceDataSourceTransferPayload memory sgds) { sgds.claimVaa = encodedPayload; } /// @dev Parse a AuthorizeGovernanceDataSourceTransferPayload (action 2) with minimal validation function parseRequestGovernanceDataSourceTransferPayload( bytes memory encodedPayload ) public pure returns (RequestGovernanceDataSourceTransferPayload memory sgdsClaim) { uint index = 0; sgdsClaim.governanceDataSourceIndex = encodedPayload.toUint32(index); index += 4; if (encodedPayload.length != index) revert PythErrors.InvalidGovernanceMessage(); } /// @dev Parse a SetDataSourcesPayload (action 3) with minimal validation function parseSetDataSourcesPayload( bytes memory encodedPayload ) public pure returns (SetDataSourcesPayload memory sds) { uint index = 0; uint8 dataSourcesLength = encodedPayload.toUint8(index); index += 1; sds.dataSources = new PythInternalStructs.DataSource[]( dataSourcesLength ); for (uint i = 0; i < dataSourcesLength; i++) { sds.dataSources[i].chainId = encodedPayload.toUint16(index); index += 2; sds.dataSources[i].emitterAddress = encodedPayload.toBytes32(index); index += 32; } if (encodedPayload.length != index) revert PythErrors.InvalidGovernanceMessage(); } /// @dev Parse a SetFeePayload (action 4) with minimal validation function parseSetFeePayload( bytes memory encodedPayload ) public pure returns (SetFeePayload memory sf) { uint index = 0; uint64 val = encodedPayload.toUint64(index); index += 8; uint64 expo = encodedPayload.toUint64(index); index += 8; sf.newFee = uint256(val) * uint256(10) ** uint256(expo); if (encodedPayload.length != index) revert PythErrors.InvalidGovernanceMessage(); } /// @dev Parse a SetValidPeriodPayload (action 5) with minimal validation function parseSetValidPeriodPayload( bytes memory encodedPayload ) public pure returns (SetValidPeriodPayload memory svp) { uint index = 0; svp.newValidPeriod = uint256(encodedPayload.toUint64(index)); index += 8; if (encodedPayload.length != index) revert PythErrors.InvalidGovernanceMessage(); } /// @dev Parse a UpdateWormholeAddressPayload (action 6) with minimal validation function parseSetWormholeAddressPayload( bytes memory encodedPayload ) public pure returns (SetWormholeAddressPayload memory sw) { uint index = 0; sw.newWormholeAddress = address(encodedPayload.toAddress(index)); index += 20; if (encodedPayload.length != index) revert PythErrors.InvalidGovernanceMessage(); } } /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); } /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); } /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } } /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967Upgrade { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS( address newImplementation, bytes memory data, bool forceCall ) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } } /** * @dev `Governance` defines a means to enacting changes to the Pyth contract. */ abstract contract PythGovernance is PythGetters, PythSetters, PythGovernanceInstructions { event ContractUpgraded( address oldImplementation, address newImplementation ); event GovernanceDataSourceSet( PythInternalStructs.DataSource oldDataSource, PythInternalStructs.DataSource newDataSource, uint64 initialSequence ); event DataSourcesSet( PythInternalStructs.DataSource[] oldDataSources, PythInternalStructs.DataSource[] newDataSources ); event FeeSet(uint oldFee, uint newFee); event ValidPeriodSet(uint oldValidPeriod, uint newValidPeriod); event WormholeAddressSet( address oldWormholeAddress, address newWormholeAddress ); function verifyGovernanceVM( bytes memory encodedVM ) internal returns (IWormhole.VM memory parsedVM) { (IWormhole.VM memory vm, bool valid, ) = wormhole().parseAndVerifyVM( encodedVM ); if (!valid) revert PythErrors.InvalidWormholeVaa(); if (!isValidGovernanceDataSource(vm.emitterChainId, vm.emitterAddress)) revert PythErrors.InvalidGovernanceDataSource(); if (vm.sequence <= lastExecutedGovernanceSequence()) revert PythErrors.OldGovernanceMessage(); setLastExecutedGovernanceSequence(vm.sequence); return vm; } function executeGovernanceInstruction(bytes calldata encodedVM) public { IWormhole.VM memory vm = verifyGovernanceVM(encodedVM); GovernanceInstruction memory gi = parseGovernanceInstruction( vm.payload ); if (gi.targetChainId != chainId() && gi.targetChainId != 0) revert PythErrors.InvalidGovernanceTarget(); if (gi.action == GovernanceAction.UpgradeContract) { if (gi.targetChainId == 0) revert PythErrors.InvalidGovernanceTarget(); upgradeContract(parseUpgradeContractPayload(gi.payload)); } else if ( gi.action == GovernanceAction.AuthorizeGovernanceDataSourceTransfer ) { AuthorizeGovernanceDataSourceTransfer( parseAuthorizeGovernanceDataSourceTransferPayload(gi.payload) ); } else if (gi.action == GovernanceAction.SetDataSources) { setDataSources(parseSetDataSourcesPayload(gi.payload)); } else if (gi.action == GovernanceAction.SetFee) { setFee(parseSetFeePayload(gi.payload)); } else if (gi.action == GovernanceAction.SetValidPeriod) { setValidPeriod(parseSetValidPeriodPayload(gi.payload)); } else if ( gi.action == GovernanceAction.RequestGovernanceDataSourceTransfer ) { // RequestGovernanceDataSourceTransfer can be only part of AuthorizeGovernanceDataSourceTransfer message revert PythErrors.InvalidGovernanceMessage(); } else if (gi.action == GovernanceAction.SetWormholeAddress) { if (gi.targetChainId == 0) revert PythErrors.InvalidGovernanceTarget(); setWormholeAddress( parseSetWormholeAddressPayload(gi.payload), encodedVM ); } else { revert PythErrors.InvalidGovernanceMessage(); } } function upgradeContract(UpgradeContractPayload memory payload) internal { // This method on this contract does not have enough access to execute this, it should be executed on the // upgradable contract. upgradeUpgradableContract(payload); } function upgradeUpgradableContract( UpgradeContractPayload memory payload ) internal virtual; // Transfer the governance data source to a new value with sanity checks // to ensure the new governance data source can manage the contract. function AuthorizeGovernanceDataSourceTransfer( AuthorizeGovernanceDataSourceTransferPayload memory payload ) internal { PythInternalStructs.DataSource memory oldGovernanceDatSource = governanceDataSource(); // Make sure the claimVaa is a valid VAA with RequestGovernanceDataSourceTransfer governance message // If it's valid then its emitter can take over the governance from the current emitter. // The VAA is checked here to ensure that the new governance data source is valid and can send message // through wormhole. (IWormhole.VM memory vm, bool valid, ) = wormhole().parseAndVerifyVM( payload.claimVaa ); if (!valid) revert PythErrors.InvalidWormholeVaa(); GovernanceInstruction memory gi = parseGovernanceInstruction( vm.payload ); if (gi.targetChainId != chainId() && gi.targetChainId != 0) revert PythErrors.InvalidGovernanceTarget(); if (gi.action != GovernanceAction.RequestGovernanceDataSourceTransfer) revert PythErrors.InvalidGovernanceMessage(); RequestGovernanceDataSourceTransferPayload memory claimPayload = parseRequestGovernanceDataSourceTransferPayload( gi.payload ); // Governance data source index is used to prevent replay attacks, so a claimVaa cannot be used twice. if ( governanceDataSourceIndex() >= claimPayload.governanceDataSourceIndex ) revert PythErrors.OldGovernanceMessage(); setGovernanceDataSourceIndex(claimPayload.governanceDataSourceIndex); PythInternalStructs.DataSource memory newGovernanceDS = PythInternalStructs.DataSource( vm.emitterChainId, vm.emitterAddress ); setGovernanceDataSource(newGovernanceDS); // Setting the last executed governance to the claimVaa sequence to avoid using older sequences. setLastExecutedGovernanceSequence(vm.sequence); emit GovernanceDataSourceSet( oldGovernanceDatSource, governanceDataSource(), lastExecutedGovernanceSequence() ); } function setDataSources(SetDataSourcesPayload memory payload) internal { PythInternalStructs.DataSource[] memory oldDataSources = validDataSources(); for (uint i = 0; i < oldDataSources.length; i += 1) { _state.isValidDataSource[hashDataSource(oldDataSources[i])] = false; } delete _state.validDataSources; for (uint i = 0; i < payload.dataSources.length; i++) { _state.validDataSources.push(payload.dataSources[i]); _state.isValidDataSource[ hashDataSource(payload.dataSources[i]) ] = true; } emit DataSourcesSet(oldDataSources, validDataSources()); } function setFee(SetFeePayload memory payload) internal { uint oldFee = singleUpdateFeeInWei(); setSingleUpdateFeeInWei(payload.newFee); emit FeeSet(oldFee, singleUpdateFeeInWei()); } function setValidPeriod(SetValidPeriodPayload memory payload) internal { uint oldValidPeriod = validTimePeriodSeconds(); setValidTimePeriodSeconds(payload.newValidPeriod); emit ValidPeriodSet(oldValidPeriod, validTimePeriodSeconds()); } function setWormholeAddress( SetWormholeAddressPayload memory payload, bytes memory encodedVM ) internal { address oldWormholeAddress = address(wormhole()); setWormhole(payload.newWormholeAddress); // We want to verify that the new wormhole address is valid, so we make sure that it can // parse and verify the same governance VAA that is used to set it. (IWormhole.VM memory vm, bool valid, ) = wormhole().parseAndVerifyVM( encodedVM ); if (!valid) revert PythErrors.InvalidGovernanceMessage(); if (!isValidGovernanceDataSource(vm.emitterChainId, vm.emitterAddress)) revert PythErrors.InvalidGovernanceMessage(); if (vm.sequence != lastExecutedGovernanceSequence()) revert PythErrors.InvalidWormholeAddressToSet(); GovernanceInstruction memory gi = parseGovernanceInstruction( vm.payload ); if (gi.action != GovernanceAction.SetWormholeAddress) revert PythErrors.InvalidWormholeAddressToSet(); // Purposefully, we don't check whether the chainId is the same as the current chainId because // we might want to change the chain id of the wormhole contract. // The following check is not necessary for security, but is a sanity check that the new wormhole // contract parses the payload correctly. SetWormholeAddressPayload memory newPayload = parseSetWormholeAddressPayload(gi.payload); if (newPayload.newWormholeAddress != payload.newWormholeAddress) revert PythErrors.InvalidWormholeAddressToSet(); emit WormholeAddressSet(oldWormholeAddress, address(wormhole())); } } contract PythUpgradable is Initializable, OwnableUpgradeable, UUPSUpgradeable, Pyth, PythGovernance { function initialize( address wormhole, uint16[] calldata dataSourceEmitterChainIds, bytes32[] calldata dataSourceEmitterAddresses, uint16 governanceEmitterChainId, bytes32 governanceEmitterAddress, uint64 governanceInitialSequence, uint validTimePeriodSeconds, uint singleUpdateFeeInWei ) public initializer { __Ownable_init(); __UUPSUpgradeable_init(); Pyth._initialize( wormhole, dataSourceEmitterChainIds, dataSourceEmitterAddresses, governanceEmitterChainId, governanceEmitterAddress, governanceInitialSequence, validTimePeriodSeconds, singleUpdateFeeInWei ); renounceOwnership(); } /// Ensures the contract cannot be uninitialized and taken over. /// @custom:oz-upgrades-unsafe-allow constructor constructor() initializer {} // Only allow the owner to upgrade the proxy to a new implementation. // The contract has no owner so this function will always revert // but UUPSUpgradeable expects this method to be implemented. function _authorizeUpgrade(address) internal override onlyOwner {} function pythUpgradableMagic() public pure returns (uint32) { return 0x97a6f304; } // Execute a UpgradeContract governance message function upgradeUpgradableContract( UpgradeContractPayload memory payload ) internal override { address oldImplementation = _getImplementation(); _upgradeToAndCallUUPS(payload.newImplementation, new bytes(0), false); // Calling a method using `this.<method>` will cause a contract call that will use // the new contract. This call will fail if the method does not exists or the magic // is different. if (this.pythUpgradableMagic() != 0x97a6f304) revert PythErrors.InvalidGovernanceMessage(); emit ContractUpgraded(oldImplementation, _getImplementation()); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InsufficientFee","type":"error"},{"inputs":[],"name":"InvalidArgument","type":"error"},{"inputs":[],"name":"InvalidGovernanceDataSource","type":"error"},{"inputs":[],"name":"InvalidGovernanceMessage","type":"error"},{"inputs":[],"name":"InvalidGovernanceTarget","type":"error"},{"inputs":[],"name":"InvalidUpdateData","type":"error"},{"inputs":[],"name":"InvalidUpdateDataSource","type":"error"},{"inputs":[],"name":"InvalidWormholeAddressToSet","type":"error"},{"inputs":[],"name":"InvalidWormholeVaa","type":"error"},{"inputs":[],"name":"NoFreshUpdate","type":"error"},{"inputs":[],"name":"OldGovernanceMessage","type":"error"},{"inputs":[],"name":"PriceFeedNotFound","type":"error"},{"inputs":[],"name":"PriceFeedNotFoundWithinRange","type":"error"},{"inputs":[],"name":"StalePrice","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"chainId","type":"uint16"},{"indexed":false,"internalType":"uint64","name":"sequenceNumber","type":"uint64"}],"name":"BatchPriceFeedUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"newImplementation","type":"address"}],"name":"ContractUpgraded","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource[]","name":"oldDataSources","type":"tuple[]"},{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource[]","name":"newDataSources","type":"tuple[]"}],"name":"DataSourcesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"FeeSet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource","name":"oldDataSource","type":"tuple"},{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource","name":"newDataSource","type":"tuple"},{"indexed":false,"internalType":"uint64","name":"initialSequence","type":"uint64"}],"name":"GovernanceDataSourceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"publishTime","type":"uint64"},{"indexed":false,"internalType":"int64","name":"price","type":"int64"},{"indexed":false,"internalType":"uint64","name":"conf","type":"uint64"}],"name":"PriceFeedUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldValidPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValidPeriod","type":"uint256"}],"name":"ValidPeriodSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldWormholeAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newWormholeAddress","type":"address"}],"name":"WormholeAddressSet","type":"event"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVM","type":"bytes"}],"name":"executeGovernanceInstruction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getEmaPrice","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"uint256","name":"age","type":"uint256"}],"name":"getEmaPriceNoOlderThan","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getEmaPriceUnsafe","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getPrice","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"uint256","name":"age","type":"uint256"}],"name":"getPriceNoOlderThan","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getPriceUnsafe","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"}],"name":"getUpdateFee","outputs":[{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"updateDataSize","type":"uint256"}],"name":"getUpdateFee","outputs":[{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getValidTimePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceDataSource","outputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceDataSourceIndex","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource","name":"ds","type":"tuple"}],"name":"hashDataSource","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"wormhole","type":"address"},{"internalType":"uint16[]","name":"dataSourceEmitterChainIds","type":"uint16[]"},{"internalType":"bytes32[]","name":"dataSourceEmitterAddresses","type":"bytes32[]"},{"internalType":"uint16","name":"governanceEmitterChainId","type":"uint16"},{"internalType":"bytes32","name":"governanceEmitterAddress","type":"bytes32"},{"internalType":"uint64","name":"governanceInitialSequence","type":"uint64"},{"internalType":"uint256","name":"validTimePeriodSeconds","type":"uint256"},{"internalType":"uint256","name":"singleUpdateFeeInWei","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"dataSourceChainId","type":"uint16"},{"internalType":"bytes32","name":"dataSourceEmitterAddress","type":"bytes32"}],"name":"isValidDataSource","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"governanceChainId","type":"uint16"},{"internalType":"bytes32","name":"governanceEmitterAddress","type":"bytes32"}],"name":"isValidGovernanceDataSource","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastExecutedGovernanceSequence","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"priceId","type":"bytes32"}],"name":"latestPriceInfoPublishTime","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseAuthorizeGovernanceDataSourceTransferPayload","outputs":[{"components":[{"internalType":"bytes","name":"claimVaa","type":"bytes"}],"internalType":"struct PythGovernanceInstructions.AuthorizeGovernanceDataSourceTransferPayload","name":"sgds","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedInstruction","type":"bytes"}],"name":"parseGovernanceInstruction","outputs":[{"components":[{"internalType":"enum PythGovernanceInstructions.GovernanceModule","name":"module","type":"uint8"},{"internalType":"enum PythGovernanceInstructions.GovernanceAction","name":"action","type":"uint8"},{"internalType":"uint16","name":"targetChainId","type":"uint16"},{"internalType":"bytes","name":"payload","type":"bytes"}],"internalType":"struct PythGovernanceInstructions.GovernanceInstruction","name":"gi","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"},{"internalType":"bytes32[]","name":"priceIds","type":"bytes32[]"},{"internalType":"uint64","name":"minPublishTime","type":"uint64"},{"internalType":"uint64","name":"maxPublishTime","type":"uint64"}],"name":"parsePriceFeedUpdates","outputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"emaPrice","type":"tuple"}],"internalType":"struct PythStructs.PriceFeed[]","name":"priceFeeds","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseRequestGovernanceDataSourceTransferPayload","outputs":[{"components":[{"internalType":"uint32","name":"governanceDataSourceIndex","type":"uint32"}],"internalType":"struct PythGovernanceInstructions.RequestGovernanceDataSourceTransferPayload","name":"sgdsClaim","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetDataSourcesPayload","outputs":[{"components":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource[]","name":"dataSources","type":"tuple[]"}],"internalType":"struct PythGovernanceInstructions.SetDataSourcesPayload","name":"sds","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetFeePayload","outputs":[{"components":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"internalType":"struct PythGovernanceInstructions.SetFeePayload","name":"sf","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetValidPeriodPayload","outputs":[{"components":[{"internalType":"uint256","name":"newValidPeriod","type":"uint256"}],"internalType":"struct PythGovernanceInstructions.SetValidPeriodPayload","name":"svp","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetWormholeAddressPayload","outputs":[{"components":[{"internalType":"address","name":"newWormholeAddress","type":"address"}],"internalType":"struct PythGovernanceInstructions.SetWormholeAddressPayload","name":"sw","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseUpgradeContractPayload","outputs":[{"components":[{"internalType":"address","name":"newImplementation","type":"address"}],"internalType":"struct PythGovernanceInstructions.UpgradeContractPayload","name":"uc","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"priceFeedExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pythUpgradableMagic","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"queryPriceFeed","outputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"emaPrice","type":"tuple"}],"internalType":"struct PythStructs.PriceFeed","name":"priceFeed","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"singleUpdateFeeInWei","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"}],"name":"updatePriceFeeds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"},{"internalType":"bytes32[]","name":"priceIds","type":"bytes32[]"},{"internalType":"uint64[]","name":"publishTimes","type":"uint64[]"}],"name":"updatePriceFeedsIfNecessary","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"validDataSources","outputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"validTimePeriodSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"wormhole","outputs":[{"internalType":"contract IWormhole","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523060601b6080523480156200001857600080fd5b50600054610100900460ff16158080156200003a5750600054600160ff909116105b806200006a575062000057306200014460201b620026861760201c565b1580156200006a575060005460ff166001145b620000d25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff191660011790558015620000f6576000805461ff0019166101001790555b80156200013d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5062000153565b6001600160a01b03163b151590565b60805160601c615f4c6200018e60003960008181610ba201528181610c3801528181611330015281816113c601526114c10152615f4c6000f3fe6080604052600436106102e75760003560e01c80638881016f11610184578063b6ed701e116100d6578063d82d58a51161008a578063e3795cc111610064578063e3795cc11461096b578063ef9e5e2814610982578063f2fde38b1461099557600080fd5b8063d82d58a5146108fd578063e17efd4814610936578063e18910a31461095657600080fd5b8063caaf43f1116100bb578063caaf43f11461089b578063cb718a9b146108c8578063d47eed45146108dd57600080fd5b8063b6ed701e14610868578063b9256d281461088857600080fd5b80639a8a059211610138578063aac4129211610112578063aac41292146106ef578063b5dcc9111461080f578063b5ec02611461082f57600080fd5b80639a8a0592146107a5578063a38d81c6146107cd578063a4ae35e0146107ef57600080fd5b80638da5cb5b116101695780638da5cb5b146107475780639474f45b1461076557806396834ad31461078557600080fd5b80638881016f146106ef57806389a5bb4d1461072757600080fd5b806352d1902d1161023d5780636c72f51b116101f15780637b72bcae116101cb5780637b72bcae1461065b57806384acd1bb1461069057806387c5bd1b146106c257600080fd5b80636c72f51b146105fa578063711a2e2814610626578063715018a61461064657600080fd5b8063586d3cf811610222578063586d3cf81461058e57806358c67635146105ad5780636b7f53ca146105cd57600080fd5b806352d1902d1461052d57806354fd4d501461054257600080fd5b8063437209a71161029f5780634c469d8c116102795780634c469d8c146104aa5780634d7a734e146104fa5780634f1ef2861461051a57600080fd5b8063437209a7146103d55780634716e9c51461046b57806348b6404d1461048b57600080fd5b806331d98b3f116102d057806331d98b3f146103425780633659cfe61461036f578063426234e41461038f57600080fd5b8063146faf77146102ec57806314dd317f1461030e575b600080fd5b3480156102f857600080fd5b5061030c6103073660046152ff565b6109b5565b005b34801561031a57600080fd5b5061032e610329366004615632565b610b06565b604051905181526020015b60405180910390f35b34801561034e57600080fd5b5061036261035d366004615574565b610b61565b6040516103399190615b80565b34801561037b57600080fd5b5061030c61038a3660046152e5565b610b97565b34801561039b57600080fd5b506040805180820182526000808252602091820152815180830190925260d05461ffff16825260d154908201526040516103399190615af5565b3480156103e157600080fd5b5061045b6103f0366004615846565b6040805160f09390931b7fffff000000000000000000000000000000000000000000000000000000000000166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b6040519015158152602001610339565b61047e6104793660046154e2565b610d52565b6040516103399190615a49565b34801561049757600080fd5b5060ce545b604051908152602001610339565b3480156104b657600080fd5b506104e16104c5366004615574565b600090815260d5602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610339565b34801561050657600080fd5b5061032e610515366004615632565b61128b565b61030c6105283660046153c0565b611325565b34801561053957600080fd5b5061049c6114b4565b34801561054e57600080fd5b50604080518082018252600581527f312e332e30000000000000000000000000000000000000000000000000000000602082015290516103399190615ac7565b34801561059a57600080fd5b5060d25467ffffffffffffffff166104e1565b3480156105b957600080fd5b5061045b6105c8366004615846565b611579565b3480156105d957600080fd5b506105ed6105e8366004615632565b61159c565b6040516103399190615b10565b34801561060657600080fd5b5060d45463ffffffff165b60405163ffffffff9091168152602001610339565b34801561063257600080fd5b506103626106413660046155a4565b6117a0565b34801561065257600080fd5b5061030c611816565b34801561066757600080fd5b5061067b610676366004615632565b61182a565b604051905163ffffffff168152602001610339565b34801561069c57600080fd5b5060c9546001600160a01b03165b6040516001600160a01b039091168152602001610339565b3480156106ce57600080fd5b506106e26106dd366004615632565b611858565b6040516103399190615bbb565b3480156106fb57600080fd5b5061070f61070a366004615632565b6119d5565b60405190516001600160a01b03168152602001610339565b34801561073357600080fd5b5061049c610742366004615665565b611a06565b34801561075357600080fd5b506033546001600160a01b03166106aa565b34801561077157600080fd5b50610362610780366004615574565b611a70565b34801561079157600080fd5b506103626107a0366004615574565b611b03565b3480156107b157600080fd5b506107ba611ba5565b60405161ffff9091168152602001610339565b3480156107d957600080fd5b506107e2611c2e565b6040516103399190615a11565b3480156107fb57600080fd5b5061036261080a3660046155a4565b611ca1565b34801561081b57600080fd5b5061036261082a366004615574565b611cce565b34801561083b57600080fd5b5061045b61084a366004615574565b600090815260d5602052604090205467ffffffffffffffff16151590565b34801561087457600080fd5b5061030c6108833660046155c5565b611cfe565b61030c61089636600461544c565b612018565b3480156108a757600080fd5b506108bb6108b6366004615574565b61212b565b6040516103399190615b71565b3480156108d457600080fd5b5060cf5461049c565b3480156108e957600080fd5b5061049c6108f836600461540c565b612308565b34801561090957600080fd5b50610929610918366004615632565b604080516020810190915290815290565b6040516103399190615ada565b34801561094257600080fd5b5061049c610951366004615574565b612473565b34801561096257600080fd5b5061049c612489565b34801561097757600080fd5b506397a6f304610611565b61030c61099036600461540c565b612494565b3480156109a157600080fd5b5061030c6109b03660046152e5565b6125f9565b600054610100900460ff16158080156109d55750600054600160ff909116105b806109ef5750303b1580156109ef575060005460ff166001145b610a665760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805460ff191660011790558015610a89576000805461ff0019166101001790555b610a91612695565b610a9961271a565b610aab8b8b8b8b8b8b8b8b8b8b612797565b610ab3611816565b8015610af9576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050505050565b6040805160208101909152600081526000610b218382612a0b565b67ffffffffffffffff168252610b38600882615d07565b905080835114610b5b576040516397363b3560e01b815260040160405180910390fd5b50919050565b604080516080810182526000808252602082018190529181018290526060810191909152610b918261080a612489565b92915050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415610c365760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610a5d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c917f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614610d0d5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610a5d565b610d1681612a71565b610d4f8160005b6040519080825280601f01601f191660200182016040528015610d47576020820181803683370190505b506000612a79565b50565b60606000610d608888612308565b905080341015610d9c576040517f025dbdd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b508367ffffffffffffffff811115610dc457634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610e5457816020015b610e41604080516060808201835260008083528351608081018552818152602081810183905294810182905291820152909182019081526040805160808101825260008082526020828101829052928201819052606082015291015290565b815260200190600190039081610de25790505b50905060005b8681101561120a576004888883818110610e8457634e487b7160e01b600052603260045260246000fd5b9050602002810190610e969190615bd6565b9050118015610eea575063504e4155610ee2898984818110610ec857634e487b7160e01b600052603260045260246000fd5b9050602002810190610eda9190615bd6565b503560e01c90565b63ffffffff16145b156110d757600080610f2c8a8a85818110610f1557634e487b7160e01b600052603260045260246000fd5b9050602002810190610f279190615bd6565b612c2d565b90925090506000818015610f5057634e487b7160e01b600052602160045260246000fd5b14610f6e5760405163734fff6760e11b815260040160405180910390fd5b50600080366000610fb08d8d88818110610f9857634e487b7160e01b600052603260045260246000fd5b9050602002810190610faa9190615bd6565b87612cf4565b93985091965094509250905060005b8360ff168110156110ac576040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101829052906110088786868b612e3f565b91995092509050600061101c8f8f84612f54565b90508d81148061105657508a818151811061104757634e487b7160e01b600052603260045260246000fd5b60209081029190910101515115155b15611063575050506110a4565b825167ffffffffffffffff908116908e16811080159061108d57508c67ffffffffffffffff168111155b1561109f5761109f8c83858785612fa5565b505050505b600101610fbf565b508481146110cd5760405163734fff6760e11b815260040160405180910390fd5b5050505050611202565b606060006111158a8a858181106110fe57634e487b7160e01b600052603260045260246000fd5b90506020028101906111109190615bd6565b6131e9565b60e00151915060009050808061112a8461333a565b92509250925060005b828110156111fc576040848601015160209060006111528e8e84612f54565b90508c81148061118c575089818151811061117d57634e487b7160e01b600052603260045260246000fd5b60209081029190910101515115155b1561119d57505050928101926111f4565b60006111aa898988613469565b50805190915067ffffffffffffffff908116908e1681108015906111d857508c67ffffffffffffffff168111155b156111ea576111ea8c84868585612fa5565b5050509483019450505b600101611133565b50505050505b600101610e5a565b5060005b848110156112805781818151811061123657634e487b7160e01b600052603260045260246000fd5b602090810291909101015151611278576040517f45805f5d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60010161120e565b509695505050505050565b6040805160208101909152600081526000806112a78482612a0b565b90506112b4600883615d07565b915060006112c28584612a0b565b90506112cf600884615d07565b92506112e667ffffffffffffffff8216600a615d62565b6112fa9067ffffffffffffffff8416615e0a565b84528451831461131d576040516397363b3560e01b815260040160405180910390fd5b505050919050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156113c45760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610a5d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661141f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b03161461149b5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610a5d565b6114a482612a71565b6114b082826001612a79565b5050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146115545760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610a5d565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b60d05460009061ffff8481169116148015611595575060d15482145b9392505050565b6115c8604080516080810190915280600081526020016000815260006020820152606060409091015290565b6000806115d58482613579565b905063ffffffff8116635054474d14611601576040516397363b3560e01b815260040160405180910390fd5b61160c600483615d07565b9150600061161a85846135df565b90508060ff16600181111561163f57634e487b7160e01b600052602160045260246000fd5b8490600181111561166057634e487b7160e01b600052602160045260246000fd5b9081600181111561168157634e487b7160e01b600052602160045260246000fd5b90525061168f600184615d07565b92506001845160018111156116b457634e487b7160e01b600052602160045260246000fd5b146116d2576040516363daeb7760e01b815260040160405180910390fd5b60006116de86856135df565b90508060ff16600681111561170357634e487b7160e01b600052602160045260246000fd5b8560200190600681111561172757634e487b7160e01b600052602160045260246000fd5b9081600681111561174857634e487b7160e01b600052602160045260246000fd5b905250611756600185615d07565b93506117628685613645565b61ffff166040860152611776600285615d07565b9350611791848588516117899190615e29565b8891906136ab565b60608601525092949350505050565b6040805160808101825260008082526020820181905291810182905260608101919091526117cd83611a70565b9050816117de4283606001516137d3565b1115610b91576040517f19abf40e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61181e6137f8565b6118286000613852565b565b60408051602081019091526000815260006118458382613579565b63ffffffff168252610b38600482615d07565b60408051602081019091526060815260008061187484826135df565b9050611881600183615d07565b91508060ff1667ffffffffffffffff8111156118ad57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156118f257816020015b60408051808201909152600080825260208201528152602001906001900390816118cb5790505b50835260005b8160ff168110156119ac5761190d8584613645565b845180518390811061192f57634e487b7160e01b600052603260045260246000fd5b602090810291909101015161ffff909116905261194d600284615d07565b925061195985846138b1565b845180518390811061197b57634e487b7160e01b600052603260045260246000fd5b602002602001015160200181815250506020836119989190615d07565b9250806119a481615e6c565b9150506118f8565b50818451146119ce576040516397363b3560e01b815260040160405180910390fd5b5050919050565b60408051602081019091526000815260006119f08382613917565b6001600160a01b03168252610b38601482615d07565b600081600001518260200151604051602001611a5392919060f09290921b7fffff000000000000000000000000000000000000000000000000000000000000168252600282015260220190565b604051602081830303815290604052805190602001209050919050565b60408051608081018252600080825260208083018281528385018381526060850184815287855260d590935294909220805467ffffffffffffffff808216938490526801000000000000000091829004600390810b810b900b9096526001820154600781810b810b900b865204909416909152909190610b5b57604051630295d7cd60e31b815260040160405180910390fd5b60408051608081018252600080825260208083018281528385018381526060850184815287855260d590935294909220805467ffffffffffffffff80821693849052680100000000000000008204600390810b810b900b9096526c010000000000000000000000008104600790810b810b900b8552600160a01b9004909416909152909190610b5b57604051630295d7cd60e31b815260040160405180910390fd5b6000611bb960c9546001600160a01b031690565b6001600160a01b0316639a8a05926040518163ffffffff1660e01b815260040160206040518083038186803b158015611bf157600080fd5b505afa158015611c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c29919061582a565b905090565b606060c9600301805480602002602001604051908101604052809291908181526020016000905b82821015611c985760008481526020908190206040805180820190915260028502909101805461ffff168252600190810154828401529083529092019101611c55565b50505050905090565b6040805160808101825260008082526020820181905291810182905260608101919091526117cd83611b03565b604080516080810182526000808252602082018190529181018290526060810191909152610b9182610641612489565b6000611d3f83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061398d92505050565b90506000611d508260e0015161159c565b9050611d5a611ba5565b61ffff16816040015161ffff1614158015611d7c5750604081015161ffff1615155b15611d9a576040516363daeb7760e01b815260040160405180910390fd5b600081602001516006811115611dc057634e487b7160e01b600052602160045260246000fd5b1415611e0657604081015161ffff16611dec576040516363daeb7760e01b815260040160405180910390fd5b611e01611dfc82606001516119d5565b613b6e565b612012565b600181602001516006811115611e2c57634e487b7160e01b600052602160045260246000fd5b1415611e5357611e01611e4e8260600151604080516020810190915290815290565b613b77565b600281602001516006811115611e7957634e487b7160e01b600052602160045260246000fd5b1415611e9457611e01611e8f8260600151611858565b613eaa565b600381602001516006811115611eba57634e487b7160e01b600052602160045260246000fd5b1415611ed557611e01611ed0826060015161128b565b614053565b600481602001516006811115611efb57634e487b7160e01b600052602160045260246000fd5b1415611f1657611e01611f118260600151610b06565b6140a5565b600581602001516006811115611f3c57634e487b7160e01b600052602160045260246000fd5b1415611f5b576040516397363b3560e01b815260040160405180910390fd5b600681602001516006811115611f8157634e487b7160e01b600052602160045260246000fd5b1415611ff957604081015161ffff16611fad576040516363daeb7760e01b815260040160405180910390fd5b611e01611fbd82606001516119d5565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506140e292505050565b6040516397363b3560e01b815260040160405180910390fd5b50505050565b8281146120385760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b838110156120f05782828281811061206357634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612078919061588b565b67ffffffffffffffff166120c88686848181106120a557634e487b7160e01b600052603260045260246000fd5b90506020020135600090815260d5602052604090205467ffffffffffffffff1690565b67ffffffffffffffff1610156120e8576120e28787612494565b50612123565b60010161203b565b506040517fde2c57fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b61218a604080516060808201835260008083528351608081018552818152602081810183905294810182905291820152909182019081526040805160808101825260008082526020828101829052928201819052606082015291015290565b6040805160c08082018352600080835260208084018290528385018290526060808501839052608080860184905260a095860184905288845260d5835286842087519586018852805467ffffffffffffffff808216885268010000000000000000808304600390810b810b900b968901969096526c010000000000000000000000008204600790810b810b810b9a89019a909a52600160a01b9091048116938701939093526001015480880b880b90970b90850152940490931691810191909152805190915067ffffffffffffffff1661227757604051630295d7cd60e31b815260040160405180910390fd5b91815260408083015160208084018051600793840b840b9052606080870151825167ffffffffffffffff9182169085015283880180518451600391820b820b9089015289519451948316948401949094526080890151878901805191880b90970b905260a089015186519083169501949094529251845190830b90920b919094015293519051931692019190915290565b600080805b8381101561246157600485858381811061233757634e487b7160e01b600052603260045260246000fd5b90506020028101906123499190615bd6565b9050118015612383575063504e415561237b868684818110610ec857634e487b7160e01b600052603260045260246000fd5b63ffffffff16145b15612441576000806123ae878785818110610f1557634e487b7160e01b600052603260045260246000fd5b909250905060008180156123d257634e487b7160e01b600052602160045260246000fd5b146123f05760405163734fff6760e11b815260040160405180910390fd5b61242b87878581811061241357634e487b7160e01b600052603260045260246000fd5b90506020028101906124259190615bd6565b8461433a565b6124389060ff1685615d07565b9350505061244f565b61244c600183615d07565b91505b8061245981615e6c565b91505061230d565b5061246b81614371565b949350505050565b60008161247f60ce5490565b610b919190615e0a565b6000611c2960cf5490565b6000805b828110156125b15760048484838181106124c257634e487b7160e01b600052603260045260246000fd5b90506020028101906124d49190615bd6565b905011801561250e575063504e4155612506858584818110610ec857634e487b7160e01b600052603260045260246000fd5b63ffffffff16145b156125615761254d84848381811061253657634e487b7160e01b600052603260045260246000fd5b90506020028101906125489190615bd6565b614386565b61255a9060ff1683615d07565b91506125a9565b61259b84848381811061258457634e487b7160e01b600052603260045260246000fd5b90506020028101906125969190615bd6565b614604565b6125a6600183615d07565b91505b600101612498565b5060006125bd82614371565b905080341015612012576040517f025dbdd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6126016137f8565b6001600160a01b03811661267d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a5d565b610d4f81613852565b6001600160a01b03163b151590565b600054610100900460ff166127125760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a5d565b611828614616565b600054610100900460ff166118285760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a5d565b60c9805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038c161790558786146127df5760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b888110156129a257600060405180604001604052808c8c8581811061281757634e487b7160e01b600052603260045260246000fd5b905060200201602081019061282c919061580e565b61ffff1681526020018a8a8581811061285557634e487b7160e01b600052603260045260246000fd5b602090810292909201359092528251838201516040805160f09390931b7fffff00000000000000000000000000000000000000000000000000000000000016838501526022808401929092528051808403909201825260429092018252805190830120600090815260cd9092529020549192505060ff16156128ea5760405163a9cb9e0d60e01b815260040160405180910390fd5b600160cd60006128f984611a06565b81526020808201929092526040016000908120805460ff19169315159390931790925560cc8054600181018255925282517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebe6002909302928301805461ffff191661ffff90921691909117905591909101517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebf909101558061299a81615e6c565b9150506127e2565b506040805180820190915261ffff86168082526020820186905260d0805461ffff1916909117905560d185905560d2805467ffffffffffffffff191667ffffffffffffffff8616179055506129f68260cf55565b6129ff8160ce55565b50505050505050505050565b6000612a18826008615d07565b83511015612a685760405162461bcd60e51b815260206004820152601460248201527f746f55696e7436345f6f75744f66426f756e64730000000000000000000000006044820152606401610a5d565b50016008015190565b610d4f6137f8565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612ab157612aac8361469c565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015612aea57600080fd5b505afa925050508015612b1a575060408051601f3d908101601f19168201909252612b179181019061558c565b60015b612b8c5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401610a5d565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612c215760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401610a5d565b50612aac838383614767565b60046000833560e01c63504e41558114612c5a5760405163734fff6760e11b815260040160405180910390fd5b60018084019386013560f81c908114612c865760405163734fff6760e11b815260040160405180910390fd5b50508184016001013560f890811c9092016002818101939186010135901c60ff168015612cc357634e487b7160e01b600052602160045260246000fd5b60019290920191905081831015612ced5760405163734fff6760e11b815260040160405180910390fd5b9250929050565b600080803681612d0888888880820361478c565b600296509092509050813560f01c60606000612d2e612d2986868b8761478c565b6147b6565b60e0015160048082015161ffff86169a909a01999193509150634155575663ffffffff821614612d715760405163734fff6760e11b815260040160405180910390fd5b8183016001015160009060ff168015612d9a57634e487b7160e01b600052602160045260246000fd5b60019093019290506000818015612dc157634e487b7160e01b600052602160045260246000fd5b14612ddf5760405163734fff6760e11b815260040160405180910390fd5b602c848401015184516c0100000000000000000000000090910460601b9950602090930192831115612e245760405163734fff6760e11b815260040160405180910390fd5b5050600188019b969a505050509381013560f81c9550935050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101829052600283019282903690829088013560f01c612e8d8989898461478c565b925092508061ffff16870196506000612eaa8a8a8a8e8888614940565b9750905080612ecc5760405163734fff6760e11b815260040160405180910390fd5b6000843560f81c8015612eef57634e487b7160e01b600052602160045260246000fd5b90506000818015612f1057634e487b7160e01b600052602160045260246000fd5b1415612f2c57612f22858560016149f2565b9097509550612f45565b60405163734fff6760e11b815260040160405180910390fd5b50505050509450945094915050565b6000805b8381101561246b5782858583818110612f8157634e487b7160e01b600052603260045260246000fd5b905060200201351415612f935761246b565b80612f9d81615e6c565b915050612f58565b82858581518110612fc657634e487b7160e01b600052603260045260246000fd5b602002602001015160000181815250508160400151858581518110612ffb57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516000019060070b908160070b81525050816060015185858151811061303c57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516020019067ffffffffffffffff16908167ffffffffffffffff1681525050816020015185858151811061308b57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516040019060030b908160030b81525050808585815181106130c857634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516060018181525050816080015185858151811061310157634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516000019060070b908160070b815250508160a0015185858151811061314257634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516020019067ffffffffffffffff16908167ffffffffffffffff1681525050816020015185858151811061319157634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516040019060030b908160030b81525050808585815181106131ce57634e487b7160e01b600052603260045260246000fd5b60200260200101516040015160600181815250505050505050565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018190526101008201839052610120820152610140810191909152600061325560c9546001600160a01b031690565b6001600160a01b031663c0fd8bde85856040518363ffffffff1660e01b8152600401613282929190615a98565b60006040518083038186803b15801561329a57600080fd5b505afa1580156132ae573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526132d691908101906156bc565b509092509050806132fa57604051632acbe91560e01b815260040160405180910390fd5b5061330481614a8c565b610b91576040517fe60dce7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080808061334d858260049101015190565b90506004840193508063ffffffff1663503257481461337f5760405163734fff6760e11b815260040160405180910390fd5b6002858501810151940193600361ffff8216146133af5760405163734fff6760e11b815260040160405180910390fd5b60028501945060006133c5878760029101015190565b905060028601955060006133dd888860019101015190565b90508161ffff16870196508060ff1660021461340c5760405163734fff6760e11b815260040160405180910390fd5b505050508284016002015161ffff169150600283019250613431848460029101015190565b61ffff16905060028301925081810283018451146134625760405163734fff6760e11b815260040160405180910390fd5b9193909250565b6040805160c081018252600080825260208201818152828401828152606084018381526080850184815260a08601948552888a01968701516048880151600790810b810b909452605088015167ffffffffffffffff9081169093526054880151600390810b900b909452605c870151830b90920b909152606485015181169092526065840151607d94850151909216835291929060ff8116600114156135145760188201915061354e565b8582018701600881015167ffffffffffffffff90811686526010820151600790810b900b6040870152601891820151166060860152909101905b50838111156135705760405163734fff6760e11b815260040160405180910390fd5b50935093915050565b6000613586826004615d07565b835110156135d65760405162461bcd60e51b815260206004820152601460248201527f746f55696e7433325f6f75744f66426f756e64730000000000000000000000006044820152606401610a5d565b50016004015190565b60006135ec826001615d07565b8351101561363c5760405162461bcd60e51b815260206004820152601360248201527f746f55696e74385f6f75744f66426f756e6473000000000000000000000000006044820152606401610a5d565b50016001015190565b6000613652826002615d07565b835110156136a25760405162461bcd60e51b815260206004820152601460248201527f746f55696e7431365f6f75744f66426f756e64730000000000000000000000006044820152606401610a5d565b50016002015190565b6060816136b981601f615d07565b10156137075760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610a5d565b6137118284615d07565b845110156137615760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610a5d565b60608215801561378057604051915060008252602082016040526137ca565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156137b95780518352602092830192016137a1565b5050858452601f01601f1916604052505b50949350505050565b6000818311156137ee576137e78284615e29565b9050610b91565b6137e78383615e29565b6033546001600160a01b031633146118285760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a5d565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006138be826020615d07565b8351101561390e5760405162461bcd60e51b815260206004820152601560248201527f746f427974657333325f6f75744f66426f756e647300000000000000000000006044820152606401610a5d565b50016020015190565b6000613924826014615d07565b835110156139745760405162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606401610a5d565b5001602001516c01000000000000000000000000900490565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820181905261010082018390526101208201526101408101919091526000806139fa60c9546001600160a01b031690565b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b8152600401613a259190615ac7565b60006040518083038186803b158015613a3d57600080fd5b505afa158015613a51573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a7991908101906156bc565b509150915080613a9c57604051632acbe91560e01b815260040160405180910390fd5b613aae82606001518360800151611579565b613ae4576040517f360f2d8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60d25467ffffffffffffffff1667ffffffffffffffff168260a0015167ffffffffffffffff1611613b41576040517f88d1b84700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a082015160d2805467ffffffffffffffff191667ffffffffffffffff9092169190911790555092915050565b610d4f81614b06565b6000613bab6040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b9050600080613bc260c9546001600160a01b031690565b84516040517fc0fd8bde0000000000000000000000000000000000000000000000000000000081526001600160a01b03929092169163c0fd8bde91613c0991600401615ac7565b60006040518083038186803b158015613c2157600080fd5b505afa158015613c35573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c5d91908101906156bc565b509150915080613c8057604051632acbe91560e01b815260040160405180910390fd5b6000613c8f8360e0015161159c565b9050613c99611ba5565b61ffff16816040015161ffff1614158015613cbb5750604081015161ffff1615155b15613cd9576040516363daeb7760e01b815260040160405180910390fd5b600581602001516006811115613cff57634e487b7160e01b600052602160045260246000fd5b14613d1d576040516397363b3560e01b815260040160405180910390fd5b6000613d2c826060015161182a565b805190915063ffffffff16613d4660d45463ffffffff1690565b63ffffffff1610613d83576040517f88d1b84700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160d480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff909216919091179055604080518082018252606086015161ffff168082526080870151602080840182905260d0805461ffff19168417905560d182905560a089015160d2805467ffffffffffffffff191667ffffffffffffffff90921691909117905584518086018652600080825290820152845180860190955291845290830152907f6bce23ef3d34e51710fe4700b43ba5f1733a6215c883f384671a4ece3ea8aa2090879060d25460408051845161ffff908116825260209586015186830152845116918101919091529290910151606083015267ffffffffffffffff16608082015260a0015b60405180910390a150505050505050565b6000613eb4611c2e565b905060005b8151811015613f2c57600060c96004016000613efb858581518110613eee57634e487b7160e01b600052603260045260246000fd5b6020026020010151611a06565b81526020810191909152604001600020805460ff1916911515919091179055613f25600182615d07565b9050613eb9565b50613f3960cc600061509d565b60005b82515181101561400e578251805160cc919083908110613f6c57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015182546001808201855560009485528385208351600290930201805461ffff191661ffff90931692909217825591909201519181019190915584518051919260cd929091613fdd9186908110613eee57634e487b7160e01b600052603260045260246000fd5b81526020810191909152604001600020805460ff19169115159190911790558061400681615e6c565b915050613f3c565b507fd451e0fcb7c5b9e13de533604d158069dad159841c45f39f09d379bfc423080d81614039611c2e565b604051614047929190615a24565b60405180910390a15050565b600061405e60ce5490565b825160ce5590507f74dbbbe280ef27b79a8a0c449d5ae2ba7a31849103241d0f98df70bbc9d03e378161409060ce5490565b60408051928352602083019190915201614047565b60006140b060cf5490565b825160cf5590507fcdb88a22f82ddd76115ab7c66cf08eb1e40afe80c9b31017eb2cbdb1570b33ae8161409060cf5490565b60006140f660c9546001600160a01b031690565b835160c9805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0390921691821790556040517fc0fd8bde00000000000000000000000000000000000000000000000000000000815291925060009182919063c0fd8bde90614166908790600401615ac7565b60006040518083038186803b15801561417e57600080fd5b505afa158015614192573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526141ba91908101906156bc565b5091509150806141dd576040516397363b3560e01b815260040160405180910390fd5b6141ef82606001518360800151611579565b61420c576040516397363b3560e01b815260040160405180910390fd5b60d25467ffffffffffffffff1667ffffffffffffffff168260a0015167ffffffffffffffff1614614250576040516309e9f6c160e11b815260040160405180910390fd5b600061425f8360e0015161159c565b905060068160200151600681111561428757634e487b7160e01b600052602160045260246000fd5b146142a5576040516309e9f6c160e11b815260040160405180910390fd5b60006142b482606001516119d5565b875181519192506001600160a01b039182169116146142e6576040516309e9f6c160e11b815260040160405180910390fd5b7fd495c4e5b386d59bccca38a2277b5d70a0f5e47d7b6587a45a6f5aca221a31258561431a60c9546001600160a01b031690565b604080516001600160a01b03938416815292909116602083015201613e99565b60008382013560f01c61434e600284615d07565b925061435e61ffff821684615d07565b92508483013560f81c5b95945050505050565b600061437c60ce5490565b610b919083615e0a565b60008060006143958585612c2d565b909250905060008180156143b957634e487b7160e01b600052602160045260246000fd5b146143d75760405163734fff6760e11b815260040160405180910390fd5b6000803660006143e8898988612cf4565b919a50929650909450909250905060005b8760ff168110156145d7576040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101829052906144428686868a612e3f565b600081815260d560205260409020548251939a50919450925067ffffffffffffffff90811691168110156145cc57600082815260d560209081526040918290208551815487840151888601516060808b015167ffffffffffffffff9586166bffffffffffffffffffffffff1990951685176801000000000000000063ffffffff60039690960b959095168502177fffffffff00000000000000000000000000000000ffffffffffffffffffffffff166c01000000000000000000000000600794850b808916919091027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff1691909117600160a01b92881692830217885560808d01516001909801805460a08f01519990950b88167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090951694909417979096169093029590951790558551918252938101919091529283019190915283917fd06a6b7f4918494b3719217d1802786c1f5112a6c1d88fe2cfec00b4584f6aec910160405180910390a25b5050506001016143f9565b508381146145f85760405163734fff6760e11b815260040160405180910390fd5b50505050505092915050565b6114b061461183836131e9565b614c56565b600054610100900460ff166146935760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a5d565b61182833613852565b6001600160a01b0381163b6147195760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610a5d565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b61477083614e78565b60008251118061477d5750805b15612aac576120128383614eb8565b36600085848661479c8683615d07565b926147a993929190615cdf565b9150915094509492505050565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018190526101008201839052610120820152610140810191909152600061482260c9546001600160a01b031690565b6001600160a01b031663c0fd8bde85856040518363ffffffff1660e01b815260040161484f929190615a98565b60006040518083038186803b15801561486757600080fd5b505afa15801561487b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526148a391908101906156bc565b509092509050806148c757604051632acbe91560e01b815260040160405180910390fd5b50613304816060015182608001516040805160f09390931b7fffff000000000000000000000000000000000000000000000000000000000000166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b600080600061498485858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250614fba92505050565b600188019790915089013560f81c60005b8160ff168110156149cc5760148901988b01356bffffffffffffffffffffffff19166149c18482614fed565b935050600101614995565b50506bffffffffffffffffffffffff199081169516949094149794965093945050505050565b6040805160c08082018352838601602081810135831c600790810b810b958501959095526028820135831c6060850152603082013560e01c600390810b900b908401526034810135821c83526044810135821c840b90930b6080830152604c830135901c60a0820152605490920191903583831115614a845760405163734fff6760e11b815260040160405180910390fd5b935093915050565b6000610b91826060015183608001516040805160f09390931b7fffff000000000000000000000000000000000000000000000000000000000000166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b6000614b397f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b8251909150614b49906000610d1d565b306001600160a01b031663e3795cc16040518163ffffffff1660e01b815260040160206040518083038186803b158015614b8257600080fd5b505afa158015614b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bba9190615871565b63ffffffff166397a6f30414614be3576040516397363b3560e01b815260040160405180910390fd5b7f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a4981614c367f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b604080516001600160a01b03938416815292909116602083015201614047565b60e081015160008080614c688461333a565b92509250925060005b82811015614e1e57600080614c87878786613469565b600081815260d5602052604090205482519887019892945090925067ffffffffffffffff9081169116811015614e1357600082815260d560209081526040918290208551815487840151888601516060808b015167ffffffffffffffff9586166bffffffffffffffffffffffff1990951685176801000000000000000063ffffffff60039690960b959095168502177fffffffff00000000000000000000000000000000ffffffffffffffffffffffff166c01000000000000000000000000600794850b808916919091027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff1691909117600160a01b92881692830217885560808d01516001909801805460a08f01519990950b88167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090951694909417979096169093029590951790558551918252938101919091529283019190915283917fd06a6b7f4918494b3719217d1802786c1f5112a6c1d88fe2cfec00b4584f6aec910160405180910390a25b505050600101614c71565b50606085015160a08601516040805161ffff909316835267ffffffffffffffff90911660208301527f943f0e8a16c19895fb87cbeb1a349ed86d7f31923089dd36c1a1ed5e300f267b910160405180910390a15050505050565b614e818161469c565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b614f375760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e747261637400000000000000000000000000000000000000000000000000006064820152608401610a5d565b600080846001600160a01b031684604051614f5291906159aa565b600060405180830381855af49150503d8060008114614f8d576040519150601f19603f3d011682016040523d82523d6000602084013e614f92565b606091505b50915091506143688282604051806060016040528060278152602001615ef06027913961505f565b6000610b91600083604051602001614fd39291906159c6565b604051602081830303815290604052805160209091012090565b60006bffffffffffffffffffffffff19808316908416111561500d579091905b6040517f010000000000000000000000000000000000000000000000000000000000000060208201526bffffffffffffffffffffffff1980851660218301528316603582015261159590604901614fd3565b6060831561506e575081611595565b61159583838151156150835781518083602001fd5b8060405162461bcd60e51b8152600401610a5d9190615ac7565b5080546000825560020290600052602060002090810190610d4f91905b808211156150da57805461ffff19168155600060018201556002016150ba565b5090565b80356001600160a01b03811681146150f557600080fd5b919050565b60008083601f84011261510b578182fd5b50813567ffffffffffffffff811115615122578182fd5b6020830191508360208260051b8501011115612ced57600080fd5b600082601f83011261514d578081fd5b8151602067ffffffffffffffff82111561516957615169615eb3565b615177818360051b01615c86565b80838252828201915082860187848660071b8901011115615196578586fd5b855b858110156151f957608080838b0312156151b0578788fd5b6151b8615c39565b83518152868401518782015260406151d18186016152d4565b9082015260606151e28582016152d4565b908201528552938501939190910190600101615198565b5090979650505050505050565b805180151581146150f557600080fd5b600082601f830112615226578081fd5b813561523961523482615cb7565b615c86565b81815284602083860101111561524d578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112615277578081fd5b815161528561523482615cb7565b818152846020838601011115615299578283fd5b61246b826020830160208701615e40565b80516150f581615ec9565b805163ffffffff811681146150f557600080fd5b80516150f581615ed9565b805160ff811681146150f557600080fd5b6000602082840312156152f6578081fd5b611595826150de565b6000806000806000806000806000806101008b8d03121561531e578586fd5b6153278b6150de565b995060208b013567ffffffffffffffff80821115615343578788fd5b61534f8e838f016150fa565b909b50995060408d0135915080821115615367578788fd5b506153748d828e016150fa565b90985096505060608b013561538881615ec9565b945060808b0135935060a08b013561539f81615ed9565b8093505060c08b0135915060e08b013590509295989b9194979a5092959850565b600080604083850312156153d2578182fd5b6153db836150de565b9150602083013567ffffffffffffffff8111156153f6578182fd5b61540285828601615216565b9150509250929050565b6000806020838503121561541e578182fd5b823567ffffffffffffffff811115615434578283fd5b615440858286016150fa565b90969095509350505050565b60008060008060008060608789031215615464578384fd5b863567ffffffffffffffff8082111561547b578586fd5b6154878a838b016150fa565b9098509650602089013591508082111561549f578586fd5b6154ab8a838b016150fa565b909650945060408901359150808211156154c3578384fd5b506154d089828a016150fa565b979a9699509497509295939492505050565b600080600080600080608087890312156154fa578384fd5b863567ffffffffffffffff80821115615511578586fd5b61551d8a838b016150fa565b90985096506020890135915080821115615535578586fd5b5061554289828a016150fa565b909550935050604087013561555681615ed9565b9150606087013561556681615ed9565b809150509295509295509295565b600060208284031215615585578081fd5b5035919050565b60006020828403121561559d578081fd5b5051919050565b600080604083850312156155b6578182fd5b50508035926020909101359150565b600080602083850312156155d7578182fd5b823567ffffffffffffffff808211156155ee578384fd5b818501915085601f830112615601578384fd5b81358181111561560f578485fd5b866020828501011115615620578485fd5b60209290920196919550909350505050565b600060208284031215615643578081fd5b813567ffffffffffffffff811115615659578182fd5b61246b84828501615216565b600060408284031215615676578081fd5b6040516040810181811067ffffffffffffffff8211171561569957615699615eb3565b60405282356156a781615ec9565b81526020928301359281019290925250919050565b6000806000606084860312156156d0578081fd5b835167ffffffffffffffff808211156156e7578283fd5b9085019061016082880312156156fb578283fd5b615703615c62565b61570c836152d4565b815261571a602084016152b5565b602082015261572b604084016152b5565b604082015261573c606084016152aa565b60608201526080830151608082015261575760a084016152c9565b60a082015261576860c084016152d4565b60c082015260e08301518281111561577e578485fd5b61578a89828601615267565b60e08301525061010061579e8185016152b5565b9082015261012083810151838111156157b5578586fd5b6157c18a82870161513d565b9183019190915250610140838101519082015294506157e260208701615206565b935060408601519150808211156157f7578283fd5b5061580486828701615267565b9150509250925092565b60006020828403121561581f578081fd5b813561159581615ec9565b60006020828403121561583b578081fd5b815161159581615ec9565b60008060408385031215615858578182fd5b823561586381615ec9565b946020939093013593505050565b600060208284031215615882578081fd5b611595826152b5565b60006020828403121561589c578081fd5b813561159581615ed9565b6000815180845260208085019450808401835b838110156158ee576158db878351805161ffff168252602090810151910152565b60409690960195908201906001016158ba565b509495945050505050565b60008151808452615911816020860160208601615e40565b601f01601f19169290920160200192915050565b80518252602081015161596c6020840182805160070b825267ffffffffffffffff6020820151166020830152604081015160030b6040830152606081015160608301525050565b50604090810151805160070b60a0840152602081015167ffffffffffffffff1660c08401529081015160030b60e08301526060015161010090910152565b600082516159bc818460208701615e40565b9190910192915050565b7fff000000000000000000000000000000000000000000000000000000000000008360f81b16815260008251615a03816001850160208701615e40565b919091016001019392505050565b60208152600061159560208301846158a7565b604081526000615a3760408301856158a7565b828103602084015261436881856158a7565b6020808252825182820181905260009190848201906040850190845b81811015615a8c57615a78838551615925565b928401926101209290920191600101615a65565b50909695505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60208152600061159560208301846158f9565b602081526000825160208084015261246b60408401826158f9565b815161ffff1681526020808301519082015260408101610b91565b602081526000825160028110615b2857615b28615e9d565b80602084015250602083015160078110615b4457615b44615e9d565b8060408401525061ffff6040840151166060830152606083015160808084015261246b60a08401826158f9565b6101208101610b918284615925565b815160070b815260208083015167ffffffffffffffff169082015260408083015160030b908201526060808301519082015260808101610b91565b602081526000825160208084015261246b60408401826158a7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615c0a578283fd5b83018035915067ffffffffffffffff821115615c24578283fd5b602001915036819003821315612ced57600080fd5b6040516080810167ffffffffffffffff81118282101715615c5c57615c5c615eb3565b60405290565b604051610160810167ffffffffffffffff81118282101715615c5c57615c5c615eb3565b604051601f8201601f1916810167ffffffffffffffff81118282101715615caf57615caf615eb3565b604052919050565b600067ffffffffffffffff821115615cd157615cd1615eb3565b50601f01601f191660200190565b60008085851115615cee578182fd5b83861115615cfa578182fd5b5050820193919092039150565b60008219821115615d1a57615d1a615e87565b500190565b600181815b80851115615d5a578160001904821115615d4057615d40615e87565b80851615615d4d57918102915b93841c9390800290615d24565b509250929050565b60006115958383600082615d7857506001610b91565b81615d8557506000610b91565b8160018114615d9b5760028114615da557615dc1565b6001915050610b91565b60ff841115615db657615db6615e87565b50506001821b610b91565b5060208310610133831016604e8410600b8410161715615de4575081810a610b91565b615dee8383615d1f565b8060001904821115615e0257615e02615e87565b029392505050565b6000816000190483118215151615615e2457615e24615e87565b500290565b600082821015615e3b57615e3b615e87565b500390565b60005b83811015615e5b578181015183820152602001615e43565b838111156120125750506000910152565b6000600019821415615e8057615e80615e87565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b61ffff81168114610d4f57600080fd5b67ffffffffffffffff81168114610d4f57600080fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122099b939a0e68f7cf23dd87f1d08ae171925bb84265dfec2ec4a23e360576bf68364736f6c63430008040033
Deployed Bytecode
0x6080604052600436106102e75760003560e01c80638881016f11610184578063b6ed701e116100d6578063d82d58a51161008a578063e3795cc111610064578063e3795cc11461096b578063ef9e5e2814610982578063f2fde38b1461099557600080fd5b8063d82d58a5146108fd578063e17efd4814610936578063e18910a31461095657600080fd5b8063caaf43f1116100bb578063caaf43f11461089b578063cb718a9b146108c8578063d47eed45146108dd57600080fd5b8063b6ed701e14610868578063b9256d281461088857600080fd5b80639a8a059211610138578063aac4129211610112578063aac41292146106ef578063b5dcc9111461080f578063b5ec02611461082f57600080fd5b80639a8a0592146107a5578063a38d81c6146107cd578063a4ae35e0146107ef57600080fd5b80638da5cb5b116101695780638da5cb5b146107475780639474f45b1461076557806396834ad31461078557600080fd5b80638881016f146106ef57806389a5bb4d1461072757600080fd5b806352d1902d1161023d5780636c72f51b116101f15780637b72bcae116101cb5780637b72bcae1461065b57806384acd1bb1461069057806387c5bd1b146106c257600080fd5b80636c72f51b146105fa578063711a2e2814610626578063715018a61461064657600080fd5b8063586d3cf811610222578063586d3cf81461058e57806358c67635146105ad5780636b7f53ca146105cd57600080fd5b806352d1902d1461052d57806354fd4d501461054257600080fd5b8063437209a71161029f5780634c469d8c116102795780634c469d8c146104aa5780634d7a734e146104fa5780634f1ef2861461051a57600080fd5b8063437209a7146103d55780634716e9c51461046b57806348b6404d1461048b57600080fd5b806331d98b3f116102d057806331d98b3f146103425780633659cfe61461036f578063426234e41461038f57600080fd5b8063146faf77146102ec57806314dd317f1461030e575b600080fd5b3480156102f857600080fd5b5061030c6103073660046152ff565b6109b5565b005b34801561031a57600080fd5b5061032e610329366004615632565b610b06565b604051905181526020015b60405180910390f35b34801561034e57600080fd5b5061036261035d366004615574565b610b61565b6040516103399190615b80565b34801561037b57600080fd5b5061030c61038a3660046152e5565b610b97565b34801561039b57600080fd5b506040805180820182526000808252602091820152815180830190925260d05461ffff16825260d154908201526040516103399190615af5565b3480156103e157600080fd5b5061045b6103f0366004615846565b6040805160f09390931b7fffff000000000000000000000000000000000000000000000000000000000000166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b6040519015158152602001610339565b61047e6104793660046154e2565b610d52565b6040516103399190615a49565b34801561049757600080fd5b5060ce545b604051908152602001610339565b3480156104b657600080fd5b506104e16104c5366004615574565b600090815260d5602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610339565b34801561050657600080fd5b5061032e610515366004615632565b61128b565b61030c6105283660046153c0565b611325565b34801561053957600080fd5b5061049c6114b4565b34801561054e57600080fd5b50604080518082018252600581527f312e332e30000000000000000000000000000000000000000000000000000000602082015290516103399190615ac7565b34801561059a57600080fd5b5060d25467ffffffffffffffff166104e1565b3480156105b957600080fd5b5061045b6105c8366004615846565b611579565b3480156105d957600080fd5b506105ed6105e8366004615632565b61159c565b6040516103399190615b10565b34801561060657600080fd5b5060d45463ffffffff165b60405163ffffffff9091168152602001610339565b34801561063257600080fd5b506103626106413660046155a4565b6117a0565b34801561065257600080fd5b5061030c611816565b34801561066757600080fd5b5061067b610676366004615632565b61182a565b604051905163ffffffff168152602001610339565b34801561069c57600080fd5b5060c9546001600160a01b03165b6040516001600160a01b039091168152602001610339565b3480156106ce57600080fd5b506106e26106dd366004615632565b611858565b6040516103399190615bbb565b3480156106fb57600080fd5b5061070f61070a366004615632565b6119d5565b60405190516001600160a01b03168152602001610339565b34801561073357600080fd5b5061049c610742366004615665565b611a06565b34801561075357600080fd5b506033546001600160a01b03166106aa565b34801561077157600080fd5b50610362610780366004615574565b611a70565b34801561079157600080fd5b506103626107a0366004615574565b611b03565b3480156107b157600080fd5b506107ba611ba5565b60405161ffff9091168152602001610339565b3480156107d957600080fd5b506107e2611c2e565b6040516103399190615a11565b3480156107fb57600080fd5b5061036261080a3660046155a4565b611ca1565b34801561081b57600080fd5b5061036261082a366004615574565b611cce565b34801561083b57600080fd5b5061045b61084a366004615574565b600090815260d5602052604090205467ffffffffffffffff16151590565b34801561087457600080fd5b5061030c6108833660046155c5565b611cfe565b61030c61089636600461544c565b612018565b3480156108a757600080fd5b506108bb6108b6366004615574565b61212b565b6040516103399190615b71565b3480156108d457600080fd5b5060cf5461049c565b3480156108e957600080fd5b5061049c6108f836600461540c565b612308565b34801561090957600080fd5b50610929610918366004615632565b604080516020810190915290815290565b6040516103399190615ada565b34801561094257600080fd5b5061049c610951366004615574565b612473565b34801561096257600080fd5b5061049c612489565b34801561097757600080fd5b506397a6f304610611565b61030c61099036600461540c565b612494565b3480156109a157600080fd5b5061030c6109b03660046152e5565b6125f9565b600054610100900460ff16158080156109d55750600054600160ff909116105b806109ef5750303b1580156109ef575060005460ff166001145b610a665760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b6000805460ff191660011790558015610a89576000805461ff0019166101001790555b610a91612695565b610a9961271a565b610aab8b8b8b8b8b8b8b8b8b8b612797565b610ab3611816565b8015610af9576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050505050565b6040805160208101909152600081526000610b218382612a0b565b67ffffffffffffffff168252610b38600882615d07565b905080835114610b5b576040516397363b3560e01b815260040160405180910390fd5b50919050565b604080516080810182526000808252602082018190529181018290526060810191909152610b918261080a612489565b92915050565b306001600160a01b037f00000000000000000000000036825bf3fbdf5a29e2d5148bfe7dcf7b5639e320161415610c365760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610a5d565b7f00000000000000000000000036825bf3fbdf5a29e2d5148bfe7dcf7b5639e3206001600160a01b0316610c917f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614610d0d5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610a5d565b610d1681612a71565b610d4f8160005b6040519080825280601f01601f191660200182016040528015610d47576020820181803683370190505b506000612a79565b50565b60606000610d608888612308565b905080341015610d9c576040517f025dbdd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b508367ffffffffffffffff811115610dc457634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610e5457816020015b610e41604080516060808201835260008083528351608081018552818152602081810183905294810182905291820152909182019081526040805160808101825260008082526020828101829052928201819052606082015291015290565b815260200190600190039081610de25790505b50905060005b8681101561120a576004888883818110610e8457634e487b7160e01b600052603260045260246000fd5b9050602002810190610e969190615bd6565b9050118015610eea575063504e4155610ee2898984818110610ec857634e487b7160e01b600052603260045260246000fd5b9050602002810190610eda9190615bd6565b503560e01c90565b63ffffffff16145b156110d757600080610f2c8a8a85818110610f1557634e487b7160e01b600052603260045260246000fd5b9050602002810190610f279190615bd6565b612c2d565b90925090506000818015610f5057634e487b7160e01b600052602160045260246000fd5b14610f6e5760405163734fff6760e11b815260040160405180910390fd5b50600080366000610fb08d8d88818110610f9857634e487b7160e01b600052603260045260246000fd5b9050602002810190610faa9190615bd6565b87612cf4565b93985091965094509250905060005b8360ff168110156110ac576040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101829052906110088786868b612e3f565b91995092509050600061101c8f8f84612f54565b90508d81148061105657508a818151811061104757634e487b7160e01b600052603260045260246000fd5b60209081029190910101515115155b15611063575050506110a4565b825167ffffffffffffffff908116908e16811080159061108d57508c67ffffffffffffffff168111155b1561109f5761109f8c83858785612fa5565b505050505b600101610fbf565b508481146110cd5760405163734fff6760e11b815260040160405180910390fd5b5050505050611202565b606060006111158a8a858181106110fe57634e487b7160e01b600052603260045260246000fd5b90506020028101906111109190615bd6565b6131e9565b60e00151915060009050808061112a8461333a565b92509250925060005b828110156111fc576040848601015160209060006111528e8e84612f54565b90508c81148061118c575089818151811061117d57634e487b7160e01b600052603260045260246000fd5b60209081029190910101515115155b1561119d57505050928101926111f4565b60006111aa898988613469565b50805190915067ffffffffffffffff908116908e1681108015906111d857508c67ffffffffffffffff168111155b156111ea576111ea8c84868585612fa5565b5050509483019450505b600101611133565b50505050505b600101610e5a565b5060005b848110156112805781818151811061123657634e487b7160e01b600052603260045260246000fd5b602090810291909101015151611278576040517f45805f5d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60010161120e565b509695505050505050565b6040805160208101909152600081526000806112a78482612a0b565b90506112b4600883615d07565b915060006112c28584612a0b565b90506112cf600884615d07565b92506112e667ffffffffffffffff8216600a615d62565b6112fa9067ffffffffffffffff8416615e0a565b84528451831461131d576040516397363b3560e01b815260040160405180910390fd5b505050919050565b306001600160a01b037f00000000000000000000000036825bf3fbdf5a29e2d5148bfe7dcf7b5639e3201614156113c45760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610a5d565b7f00000000000000000000000036825bf3fbdf5a29e2d5148bfe7dcf7b5639e3206001600160a01b031661141f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b03161461149b5760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610a5d565b6114a482612a71565b6114b082826001612a79565b5050565b6000306001600160a01b037f00000000000000000000000036825bf3fbdf5a29e2d5148bfe7dcf7b5639e32016146115545760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610a5d565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b60d05460009061ffff8481169116148015611595575060d15482145b9392505050565b6115c8604080516080810190915280600081526020016000815260006020820152606060409091015290565b6000806115d58482613579565b905063ffffffff8116635054474d14611601576040516397363b3560e01b815260040160405180910390fd5b61160c600483615d07565b9150600061161a85846135df565b90508060ff16600181111561163f57634e487b7160e01b600052602160045260246000fd5b8490600181111561166057634e487b7160e01b600052602160045260246000fd5b9081600181111561168157634e487b7160e01b600052602160045260246000fd5b90525061168f600184615d07565b92506001845160018111156116b457634e487b7160e01b600052602160045260246000fd5b146116d2576040516363daeb7760e01b815260040160405180910390fd5b60006116de86856135df565b90508060ff16600681111561170357634e487b7160e01b600052602160045260246000fd5b8560200190600681111561172757634e487b7160e01b600052602160045260246000fd5b9081600681111561174857634e487b7160e01b600052602160045260246000fd5b905250611756600185615d07565b93506117628685613645565b61ffff166040860152611776600285615d07565b9350611791848588516117899190615e29565b8891906136ab565b60608601525092949350505050565b6040805160808101825260008082526020820181905291810182905260608101919091526117cd83611a70565b9050816117de4283606001516137d3565b1115610b91576040517f19abf40e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61181e6137f8565b6118286000613852565b565b60408051602081019091526000815260006118458382613579565b63ffffffff168252610b38600482615d07565b60408051602081019091526060815260008061187484826135df565b9050611881600183615d07565b91508060ff1667ffffffffffffffff8111156118ad57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156118f257816020015b60408051808201909152600080825260208201528152602001906001900390816118cb5790505b50835260005b8160ff168110156119ac5761190d8584613645565b845180518390811061192f57634e487b7160e01b600052603260045260246000fd5b602090810291909101015161ffff909116905261194d600284615d07565b925061195985846138b1565b845180518390811061197b57634e487b7160e01b600052603260045260246000fd5b602002602001015160200181815250506020836119989190615d07565b9250806119a481615e6c565b9150506118f8565b50818451146119ce576040516397363b3560e01b815260040160405180910390fd5b5050919050565b60408051602081019091526000815260006119f08382613917565b6001600160a01b03168252610b38601482615d07565b600081600001518260200151604051602001611a5392919060f09290921b7fffff000000000000000000000000000000000000000000000000000000000000168252600282015260220190565b604051602081830303815290604052805190602001209050919050565b60408051608081018252600080825260208083018281528385018381526060850184815287855260d590935294909220805467ffffffffffffffff808216938490526801000000000000000091829004600390810b810b900b9096526001820154600781810b810b900b865204909416909152909190610b5b57604051630295d7cd60e31b815260040160405180910390fd5b60408051608081018252600080825260208083018281528385018381526060850184815287855260d590935294909220805467ffffffffffffffff80821693849052680100000000000000008204600390810b810b900b9096526c010000000000000000000000008104600790810b810b900b8552600160a01b9004909416909152909190610b5b57604051630295d7cd60e31b815260040160405180910390fd5b6000611bb960c9546001600160a01b031690565b6001600160a01b0316639a8a05926040518163ffffffff1660e01b815260040160206040518083038186803b158015611bf157600080fd5b505afa158015611c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c29919061582a565b905090565b606060c9600301805480602002602001604051908101604052809291908181526020016000905b82821015611c985760008481526020908190206040805180820190915260028502909101805461ffff168252600190810154828401529083529092019101611c55565b50505050905090565b6040805160808101825260008082526020820181905291810182905260608101919091526117cd83611b03565b604080516080810182526000808252602082018190529181018290526060810191909152610b9182610641612489565b6000611d3f83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061398d92505050565b90506000611d508260e0015161159c565b9050611d5a611ba5565b61ffff16816040015161ffff1614158015611d7c5750604081015161ffff1615155b15611d9a576040516363daeb7760e01b815260040160405180910390fd5b600081602001516006811115611dc057634e487b7160e01b600052602160045260246000fd5b1415611e0657604081015161ffff16611dec576040516363daeb7760e01b815260040160405180910390fd5b611e01611dfc82606001516119d5565b613b6e565b612012565b600181602001516006811115611e2c57634e487b7160e01b600052602160045260246000fd5b1415611e5357611e01611e4e8260600151604080516020810190915290815290565b613b77565b600281602001516006811115611e7957634e487b7160e01b600052602160045260246000fd5b1415611e9457611e01611e8f8260600151611858565b613eaa565b600381602001516006811115611eba57634e487b7160e01b600052602160045260246000fd5b1415611ed557611e01611ed0826060015161128b565b614053565b600481602001516006811115611efb57634e487b7160e01b600052602160045260246000fd5b1415611f1657611e01611f118260600151610b06565b6140a5565b600581602001516006811115611f3c57634e487b7160e01b600052602160045260246000fd5b1415611f5b576040516397363b3560e01b815260040160405180910390fd5b600681602001516006811115611f8157634e487b7160e01b600052602160045260246000fd5b1415611ff957604081015161ffff16611fad576040516363daeb7760e01b815260040160405180910390fd5b611e01611fbd82606001516119d5565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506140e292505050565b6040516397363b3560e01b815260040160405180910390fd5b50505050565b8281146120385760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b838110156120f05782828281811061206357634e487b7160e01b600052603260045260246000fd5b9050602002016020810190612078919061588b565b67ffffffffffffffff166120c88686848181106120a557634e487b7160e01b600052603260045260246000fd5b90506020020135600090815260d5602052604090205467ffffffffffffffff1690565b67ffffffffffffffff1610156120e8576120e28787612494565b50612123565b60010161203b565b506040517fde2c57fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b61218a604080516060808201835260008083528351608081018552818152602081810183905294810182905291820152909182019081526040805160808101825260008082526020828101829052928201819052606082015291015290565b6040805160c08082018352600080835260208084018290528385018290526060808501839052608080860184905260a095860184905288845260d5835286842087519586018852805467ffffffffffffffff808216885268010000000000000000808304600390810b810b900b968901969096526c010000000000000000000000008204600790810b810b810b9a89019a909a52600160a01b9091048116938701939093526001015480880b880b90970b90850152940490931691810191909152805190915067ffffffffffffffff1661227757604051630295d7cd60e31b815260040160405180910390fd5b91815260408083015160208084018051600793840b840b9052606080870151825167ffffffffffffffff9182169085015283880180518451600391820b820b9089015289519451948316948401949094526080890151878901805191880b90970b905260a089015186519083169501949094529251845190830b90920b919094015293519051931692019190915290565b600080805b8381101561246157600485858381811061233757634e487b7160e01b600052603260045260246000fd5b90506020028101906123499190615bd6565b9050118015612383575063504e415561237b868684818110610ec857634e487b7160e01b600052603260045260246000fd5b63ffffffff16145b15612441576000806123ae878785818110610f1557634e487b7160e01b600052603260045260246000fd5b909250905060008180156123d257634e487b7160e01b600052602160045260246000fd5b146123f05760405163734fff6760e11b815260040160405180910390fd5b61242b87878581811061241357634e487b7160e01b600052603260045260246000fd5b90506020028101906124259190615bd6565b8461433a565b6124389060ff1685615d07565b9350505061244f565b61244c600183615d07565b91505b8061245981615e6c565b91505061230d565b5061246b81614371565b949350505050565b60008161247f60ce5490565b610b919190615e0a565b6000611c2960cf5490565b6000805b828110156125b15760048484838181106124c257634e487b7160e01b600052603260045260246000fd5b90506020028101906124d49190615bd6565b905011801561250e575063504e4155612506858584818110610ec857634e487b7160e01b600052603260045260246000fd5b63ffffffff16145b156125615761254d84848381811061253657634e487b7160e01b600052603260045260246000fd5b90506020028101906125489190615bd6565b614386565b61255a9060ff1683615d07565b91506125a9565b61259b84848381811061258457634e487b7160e01b600052603260045260246000fd5b90506020028101906125969190615bd6565b614604565b6125a6600183615d07565b91505b600101612498565b5060006125bd82614371565b905080341015612012576040517f025dbdd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6126016137f8565b6001600160a01b03811661267d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a5d565b610d4f81613852565b6001600160a01b03163b151590565b600054610100900460ff166127125760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a5d565b611828614616565b600054610100900460ff166118285760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a5d565b60c9805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038c161790558786146127df5760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b888110156129a257600060405180604001604052808c8c8581811061281757634e487b7160e01b600052603260045260246000fd5b905060200201602081019061282c919061580e565b61ffff1681526020018a8a8581811061285557634e487b7160e01b600052603260045260246000fd5b602090810292909201359092528251838201516040805160f09390931b7fffff00000000000000000000000000000000000000000000000000000000000016838501526022808401929092528051808403909201825260429092018252805190830120600090815260cd9092529020549192505060ff16156128ea5760405163a9cb9e0d60e01b815260040160405180910390fd5b600160cd60006128f984611a06565b81526020808201929092526040016000908120805460ff19169315159390931790925560cc8054600181018255925282517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebe6002909302928301805461ffff191661ffff90921691909117905591909101517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebf909101558061299a81615e6c565b9150506127e2565b506040805180820190915261ffff86168082526020820186905260d0805461ffff1916909117905560d185905560d2805467ffffffffffffffff191667ffffffffffffffff8616179055506129f68260cf55565b6129ff8160ce55565b50505050505050505050565b6000612a18826008615d07565b83511015612a685760405162461bcd60e51b815260206004820152601460248201527f746f55696e7436345f6f75744f66426f756e64730000000000000000000000006044820152606401610a5d565b50016008015190565b610d4f6137f8565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612ab157612aac8361469c565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015612aea57600080fd5b505afa925050508015612b1a575060408051601f3d908101601f19168201909252612b179181019061558c565b60015b612b8c5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401610a5d565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612c215760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401610a5d565b50612aac838383614767565b60046000833560e01c63504e41558114612c5a5760405163734fff6760e11b815260040160405180910390fd5b60018084019386013560f81c908114612c865760405163734fff6760e11b815260040160405180910390fd5b50508184016001013560f890811c9092016002818101939186010135901c60ff168015612cc357634e487b7160e01b600052602160045260246000fd5b60019290920191905081831015612ced5760405163734fff6760e11b815260040160405180910390fd5b9250929050565b600080803681612d0888888880820361478c565b600296509092509050813560f01c60606000612d2e612d2986868b8761478c565b6147b6565b60e0015160048082015161ffff86169a909a01999193509150634155575663ffffffff821614612d715760405163734fff6760e11b815260040160405180910390fd5b8183016001015160009060ff168015612d9a57634e487b7160e01b600052602160045260246000fd5b60019093019290506000818015612dc157634e487b7160e01b600052602160045260246000fd5b14612ddf5760405163734fff6760e11b815260040160405180910390fd5b602c848401015184516c0100000000000000000000000090910460601b9950602090930192831115612e245760405163734fff6760e11b815260040160405180910390fd5b5050600188019b969a505050509381013560f81c9550935050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101829052600283019282903690829088013560f01c612e8d8989898461478c565b925092508061ffff16870196506000612eaa8a8a8a8e8888614940565b9750905080612ecc5760405163734fff6760e11b815260040160405180910390fd5b6000843560f81c8015612eef57634e487b7160e01b600052602160045260246000fd5b90506000818015612f1057634e487b7160e01b600052602160045260246000fd5b1415612f2c57612f22858560016149f2565b9097509550612f45565b60405163734fff6760e11b815260040160405180910390fd5b50505050509450945094915050565b6000805b8381101561246b5782858583818110612f8157634e487b7160e01b600052603260045260246000fd5b905060200201351415612f935761246b565b80612f9d81615e6c565b915050612f58565b82858581518110612fc657634e487b7160e01b600052603260045260246000fd5b602002602001015160000181815250508160400151858581518110612ffb57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516000019060070b908160070b81525050816060015185858151811061303c57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516020019067ffffffffffffffff16908167ffffffffffffffff1681525050816020015185858151811061308b57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516040019060030b908160030b81525050808585815181106130c857634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516060018181525050816080015185858151811061310157634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516000019060070b908160070b815250508160a0015185858151811061314257634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516020019067ffffffffffffffff16908167ffffffffffffffff1681525050816020015185858151811061319157634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516040019060030b908160030b81525050808585815181106131ce57634e487b7160e01b600052603260045260246000fd5b60200260200101516040015160600181815250505050505050565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018190526101008201839052610120820152610140810191909152600061325560c9546001600160a01b031690565b6001600160a01b031663c0fd8bde85856040518363ffffffff1660e01b8152600401613282929190615a98565b60006040518083038186803b15801561329a57600080fd5b505afa1580156132ae573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526132d691908101906156bc565b509092509050806132fa57604051632acbe91560e01b815260040160405180910390fd5b5061330481614a8c565b610b91576040517fe60dce7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080808061334d858260049101015190565b90506004840193508063ffffffff1663503257481461337f5760405163734fff6760e11b815260040160405180910390fd5b6002858501810151940193600361ffff8216146133af5760405163734fff6760e11b815260040160405180910390fd5b60028501945060006133c5878760029101015190565b905060028601955060006133dd888860019101015190565b90508161ffff16870196508060ff1660021461340c5760405163734fff6760e11b815260040160405180910390fd5b505050508284016002015161ffff169150600283019250613431848460029101015190565b61ffff16905060028301925081810283018451146134625760405163734fff6760e11b815260040160405180910390fd5b9193909250565b6040805160c081018252600080825260208201818152828401828152606084018381526080850184815260a08601948552888a01968701516048880151600790810b810b909452605088015167ffffffffffffffff9081169093526054880151600390810b900b909452605c870151830b90920b909152606485015181169092526065840151607d94850151909216835291929060ff8116600114156135145760188201915061354e565b8582018701600881015167ffffffffffffffff90811686526010820151600790810b900b6040870152601891820151166060860152909101905b50838111156135705760405163734fff6760e11b815260040160405180910390fd5b50935093915050565b6000613586826004615d07565b835110156135d65760405162461bcd60e51b815260206004820152601460248201527f746f55696e7433325f6f75744f66426f756e64730000000000000000000000006044820152606401610a5d565b50016004015190565b60006135ec826001615d07565b8351101561363c5760405162461bcd60e51b815260206004820152601360248201527f746f55696e74385f6f75744f66426f756e6473000000000000000000000000006044820152606401610a5d565b50016001015190565b6000613652826002615d07565b835110156136a25760405162461bcd60e51b815260206004820152601460248201527f746f55696e7431365f6f75744f66426f756e64730000000000000000000000006044820152606401610a5d565b50016002015190565b6060816136b981601f615d07565b10156137075760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610a5d565b6137118284615d07565b845110156137615760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610a5d565b60608215801561378057604051915060008252602082016040526137ca565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156137b95780518352602092830192016137a1565b5050858452601f01601f1916604052505b50949350505050565b6000818311156137ee576137e78284615e29565b9050610b91565b6137e78383615e29565b6033546001600160a01b031633146118285760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a5d565b603380546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006138be826020615d07565b8351101561390e5760405162461bcd60e51b815260206004820152601560248201527f746f427974657333325f6f75744f66426f756e647300000000000000000000006044820152606401610a5d565b50016020015190565b6000613924826014615d07565b835110156139745760405162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606401610a5d565b5001602001516c01000000000000000000000000900490565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820181905261010082018390526101208201526101408101919091526000806139fa60c9546001600160a01b031690565b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b8152600401613a259190615ac7565b60006040518083038186803b158015613a3d57600080fd5b505afa158015613a51573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a7991908101906156bc565b509150915080613a9c57604051632acbe91560e01b815260040160405180910390fd5b613aae82606001518360800151611579565b613ae4576040517f360f2d8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60d25467ffffffffffffffff1667ffffffffffffffff168260a0015167ffffffffffffffff1611613b41576040517f88d1b84700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a082015160d2805467ffffffffffffffff191667ffffffffffffffff9092169190911790555092915050565b610d4f81614b06565b6000613bab6040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b9050600080613bc260c9546001600160a01b031690565b84516040517fc0fd8bde0000000000000000000000000000000000000000000000000000000081526001600160a01b03929092169163c0fd8bde91613c0991600401615ac7565b60006040518083038186803b158015613c2157600080fd5b505afa158015613c35573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c5d91908101906156bc565b509150915080613c8057604051632acbe91560e01b815260040160405180910390fd5b6000613c8f8360e0015161159c565b9050613c99611ba5565b61ffff16816040015161ffff1614158015613cbb5750604081015161ffff1615155b15613cd9576040516363daeb7760e01b815260040160405180910390fd5b600581602001516006811115613cff57634e487b7160e01b600052602160045260246000fd5b14613d1d576040516397363b3560e01b815260040160405180910390fd5b6000613d2c826060015161182a565b805190915063ffffffff16613d4660d45463ffffffff1690565b63ffffffff1610613d83576040517f88d1b84700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160d480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff909216919091179055604080518082018252606086015161ffff168082526080870151602080840182905260d0805461ffff19168417905560d182905560a089015160d2805467ffffffffffffffff191667ffffffffffffffff90921691909117905584518086018652600080825290820152845180860190955291845290830152907f6bce23ef3d34e51710fe4700b43ba5f1733a6215c883f384671a4ece3ea8aa2090879060d25460408051845161ffff908116825260209586015186830152845116918101919091529290910151606083015267ffffffffffffffff16608082015260a0015b60405180910390a150505050505050565b6000613eb4611c2e565b905060005b8151811015613f2c57600060c96004016000613efb858581518110613eee57634e487b7160e01b600052603260045260246000fd5b6020026020010151611a06565b81526020810191909152604001600020805460ff1916911515919091179055613f25600182615d07565b9050613eb9565b50613f3960cc600061509d565b60005b82515181101561400e578251805160cc919083908110613f6c57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015182546001808201855560009485528385208351600290930201805461ffff191661ffff90931692909217825591909201519181019190915584518051919260cd929091613fdd9186908110613eee57634e487b7160e01b600052603260045260246000fd5b81526020810191909152604001600020805460ff19169115159190911790558061400681615e6c565b915050613f3c565b507fd451e0fcb7c5b9e13de533604d158069dad159841c45f39f09d379bfc423080d81614039611c2e565b604051614047929190615a24565b60405180910390a15050565b600061405e60ce5490565b825160ce5590507f74dbbbe280ef27b79a8a0c449d5ae2ba7a31849103241d0f98df70bbc9d03e378161409060ce5490565b60408051928352602083019190915201614047565b60006140b060cf5490565b825160cf5590507fcdb88a22f82ddd76115ab7c66cf08eb1e40afe80c9b31017eb2cbdb1570b33ae8161409060cf5490565b60006140f660c9546001600160a01b031690565b835160c9805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0390921691821790556040517fc0fd8bde00000000000000000000000000000000000000000000000000000000815291925060009182919063c0fd8bde90614166908790600401615ac7565b60006040518083038186803b15801561417e57600080fd5b505afa158015614192573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526141ba91908101906156bc565b5091509150806141dd576040516397363b3560e01b815260040160405180910390fd5b6141ef82606001518360800151611579565b61420c576040516397363b3560e01b815260040160405180910390fd5b60d25467ffffffffffffffff1667ffffffffffffffff168260a0015167ffffffffffffffff1614614250576040516309e9f6c160e11b815260040160405180910390fd5b600061425f8360e0015161159c565b905060068160200151600681111561428757634e487b7160e01b600052602160045260246000fd5b146142a5576040516309e9f6c160e11b815260040160405180910390fd5b60006142b482606001516119d5565b875181519192506001600160a01b039182169116146142e6576040516309e9f6c160e11b815260040160405180910390fd5b7fd495c4e5b386d59bccca38a2277b5d70a0f5e47d7b6587a45a6f5aca221a31258561431a60c9546001600160a01b031690565b604080516001600160a01b03938416815292909116602083015201613e99565b60008382013560f01c61434e600284615d07565b925061435e61ffff821684615d07565b92508483013560f81c5b95945050505050565b600061437c60ce5490565b610b919083615e0a565b60008060006143958585612c2d565b909250905060008180156143b957634e487b7160e01b600052602160045260246000fd5b146143d75760405163734fff6760e11b815260040160405180910390fd5b6000803660006143e8898988612cf4565b919a50929650909450909250905060005b8760ff168110156145d7576040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101829052906144428686868a612e3f565b600081815260d560205260409020548251939a50919450925067ffffffffffffffff90811691168110156145cc57600082815260d560209081526040918290208551815487840151888601516060808b015167ffffffffffffffff9586166bffffffffffffffffffffffff1990951685176801000000000000000063ffffffff60039690960b959095168502177fffffffff00000000000000000000000000000000ffffffffffffffffffffffff166c01000000000000000000000000600794850b808916919091027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff1691909117600160a01b92881692830217885560808d01516001909801805460a08f01519990950b88167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090951694909417979096169093029590951790558551918252938101919091529283019190915283917fd06a6b7f4918494b3719217d1802786c1f5112a6c1d88fe2cfec00b4584f6aec910160405180910390a25b5050506001016143f9565b508381146145f85760405163734fff6760e11b815260040160405180910390fd5b50505050505092915050565b6114b061461183836131e9565b614c56565b600054610100900460ff166146935760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a5d565b61182833613852565b6001600160a01b0381163b6147195760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610a5d565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b61477083614e78565b60008251118061477d5750805b15612aac576120128383614eb8565b36600085848661479c8683615d07565b926147a993929190615cdf565b9150915094509492505050565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e082018190526101008201839052610120820152610140810191909152600061482260c9546001600160a01b031690565b6001600160a01b031663c0fd8bde85856040518363ffffffff1660e01b815260040161484f929190615a98565b60006040518083038186803b15801561486757600080fd5b505afa15801561487b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526148a391908101906156bc565b509092509050806148c757604051632acbe91560e01b815260040160405180910390fd5b50613304816060015182608001516040805160f09390931b7fffff000000000000000000000000000000000000000000000000000000000000166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b600080600061498485858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250614fba92505050565b600188019790915089013560f81c60005b8160ff168110156149cc5760148901988b01356bffffffffffffffffffffffff19166149c18482614fed565b935050600101614995565b50506bffffffffffffffffffffffff199081169516949094149794965093945050505050565b6040805160c08082018352838601602081810135831c600790810b810b958501959095526028820135831c6060850152603082013560e01c600390810b900b908401526034810135821c83526044810135821c840b90930b6080830152604c830135901c60a0820152605490920191903583831115614a845760405163734fff6760e11b815260040160405180910390fd5b935093915050565b6000610b91826060015183608001516040805160f09390931b7fffff000000000000000000000000000000000000000000000000000000000000166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b6000614b397f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b8251909150614b49906000610d1d565b306001600160a01b031663e3795cc16040518163ffffffff1660e01b815260040160206040518083038186803b158015614b8257600080fd5b505afa158015614b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bba9190615871565b63ffffffff166397a6f30414614be3576040516397363b3560e01b815260040160405180910390fd5b7f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a4981614c367f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b604080516001600160a01b03938416815292909116602083015201614047565b60e081015160008080614c688461333a565b92509250925060005b82811015614e1e57600080614c87878786613469565b600081815260d5602052604090205482519887019892945090925067ffffffffffffffff9081169116811015614e1357600082815260d560209081526040918290208551815487840151888601516060808b015167ffffffffffffffff9586166bffffffffffffffffffffffff1990951685176801000000000000000063ffffffff60039690960b959095168502177fffffffff00000000000000000000000000000000ffffffffffffffffffffffff166c01000000000000000000000000600794850b808916919091027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff1691909117600160a01b92881692830217885560808d01516001909801805460a08f01519990950b88167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090951694909417979096169093029590951790558551918252938101919091529283019190915283917fd06a6b7f4918494b3719217d1802786c1f5112a6c1d88fe2cfec00b4584f6aec910160405180910390a25b505050600101614c71565b50606085015160a08601516040805161ffff909316835267ffffffffffffffff90911660208301527f943f0e8a16c19895fb87cbeb1a349ed86d7f31923089dd36c1a1ed5e300f267b910160405180910390a15050505050565b614e818161469c565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b614f375760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e747261637400000000000000000000000000000000000000000000000000006064820152608401610a5d565b600080846001600160a01b031684604051614f5291906159aa565b600060405180830381855af49150503d8060008114614f8d576040519150601f19603f3d011682016040523d82523d6000602084013e614f92565b606091505b50915091506143688282604051806060016040528060278152602001615ef06027913961505f565b6000610b91600083604051602001614fd39291906159c6565b604051602081830303815290604052805160209091012090565b60006bffffffffffffffffffffffff19808316908416111561500d579091905b6040517f010000000000000000000000000000000000000000000000000000000000000060208201526bffffffffffffffffffffffff1980851660218301528316603582015261159590604901614fd3565b6060831561506e575081611595565b61159583838151156150835781518083602001fd5b8060405162461bcd60e51b8152600401610a5d9190615ac7565b5080546000825560020290600052602060002090810190610d4f91905b808211156150da57805461ffff19168155600060018201556002016150ba565b5090565b80356001600160a01b03811681146150f557600080fd5b919050565b60008083601f84011261510b578182fd5b50813567ffffffffffffffff811115615122578182fd5b6020830191508360208260051b8501011115612ced57600080fd5b600082601f83011261514d578081fd5b8151602067ffffffffffffffff82111561516957615169615eb3565b615177818360051b01615c86565b80838252828201915082860187848660071b8901011115615196578586fd5b855b858110156151f957608080838b0312156151b0578788fd5b6151b8615c39565b83518152868401518782015260406151d18186016152d4565b9082015260606151e28582016152d4565b908201528552938501939190910190600101615198565b5090979650505050505050565b805180151581146150f557600080fd5b600082601f830112615226578081fd5b813561523961523482615cb7565b615c86565b81815284602083860101111561524d578283fd5b816020850160208301379081016020019190915292915050565b600082601f830112615277578081fd5b815161528561523482615cb7565b818152846020838601011115615299578283fd5b61246b826020830160208701615e40565b80516150f581615ec9565b805163ffffffff811681146150f557600080fd5b80516150f581615ed9565b805160ff811681146150f557600080fd5b6000602082840312156152f6578081fd5b611595826150de565b6000806000806000806000806000806101008b8d03121561531e578586fd5b6153278b6150de565b995060208b013567ffffffffffffffff80821115615343578788fd5b61534f8e838f016150fa565b909b50995060408d0135915080821115615367578788fd5b506153748d828e016150fa565b90985096505060608b013561538881615ec9565b945060808b0135935060a08b013561539f81615ed9565b8093505060c08b0135915060e08b013590509295989b9194979a5092959850565b600080604083850312156153d2578182fd5b6153db836150de565b9150602083013567ffffffffffffffff8111156153f6578182fd5b61540285828601615216565b9150509250929050565b6000806020838503121561541e578182fd5b823567ffffffffffffffff811115615434578283fd5b615440858286016150fa565b90969095509350505050565b60008060008060008060608789031215615464578384fd5b863567ffffffffffffffff8082111561547b578586fd5b6154878a838b016150fa565b9098509650602089013591508082111561549f578586fd5b6154ab8a838b016150fa565b909650945060408901359150808211156154c3578384fd5b506154d089828a016150fa565b979a9699509497509295939492505050565b600080600080600080608087890312156154fa578384fd5b863567ffffffffffffffff80821115615511578586fd5b61551d8a838b016150fa565b90985096506020890135915080821115615535578586fd5b5061554289828a016150fa565b909550935050604087013561555681615ed9565b9150606087013561556681615ed9565b809150509295509295509295565b600060208284031215615585578081fd5b5035919050565b60006020828403121561559d578081fd5b5051919050565b600080604083850312156155b6578182fd5b50508035926020909101359150565b600080602083850312156155d7578182fd5b823567ffffffffffffffff808211156155ee578384fd5b818501915085601f830112615601578384fd5b81358181111561560f578485fd5b866020828501011115615620578485fd5b60209290920196919550909350505050565b600060208284031215615643578081fd5b813567ffffffffffffffff811115615659578182fd5b61246b84828501615216565b600060408284031215615676578081fd5b6040516040810181811067ffffffffffffffff8211171561569957615699615eb3565b60405282356156a781615ec9565b81526020928301359281019290925250919050565b6000806000606084860312156156d0578081fd5b835167ffffffffffffffff808211156156e7578283fd5b9085019061016082880312156156fb578283fd5b615703615c62565b61570c836152d4565b815261571a602084016152b5565b602082015261572b604084016152b5565b604082015261573c606084016152aa565b60608201526080830151608082015261575760a084016152c9565b60a082015261576860c084016152d4565b60c082015260e08301518281111561577e578485fd5b61578a89828601615267565b60e08301525061010061579e8185016152b5565b9082015261012083810151838111156157b5578586fd5b6157c18a82870161513d565b9183019190915250610140838101519082015294506157e260208701615206565b935060408601519150808211156157f7578283fd5b5061580486828701615267565b9150509250925092565b60006020828403121561581f578081fd5b813561159581615ec9565b60006020828403121561583b578081fd5b815161159581615ec9565b60008060408385031215615858578182fd5b823561586381615ec9565b946020939093013593505050565b600060208284031215615882578081fd5b611595826152b5565b60006020828403121561589c578081fd5b813561159581615ed9565b6000815180845260208085019450808401835b838110156158ee576158db878351805161ffff168252602090810151910152565b60409690960195908201906001016158ba565b509495945050505050565b60008151808452615911816020860160208601615e40565b601f01601f19169290920160200192915050565b80518252602081015161596c6020840182805160070b825267ffffffffffffffff6020820151166020830152604081015160030b6040830152606081015160608301525050565b50604090810151805160070b60a0840152602081015167ffffffffffffffff1660c08401529081015160030b60e08301526060015161010090910152565b600082516159bc818460208701615e40565b9190910192915050565b7fff000000000000000000000000000000000000000000000000000000000000008360f81b16815260008251615a03816001850160208701615e40565b919091016001019392505050565b60208152600061159560208301846158a7565b604081526000615a3760408301856158a7565b828103602084015261436881856158a7565b6020808252825182820181905260009190848201906040850190845b81811015615a8c57615a78838551615925565b928401926101209290920191600101615a65565b50909695505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60208152600061159560208301846158f9565b602081526000825160208084015261246b60408401826158f9565b815161ffff1681526020808301519082015260408101610b91565b602081526000825160028110615b2857615b28615e9d565b80602084015250602083015160078110615b4457615b44615e9d565b8060408401525061ffff6040840151166060830152606083015160808084015261246b60a08401826158f9565b6101208101610b918284615925565b815160070b815260208083015167ffffffffffffffff169082015260408083015160030b908201526060808301519082015260808101610b91565b602081526000825160208084015261246b60408401826158a7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615c0a578283fd5b83018035915067ffffffffffffffff821115615c24578283fd5b602001915036819003821315612ced57600080fd5b6040516080810167ffffffffffffffff81118282101715615c5c57615c5c615eb3565b60405290565b604051610160810167ffffffffffffffff81118282101715615c5c57615c5c615eb3565b604051601f8201601f1916810167ffffffffffffffff81118282101715615caf57615caf615eb3565b604052919050565b600067ffffffffffffffff821115615cd157615cd1615eb3565b50601f01601f191660200190565b60008085851115615cee578182fd5b83861115615cfa578182fd5b5050820193919092039150565b60008219821115615d1a57615d1a615e87565b500190565b600181815b80851115615d5a578160001904821115615d4057615d40615e87565b80851615615d4d57918102915b93841c9390800290615d24565b509250929050565b60006115958383600082615d7857506001610b91565b81615d8557506000610b91565b8160018114615d9b5760028114615da557615dc1565b6001915050610b91565b60ff841115615db657615db6615e87565b50506001821b610b91565b5060208310610133831016604e8410600b8410161715615de4575081810a610b91565b615dee8383615d1f565b8060001904821115615e0257615e02615e87565b029392505050565b6000816000190483118215151615615e2457615e24615e87565b500290565b600082821015615e3b57615e3b615e87565b500390565b60005b83811015615e5b578181015183820152602001615e43565b838111156120125750506000910152565b6000600019821415615e8057615e80615e87565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b61ffff81168114610d4f57600080fd5b67ffffffffffffffff81168114610d4f57600080fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122099b939a0e68f7cf23dd87f1d08ae171925bb84265dfec2ec4a23e360576bf68364736f6c63430008040033
Deployed Bytecode Sourcemap
184075:2225:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;184208:821;;;;;;;;;;-1:-1:-1;184208:821:0;;;;;:::i;:::-;;:::i;:::-;;154453:369;;;;;;;;;;-1:-1:-1;154453:369:0;;;;;:::i;:::-;;:::i;:::-;;;31549:13:1;;31531:32;;31519:2;31504:18;154453:369:0;;;;;;;;32402:189;;;;;;;;;;-1:-1:-1;32402:189:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;142706:200::-;;;;;;;;;;-1:-1:-1;142706:200:0;;;;;:::i;:::-;;:::i;68556:177::-;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;68691:34:0;;;;;;;;68698:27;68691:34;;;;;;;;;;;68556:177;;;;;;:::i;67352:421::-;;;;;;;;;;-1:-1:-1;67352:421:0;;;;;:::i;:::-;67597:134;;;15884:3:1;15880:16;;;;15898:66;15876:89;67597:134:0;;;;15864:102:1;;;;15982:11;;;;15975:27;;;;67597:134:0;;;;;;;;;;16018:12:1;;;;67597:134:0;;67565:185;;;;;;;;;-1:-1:-1;67522:243:0;;;:24;:243;;;;;;;;;67352:421;;;;19348:14:1;;19341:22;19323:41;;19311:2;19296:18;67352:421:0;19278:92:1;103327:7480:0;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;68741:112::-;;;;;;;;;;-1:-1:-1;68818:27:0;;68741:112;;;19521:25:1;;;19509:2;19494:18;68741:112:0;19476:76:1;66973:167:0;;;;;;;;;;-1:-1:-1;66973:167:0;;;;;:::i;:::-;67063:6;67089:31;;;:22;:31;;;;;:43;;;;66973:167;;;;33769:18:1;33757:31;;;33739:50;;33727:2;33712:18;66973:167:0;33694:101:1;153885:481:0;;;;;;;;;;-1:-1:-1;153885:481:0;;;;;:::i;:::-;;:::i;143165:225::-;;;;;;:::i;:::-;;:::i;142384:133::-;;;;;;;;;;;;;:::i;113077:88::-;;;;;;;;;;-1:-1:-1;113143:14:0;;;;;;;;;;;;;;;;113077:88;;;;113143:14;113077:88;:::i;68235:134::-;;;;;;;;;;-1:-1:-1;68324:37:0;;;;68235:134;;67781:344;;;;;;;;;;-1:-1:-1;67781:344:0;;;;;:::i;:::-;;:::i;150453:1111::-;;;;;;;;;;-1:-1:-1;150453:1111:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;68985:124::-;;;;;;;;;;-1:-1:-1;69069:32:0;;;;68985:124;;;33572:10:1;33560:23;;;33542:42;;33530:2;33515:18;68985:124:0;33497:93:1;33622:330:0;;;;;;;;;;-1:-1:-1;33622:330:0;;;;;:::i;:::-;;:::i;147333:103::-;;;;;;;;;;;;;:::i;152510:457::-;;;;;;;;;;-1:-1:-1;152510:457:0;;;;;:::i;:::-;;:::i;:::-;;;30894:13:1;;30909:10;30890:30;30872:49;;30860:2;30845:18;152510:457:0;30827:100:1;66672:104:0;;;;;;;;;;-1:-1:-1;66752:6:0;:15;-1:-1:-1;;;;;66752:15:0;66672:104;;;-1:-1:-1;;;;;17133:55:1;;;17115:74;;17103:2;17088:18;66672:104:0;17070:125:1;153054:752:0;;;;;;;;;;-1:-1:-1;153054:752:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;151652:374::-;;;;;;;;;;-1:-1:-1;151652:374:0;;;;;:::i;:::-;;:::i;:::-;;;32095:13:1;;-1:-1:-1;;;;;32091:62:1;32073:81;;32061:2;32046:18;151652:374:0;32028:132:1;67148:196:0;;;;;;;;;;-1:-1:-1;67148:196:0;;;;;:::i;:::-;;:::i;146685:87::-;;;;;;;;;;-1:-1:-1;146758:6:0;;-1:-1:-1;;;;;146758:6:0;146685:87;;99621:439;;;;;;;;;;-1:-1:-1;99621:439:0;;;;;:::i;:::-;;:::i;98918:430::-;;;;;;;;;;-1:-1:-1;98918:430:0;;;;;:::i;:::-;;:::i;68133:94::-;;;;;;;;;;;;;:::i;:::-;;;32657:6:1;32645:19;;;32627:38;;32615:2;32600:18;68133:94:0;32582:89:1;68377:171:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;33043:324::-;;;;;;;;;;-1:-1:-1;33043:324:0;;;;;:::i;:::-;;:::i;32599:195::-;;;;;;;;;;-1:-1:-1;32599:195:0;;;;;:::i;:::-;;:::i;112809:136::-;;;;;;;;;;-1:-1:-1;112809:136:0;;;;;:::i;:::-;112876:4;67089:31;;;:22;:31;;;;;:43;;;112901:35;;;112809:136;176258:1957;;;;;;;;;;-1:-1:-1;176258:1957:0;;;;;:::i;:::-;;:::i;97882:763::-;;;;;;:::i;:::-;;:::i;112025:776::-;;;;;;;;;;-1:-1:-1;112025:776:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;68861:116::-;;;;;;;;;;-1:-1:-1;68940:29:0;;68861:116;;90800:1002;;;;;;;;;;-1:-1:-1;90800:1002:0;;;;;:::i;:::-;;:::i;152136:264::-;;;;;;;;;;-1:-1:-1;152136:264:0;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;152362:30:0;;;-1:-1:-1;152136:264:0;;;;;;;;:::i;90631:161::-;;;;;;;;;;-1:-1:-1;90631:161:0;;;;;:::i;:::-;;:::i;112953:116::-;;;;;;;;;;;;;:::i;185483:96::-;;;;;;;;;;-1:-1:-1;185561:10:0;185483:96;;89693:846;;;;;;:::i;:::-;;:::i;147591:201::-;;;;;;;;;;-1:-1:-1;147591:201:0;;;;;:::i;:::-;;:::i;184208:821::-;124712:19;124735:13;;;;;;124734:14;;124782:34;;;;-1:-1:-1;124800:12:0;;124815:1;124800:12;;;;:16;124782:34;124781:108;;;-1:-1:-1;124861:4:0;114561:19;:23;;;124822:66;;-1:-1:-1;124871:12:0;;;;;:17;124822:66;124759:204;;;;-1:-1:-1;;;124759:204:0;;24217:2:1;124759:204:0;;;24199:21:1;24256:2;24236:18;;;24229:30;24295:34;24275:18;;;24268:62;24366:16;24346:18;;;24339:44;24400:19;;124759:204:0;;;;;;;;;124974:12;:16;;-1:-1:-1;;124974:16:0;124989:1;124974:16;;;125001:67;;;;125036:13;:20;;-1:-1:-1;;125036:20:0;;;;;125001:67;184604:16:::1;:14;:16::i;:::-;184631:24;:22;:24::i;:::-;184668:321;184699:8;184722:25;;184762:26;;184803:24;184842;184881:25;184921:22;184958:20;184668:16;:321::i;:::-;185002:19;:17;:19::i;:::-;125094:14:::0;125090:102;;;125141:5;125125:21;;-1:-1:-1;;125125:21:0;;;125166:14;;-1:-1:-1;20635:36:1;;125166:14:0;;20623:2:1;20608:18;125166:14:0;;;;;;;125090:102;184208:821;;;;;;;;;;;:::o;154453:369::-;-1:-1:-1;;;;;;;;;;;;154600:10:0;154656:30;:14;154600:10;154656:23;:30::i;:::-;154648:39;;154627:60;;154698:10;154707:1;154698:10;;:::i;:::-;;;154750:5;154725:14;:21;:30;154721:93;;154777:37;;-1:-1:-1;;;154777:37:0;;;;;;;;;;;154721:93;154453:369;;;;:::o;32402:189::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32538:45:0;32558:2;32562:20;:18;:20::i;32538:45::-;32531:52;32402:189;-1:-1:-1;;32402:189:0:o;142706:200::-;141245:4;-1:-1:-1;;;;;141254:6:0;141237:23;;;141229:80;;;;-1:-1:-1;;;141229:80:0;;21515:2:1;141229:80:0;;;21497:21:1;21554:2;21534:18;;;21527:30;21593:34;21573:18;;;21566:62;21664:14;21644:18;;;21637:42;21696:19;;141229:80:0;21487:234:1;141229:80:0;141352:6;-1:-1:-1;;;;;141328:30:0;:20;132876:66;133237:65;-1:-1:-1;;;;;133237:65:0;;133157:153;141328:20;-1:-1:-1;;;;;141328:30:0;;141320:87;;;;-1:-1:-1;;;141320:87:0;;22277:2:1;141320:87:0;;;22259:21:1;22316:2;22296:18;;;22289:30;22355:34;22335:18;;;22328:62;22426:14;22406:18;;;22399:42;22458:19;;141320:87:0;22249:234:1;141320:87:0;142790:36:::1;142808:17;142790;:36::i;:::-;142837:61;142859:17:::0;142888:1:::1;142878:12;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;-1:-1:-1;142878:12:0::1;;142892:5;142837:21;:61::i;:::-;142706:200:::0;:::o;103327:7480::-;103576:41;103650:16;103669:24;103682:10;;103669:12;:24::i;:::-;103650:43;;103724:11;103712:9;:23;103708:64;;;103744:28;;;;;;;;;;;;;;103708:64;-1:-1:-1;103860:8:0;103832:44;;;;;;-1:-1:-1;;;103832:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103832:44:0;;;;;;;;;;;;;;;;;103819:57;;103896:6;103891:6687;103908:21;;;103891:6687;;;104004:1;103981:10;;103992:1;103981:13;;;;;-1:-1:-1;;;103981:13:0;;;;;;;;;;;;;;;;;;;;:::i;:::-;:20;;:24;:140;;;;-1:-1:-1;75497:10:0;104030:49;104062:10;;104073:1;104062:13;;;;;-1:-1:-1;;;104062:13:0;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;37283:40:0;37278:3;37274:50;;37086:284;104030:49;:91;;;103981:140;103955:6608;;;104164:11;104225:21;104381:109;104450:10;;104461:1;104450:13;;;;;-1:-1:-1;;;104450:13:0;;;;;;;;;;;;;;;;;;;;:::i;:::-;104381:38;:109::i;:::-;104273:217;;-1:-1:-1;104273:217:0;-1:-1:-1;104537:25:0;104523:10;:39;;;;-1:-1:-1;;;104523:39:0;;;;;;;;;;104519:141;;104602:30;;-1:-1:-1;;;104602:30:0;;;;;;;;;;;104519:141;103955:6608;104707:14;104744:16;104783:22;;104991:173;105095:10;;105106:1;105095:13;;;;;-1:-1:-1;;;105095:13:0;;;;;;;;;;;;;;;;;;;;:::i;:::-;105135:6;104991:77;:173::i;:::-;104828:336;;-1:-1:-1;104828:336:0;;-1:-1:-1;104828:336:0;-1:-1:-1;104828:336:0;-1:-1:-1;104828:336:0;-1:-1:-1;105194:6:0;105189:2040;105210:10;105206:14;;:1;:14;105189:2040;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105504:170:0;105566:6;105603:7;;105641:6;105504:31;:170::i;:::-;105364:310;;-1:-1:-1;105364:310:0;-1:-1:-1;105364:310:0;-1:-1:-1;105809:6:0;105818:37;105837:8;;105364:310;105818:18;:37::i;:::-;105809:46;-1:-1:-1;106079:20:0;;;;:45;;;106103:10;106114:1;106103:13;;;;;;-1:-1:-1;;;106103:13:0;;;;;;;;;;;;;;;;;;;:16;:21;;106079:45;106075:126;;;106161:8;;;;;106075:126;106257:16;;106252:22;;;;;106696:29;;;;;;;:95;;;106777:14;106762:29;;:11;:29;;106696:95;106658:521;;;106858:289;106923:10;106972:1;107012:7;107058:4;107101:11;106858:26;:289::i;:::-;105189:2040;;;;;105222:3;;105189:2040;;;-1:-1:-1;107255:24:0;;;107251:92;;107313:30;;-1:-1:-1;;;107313:30:0;;;;;;;;;;;107251:92;103955:6608;;;;;;;;107392:20;107462:51;107516:111;107583:10;;107594:1;107583:13;;;;;-1:-1:-1;;;107583:13:0;;;;;;;;;;;;;;;;;;;;:::i;:::-;107516:32;:111::i;:::-;107664:10;;;;-1:-1:-1;107842:10:0;;-1:-1:-1;107842:10:0;;107970:36;107664:10;107970:27;:36::i;:::-;107815:191;;;;;;108089:6;108084:2460;108105:13;108101:1;:17;108084:2460;;;15367:30;;;;;15361:37;108508:2;;108803:6;108812:37;108831:8;;108841:7;108812:18;:37::i;:::-;108803:46;-1:-1:-1;109061:20:0;;;;:45;;;109085:10;109096:1;109085:13;;;;;;-1:-1:-1;;;109085:13:0;;;;;;;;;;;;;;;;;;;:16;:21;;109061:45;109057:173;;;-1:-1:-1;;;109139:24:0;;;;109194:8;;109057:173;109289:41;109363:194;109429:7;109471:5;109511:15;109363:31;:194::i;:::-;-1:-1:-1;109610:16:0;;109258:299;;-1:-1:-1;109605:22:0;;;;;110025:29;;;;;;;:91;;;110102:14;110087:29;;:11;:29;;110025:91;109991:477;;;110175:265;110236:10;110281:1;110317:7;110359:4;110398:11;110175:26;:265::i;:::-;-1:-1:-1;;;110496:24:0;;;;-1:-1:-1;;108084:2460:0;108120:3;;108084:2460;;;;103955:6608;;;;;103931:3;;103891:6687;;;;110599:6;110594:195;110611:19;;;110594:195;;;110660:10;110671:1;110660:13;;;;;;-1:-1:-1;;;110660:13:0;;;;;;;;;;;;;;;;;;;:16;110656:118;;110713:41;;;;;;;;;;;;;;110656:118;110632:3;;110594:195;;;;103327:7480;;;;;;;;:::o;153885:481::-;-1:-1:-1;;;;;;;;;;;;154015:10:0;;154055:30;:14;154015:10;154055:23;:30::i;:::-;154042:43;-1:-1:-1;154096:10:0;154105:1;154096:10;;:::i;:::-;;-1:-1:-1;154119:11:0;154133:30;:14;154096:10;154133:23;:30::i;:::-;154119:44;-1:-1:-1;154174:10:0;154183:1;154174:10;;:::i;:::-;;-1:-1:-1;154224:28:0;154239:13;;;154232:2;154224:28;:::i;:::-;154209:43;;:12;;;:43;:::i;:::-;154197:55;;154269:21;;:30;;154265:93;;154321:37;;-1:-1:-1;;;154321:37:0;;;;;;;;;;;154265:93;153885:481;;;;;;:::o;143165:225::-;141245:4;-1:-1:-1;;;;;141254:6:0;141237:23;;;141229:80;;;;-1:-1:-1;;;141229:80:0;;21515:2:1;141229:80:0;;;21497:21:1;21554:2;21534:18;;;21527:30;21593:34;21573:18;;;21566:62;21664:14;21644:18;;;21637:42;21696:19;;141229:80:0;21487:234:1;141229:80:0;141352:6;-1:-1:-1;;;;;141328:30:0;:20;132876:66;133237:65;-1:-1:-1;;;;;133237:65:0;;133157:153;141328:20;-1:-1:-1;;;;;141328:30:0;;141320:87;;;;-1:-1:-1;;;141320:87:0;;22277:2:1;141320:87:0;;;22259:21:1;22316:2;22296:18;;;22289:30;22355:34;22335:18;;;22328:62;22426:14;22406:18;;;22399:42;22458:19;;141320:87:0;22249:234:1;141320:87:0;143283:36:::1;143301:17;143283;:36::i;:::-;143330:52;143352:17;143371:4;143377;143330:21;:52::i;:::-;143165:225:::0;;:::o;142384:133::-;142462:7;141690:4;-1:-1:-1;;;;;141699:6:0;141682:23;;141674:92;;;;-1:-1:-1;;;141674:92:0;;23382:2:1;141674:92:0;;;23364:21:1;23421:2;23401:18;;;23394:30;23460:34;23440:18;;;23433:62;23531:26;23511:18;;;23504:54;23575:19;;141674:92:0;23354:246:1;141674:92:0;-1:-1:-1;132876:66:0::1;142384:133:::0;:::o;67781:344::-;67961:27;:35;67924:4;;67961:56;;;;:35;;:56;:156;;;;-1:-1:-1;68034:42:0;;:83;;67961:156;67941:176;67781:344;-1:-1:-1;;;67781:344:0:o;150453:1111::-;150559:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;150559:31:0;150603:10;;150645:34;:18;150603:10;150645:27;:34::i;:::-;150630:49;-1:-1:-1;150696:14:0;;;148759:10;150696:14;150692:64;;150719:37;;-1:-1:-1;;;150719:37:0;;;;;;;;;;;150692:64;150769:10;150778:1;150769:10;;:::i;:::-;;-1:-1:-1;150792:15:0;150810:33;:18;150769:10;150810:26;:33::i;:::-;150792:51;;150883:9;150866:27;;;;;;;;-1:-1:-1;;;150866:27:0;;;;;;;;;150854:2;;:39;;;;;;-1:-1:-1;;;150854:39:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;150854:39:0;;;;;;;;;;;-1:-1:-1;150904:10:0;150913:1;150904:10;;:::i;:::-;;-1:-1:-1;148896:23:0;150931:9;;:19;;;;;;-1:-1:-1;;;150931:19:0;;;;;;;;;;150927:68;;150959:36;;-1:-1:-1;;;150959:36:0;;;;;;;;;;;150927:68;151008:18;151029:33;:18;151056:5;151029:26;:33::i;:::-;151008:54;;151102:12;151085:30;;;;;;;;-1:-1:-1;;;151085:30:0;;;;;;;;;151073:2;:9;;:42;;;;;;;-1:-1:-1;;;151073:42:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;151073:42:0;;;;;;;;;;;-1:-1:-1;151126:10:0;151135:1;151126:10;;:::i;:::-;;-1:-1:-1;151168:34:0;:18;151126:10;151168:27;:34::i;:::-;151149:53;;:16;;;:53;151213:10;151222:1;151213:10;;:::i;:::-;;;151453:103;151492:5;151540;151512:18;:25;:33;;;;:::i;:::-;151453:18;;:103;:24;:103::i;:::-;151440:10;;;:116;-1:-1:-1;151440:2:0;;150453:1111;-1:-1:-1;;;;150453:1111:0:o;33622:330::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33790:21:0;33808:2;33790:17;:21::i;:::-;33782:29;;33871:3;33828:40;33833:15;33850:5;:17;;;33828:4;:40::i;:::-;:46;33824:95;;;33896:23;;;;;;;;;;;;;;147333:103;146571:13;:11;:13::i;:::-;147398:30:::1;147425:1;147398:18;:30::i;:::-;147333:103::o:0;152510:457::-;-1:-1:-1;;;;;;;;;;;;152737:10:0;152802:30;:14;152737:10;152802:23;:30::i;:::-;152764:68;;;;152843:10;152852:1;152843:10;;:::i;153054:752::-;-1:-1:-1;;;;;;;;;;;;153201:10:0;;153254:29;:14;153201:10;153254:22;:29::i;:::-;153228:55;-1:-1:-1;153294:10:0;153303:1;153294:10;;:::i;:::-;;;153386:17;153335:79;;;;;;;;-1:-1:-1;;;153335:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;153335:79:0;;;;;;;;;;;;;;;-1:-1:-1;153317:97:0;;:15;153427:266;153448:17;153444:21;;:1;:21;153427:266;;;153516:30;:14;153540:5;153516:23;:30::i;:::-;153487:15;;:18;;153503:1;;153487:18;;;;-1:-1:-1;;;153487:18:0;;;;;;;;;;;;;;;;;;;:59;;;;;;153561:10;153570:1;153561:10;;:::i;:::-;;-1:-1:-1;153624:31:0;:14;153561:10;153624:24;:31::i;:::-;153588:15;;:18;;153604:1;;153588:18;;;;-1:-1:-1;;;153588:18:0;;;;;;;;;;;;;;;:33;;:67;;;;;153679:2;153670:11;;;;;:::i;:::-;;-1:-1:-1;153467:3:0;;;;:::i;:::-;;;;153427:266;;;;153734:5;153709:14;:21;:30;153705:93;;153761:37;;-1:-1:-1;;;153761:37:0;;;;;;;;;;;153705:93;153054:752;;;;;:::o;151652:374::-;-1:-1:-1;;;;;;;;;;;;151800:10:0;151858:31;:14;151800:10;151858:24;:31::i;:::-;-1:-1:-1;;;;;151827:63:0;;;151901:11;151910:2;151901:11;;:::i;67148:196::-;67251:7;67305:2;:10;;;67317:2;:17;;;67288:47;;;;;;;;15884:3:1;15880:16;;;;15898:66;15876:89;15864:102;;15991:1;15982:11;;15975:27;16027:2;16018:12;;15854:182;67288:47:0;;;;;;;;;;;;;67278:58;;;;;;67271:65;;67148:196;;;:::o;99621:439::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99794:26:0;;;:22;:26;;;;;;;99851:16;;;;;;99831:36;;;;99891:9;;;;;;;;;99878:22;;;;;;;99851:16;99925:13;;;;;;;99911:27;;;;;;99962:12;;;;99949:25;;;-1:-1:-1;;99794:26:0;99987:65;;100022:30;;-1:-1:-1;;;100022:30:0;;;;;;;;;;;98918:430;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99088:26:0;;;:22;:26;;;;;;;99145:16;;;;;;99125:36;;;;99185:9;;;;;;;99172:22;;;;;;;99219:10;;;;;;;99205:24;;;;;;-1:-1:-1;;;99253:9:0;;;;;99240:22;;;-1:-1:-1;;99088:26:0;99275:65;;99310:30;;-1:-1:-1;;;99310:30:0;;;;;;;;;;;68133:94;68173:6;68199:10;66752:6;:15;-1:-1:-1;;;;;66752:15:0;;66672:104;68199:10;-1:-1:-1;;;;;68199:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;68192:27;;68133:94;:::o;68377:171::-;68453:39;68517:6;:23;;68510:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68377:171;:::o;33043:324::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;33208:18:0;33223:2;33208:14;:18::i;32599:195::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32738:48:0;32761:2;32765:20;:18;:20::i;176258:1957::-;176340:22;176365:29;176384:9;;176365:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;176365:18:0;;-1:-1:-1;;;176365:29:0:i;:::-;176340:54;;176407:31;176441:62;176482:2;:10;;;176441:26;:62::i;:::-;176407:96;;176540:9;:7;:9::i;:::-;176520:29;;:2;:16;;;:29;;;;:54;;;;-1:-1:-1;176553:16:0;;;;:21;;;;176520:54;176516:116;;;176596:36;;-1:-1:-1;;;176596:36:0;;;;;;;;;;;176516:116;176662:32;176649:2;:9;;;:45;;;;;;-1:-1:-1;;;176649:45:0;;;;;;;;;;176645:1563;;;176715:16;;;;:21;;176711:87;;176762:36;;-1:-1:-1;;;176762:36:0;;;;;;;;;;;176711:87;176813:56;176829:39;176857:2;:10;;;176829:27;:39::i;:::-;176813:15;:56::i;:::-;176645:1563;;;176918:54;176905:2;:9;;;:67;;;;;;-1:-1:-1;;;176905:67:0;;;;;;;;;;176887:1321;;;176999:132;177055:61;177105:2;:10;;;-1:-1:-1;;;;;;;;;152362:30:0;;;-1:-1:-1;152136:264:0;177055:61;176999:37;:132::i;176887:1321::-;177166:31;177153:2;:9;;;:44;;;;;;-1:-1:-1;;;177153:44:0;;;;;;;;;;177149:1059;;;177214:54;177229:38;177256:2;:10;;;177229:26;:38::i;:::-;177214:14;:54::i;177149:1059::-;177303:23;177290:2;:9;;;:36;;;;;;-1:-1:-1;;;177290:36:0;;;;;;;;;;177286:922;;;177343:38;177350:30;177369:2;:10;;;177350:18;:30::i;:::-;177343:6;:38::i;177286:922::-;177416:31;177403:2;:9;;;:44;;;;;;-1:-1:-1;;;177403:44:0;;;;;;;;;;177399:809;;;177464:54;177479:38;177506:2;:10;;;177479:26;:38::i;:::-;177464:14;:54::i;177399:809::-;177567:52;177554:2;:9;;;:65;;;;;;-1:-1:-1;;;177554:65:0;;;;;;;;;;177536:672;;;177771:37;;-1:-1:-1;;;177771:37:0;;;;;;;;;;;177536:672;177843:35;177830:2;:9;;;:48;;;;;;-1:-1:-1;;;177830:48:0;;;;;;;;;;177826:382;;;177899:16;;;;:21;;177895:87;;177946:36;;-1:-1:-1;;;177946:36:0;;;;;;;;;;;177895:87;177997:122;178034:42;178065:2;:10;;;178034:30;:42::i;:::-;178095:9;;177997:122;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;177997:18:0;;-1:-1:-1;;;177997:122:0:i;177826:382::-;178159:37;;-1:-1:-1;;;178159:37:0;;;;;;;;;;;177826:382;176258:1957;;;;:::o;97882:763::-;98084:38;;;98080:92;;98144:28;;-1:-1:-1;;;98144:28:0;;;;;;;;;;;98080:92;98190:6;98185:407;98202:19;;;98185:407;;;98412:12;;98425:1;98412:15;;;;;-1:-1:-1;;;98412:15:0;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98370:57;;:39;98397:8;;98406:1;98397:11;;;;;-1:-1:-1;;;98397:11:0;;;;;;;;;;;;;;;67063:6;67089:31;;;:22;:31;;;;;:43;;;;66973:167;98370:39;:57;;;98366:151;;;98448:28;98465:10;;98448:16;:28::i;:::-;98495:7;;;98366:151;98562:3;;98185:407;;;;98611:26;;;;;;;;;;;;;;97882:763;;;;;;;:::o;112025:776::-;112107:38;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112107:38:0;-1:-1:-1;;;;;;;;;112217:41:0;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66926:31:0;;;:22;:31;;;;;66919:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;66919:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112295:16;;112217:63;;-1:-1:-1;112295:21:0;;112291:64;;112325:30;;-1:-1:-1;;;112325:30:0;;;;;;;;;;;112291:64;112368:17;;;112420:10;;;;;112396:15;;;;;;:34;;;;;;;;112464:9;;;;;112441:15;;:32;;;;:20;;;:32;112507:9;;;;;112484:15;;:32;;;;;;:20;;;:32;112562:16;;112527:15;;112557:22;;;112527:27;;;:52;;;;112619:13;;;;112592:18;;;;;:40;;;;;;;;112669:12;;;;112643:18;;:38;;;:23;;:38;;;;112718:9;;112692:18;;:35;;;;;;:23;;;;:35;112776:16;;112738:18;;112771:22;;112738:30;;:55;;;;112368:9;112025:776::o;90800:1002::-;90897:14;;;90959:790;90976:21;;;90959:790;;;91064:1;91041:10;;91052:1;91041:13;;;;;-1:-1:-1;;;91041:13:0;;;;;;;;;;;;;;;;;;;;:::i;:::-;:20;;:24;:132;;;;-1:-1:-1;75497:10:0;91086:49;91118:10;;91129:1;91118:13;;;;;-1:-1:-1;;;91118:13:0;;;;;;;;91086:49;:87;;;91041:132;91019:719;;;91231:11;91265:21;91308:53;91347:10;;91358:1;91347:13;;;;;-1:-1:-1;;;91347:13:0;;;;;;;;91308:53;91208:153;;-1:-1:-1;91208:153:0;-1:-1:-1;91398:25:0;91384:10;:39;;;;-1:-1:-1;;;91384:39:0;;;;;;;;;;91380:125;;91455:30;;-1:-1:-1;;;91455:30:0;;;;;;;;;;;91380:125;91542:119;91600:10;;91611:1;91600:13;;;;;-1:-1:-1;;;91600:13:0;;;;;;;;;;;;;;;;;;;;:::i;:::-;91636:6;91542:35;:119::i;:::-;91523:138;;;;;;:::i;:::-;;;91019:719;;;;;91702:20;91721:1;91702:20;;:::i;:::-;;;91019:719;90999:3;;;;:::i;:::-;;;;90959:790;;;;91766:28;91778:15;91766:11;:28::i;:::-;91759:35;90800:1002;-1:-1:-1;;;;90800:1002:0:o;90631:161::-;90711:14;90770;90745:22;68818:27;;;68741:112;90745:22;:39;;;;:::i;112953:116::-;113013:4;113037:24;68940:29;;;68861:116;89693:846;89799:20;89839:6;89834:565;89851:21;;;89834:565;;;89936:1;89913:10;;89924:1;89913:13;;;;;-1:-1:-1;;;89913:13:0;;;;;;;;;;;;;;;;;;;;:::i;:::-;:20;;:24;:132;;;;-1:-1:-1;75497:10:0;89958:49;89990:10;;90001:1;89990:13;;;;;-1:-1:-1;;;89990:13:0;;;;;;;;89958:49;:87;;;89913:132;89891:433;;;90099:92;90159:10;;90170:1;90159:13;;;;;-1:-1:-1;;;90159:13:0;;;;;;;;;;;;;;;;;;;;:::i;:::-;90099:37;:92::i;:::-;90080:111;;;;;;:::i;:::-;;;89891:433;;;90232:37;90255:10;;90266:1;90255:13;;;;;-1:-1:-1;;;90255:13:0;;;;;;;;;;;;;;;;;;;;:::i;:::-;90232:22;:37::i;:::-;90288:20;90307:1;90288:20;;:::i;:::-;;;89891:433;90369:3;;89834:565;;;;90409:16;90428:28;90440:15;90428:11;:28::i;:::-;90409:47;;90483:11;90471:9;:23;90467:64;;;90503:28;;;;;;;;;;;;;;147591:201;146571:13;:11;:13::i;:::-;-1:-1:-1;;;;;147680:22:0;::::1;147672:73;;;::::0;-1:-1:-1;;;147672:73:0;;21108:2:1;147672:73:0::1;::::0;::::1;21090:21:1::0;21147:2;21127:18;;;21120:30;21186:34;21166:18;;;21159:62;21257:8;21237:18;;;21230:36;21283:19;;147672:73:0::1;21080:228:1::0;147672:73:0::1;147756:28;147775:8;147756:18;:28::i;114266:326::-:0;-1:-1:-1;;;;;114561:19:0;;:23;;;114266:326::o;146228:97::-;126855:13;;;;;;;126847:69;;;;-1:-1:-1;;;126847:69:0;;27623:2:1;126847:69:0;;;27605:21:1;27662:2;27642:18;;;27635:30;27701:34;27681:18;;;27674:62;27772:13;27752:18;;;27745:41;27803:19;;126847:69:0;27595:233:1;126847:69:0;146291:26:::1;:24;:26::i;140382:68::-:0;126855:13;;;;;;;126847:69;;;;-1:-1:-1;;;126847:69:0;;27623:2:1;126847:69:0;;;27605:21:1;27662:2;27642:18;;;27635:30;27701:34;27681:18;;;27674:62;27772:13;27752:18;;;27745:41;27803:19;;126847:69:0;27595:233:1;87852:1635:0;69214:6;:29;;-1:-1:-1;;69214:29:0;-1:-1:-1;;;;;69214:29:0;;;;;88291:82;;;88273:147;;88392:28;;-1:-1:-1;;;88392:28:0;;;;;;;;;;;88273:147;88438:6;88433:550;88450:36;;;88433:550;;;88508:40;88551:170;;;;;;;;88622:25;;88648:1;88622:28;;;;;-1:-1:-1;;;88622:28:0;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;88551:170;;;;;;88673:26;;88700:1;88673:29;;;;;-1:-1:-1;;;88673:29:0;;;;;;;;;;;;;;;;;;88551:170;;;88772:10;;88784:17;;;;67597:134;;;15884:3:1;15880:16;;;;15898:66;15876:89;67597:134:0;;;15864:102:1;15982:11;;;;15975:27;;;;67597:134:0;;;;;;;;;;16018:12:1;;;;67597:134:0;;67565:185;;;;;;-1:-1:-1;67522:243:0;;;:24;:243;;;;;;88772:10;;-1:-1:-1;;67522:243:0;;88738:118;;;88828:28;;-1:-1:-1;;;88828:28:0;;;;;;;;;;;88738:118;88920:4;88873:24;:44;88898:18;88913:2;88898:14;:18::i;:::-;88873:44;;;;;;;;;;;;-1:-1:-1;88873:44:0;;;:51;;-1:-1:-1;;88873:51:0;;;;;;;;;;;88939:23;:32;;-1:-1:-1;88939:32:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;88939:32:0;;;;;;;;;;;;;;;;;;;;;88488:3;;;;:::i;:::-;;;;88433:550;;;-1:-1:-1;89053:100:0;;;;;;;;;;;;;;;;;;;;;69834:27;:43;;-1:-1:-1;;69834:43:0;;;;;;;;;;69973:37;:48;;-1:-1:-1;;69973:48:0;;;;;;;87852:1635;89350:61;89388:22;69642:29;:54;69558:146;89350:61;89422:57;89458:20;69509:27;:33;69446:104;89422:57;87852:1635;;;;;;;;;;:::o;55525:339::-;55628:6;55672:10;:6;55681:1;55672:10;:::i;:::-;55655:6;:13;:27;;55647:60;;;;-1:-1:-1;;;55647:60:0;;22690:2:1;55647:60:0;;;22672:21:1;22729:2;22709:18;;;22702:30;22768:22;22748:18;;;22741:50;22808:18;;55647:60:0;22662:170:1;55647:60:0;-1:-1:-1;55788:29:0;55804:3;55788:29;55782:36;;55525:339::o;185409:66::-;146571:13;:11;:13::i;134575:992::-;132528:66;135029:59;;;135025:535;;;135105:37;135124:17;135105:18;:37::i;:::-;134575:992;;;:::o;135025:535::-;135208:17;-1:-1:-1;;;;;135179:61:0;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;135179:63:0;;;;;;;;-1:-1:-1;;135179:63:0;;;;;;;;;;;;:::i;:::-;;;135175:306;;135409:56;;-1:-1:-1;;;135409:56:0;;24632:2:1;135409:56:0;;;24614:21:1;24671:2;24651:18;;;24644:30;24710:34;24690:18;;;24683:62;24781:16;24761:18;;;24754:44;24815:19;;135409:56:0;24604:236:1;135175:306:0;132876:66;135293:28;;135285:82;;;;-1:-1:-1;;;135285:82:0;;23807:2:1;135285:82:0;;;23789:21:1;23846:2;23826:18;;;23819:30;23885:34;23865:18;;;23858:62;23956:11;23936:18;;;23929:39;23985:19;;135285:82:0;23779:231:1;135285:82:0;135243:140;135495:53;135513:17;135532:4;135538:9;135495:17;:53::i;76465:2427::-;76867:1;76586:11;37283:40;;37278:3;37274:50;75497:10;76893:26;;76889:90;;76949:30;;-1:-1:-1;;;76949:30:0;;;;;;;;;;;76889:90;77170:1;77160:11;;;;36712:26;;36699:40;36694:3;36690:50;;77196:29;;77192:93;;77255:30;;-1:-1:-1;;;77255:30:0;;;;;;;;;;;77192:93;-1:-1:-1;;36712:26:0;;;77476:1;36712:26;36699:40;36694:3;36690:50;;;78561:28;;;;;;;;36712:26;;;;36699:40;36690:50;;78634:101;;;;;;-1:-1:-1;;;78634:101:0;;;;;;;;;78762:1;78752:11;;;;;78621:114;-1:-1:-1;78784:33:0;;;78780:93;;;78843:30;;-1:-1:-1;;;78843:30:0;;;;;;;;;;;78780:93;76465:2427;;;;;:::o;78900:3081::-;79130:11;;;79216:22;79130:11;79301:170;79348:17;;79384:13;79416:40;;;79301:28;:170::i;:::-;79656:1;;-1:-1:-1;79291:180:0;;-1:-1:-1;79291:180:0;-1:-1:-1;36991:40:0;;36986:3;36982:50;79693:27;79495:1;79787:242;79834:172;79291:180;;79656:1;36982:50;79834:28;:172::i;:::-;79787:20;:242::i;:::-;80298:10;;;13986:3;13970:29;;;13964:36;80052:21;;;;;;;;80298:10;;-1:-1:-1;13986:3:0;-1:-1:-1;75612:10:0;80624:35;;;;80620:103;;80693:30;;-1:-1:-1;;;80693:30:0;;;;;;;;;;;80620:103;13418:29;;;13434:3;13418:29;13412:36;80748:21;;80772:113;;;;;;-1:-1:-1;;;80772:113:0;;;;;;;;;80908:15;;;;;80748:137;-1:-1:-1;80966:25:0;80952:10;:39;;;;-1:-1:-1;;;80952:39:0;;;;;;;;;;80948:107;;81025:30;;-1:-1:-1;;;81025:30:0;;;;;;;;;;;80948:107;13080:30;;;;;13074:37;81740:21;;13130:27;13052:120;;;81461:112;;;-1:-1:-1;81596:19:0;;;;;81724:37;;81720:105;;;81795:30;;-1:-1:-1;;;81795:30:0;;;;;;;;;;;81720:105;-1:-1:-1;;81961:1:0;81951:11;;;78900:3081;;-1:-1:-1;;;;36712:26:0;;;36699:40;36694:3;36690:50;;-1:-1:-1;36712:26:0;-1:-1:-1;;78900:3081:0:o;82471:1483::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83008:1:0;82998:11;;;-1:-1:-1;;82821:29:0;;-1:-1:-1;;37004:26:0;;36991:40;36986:3;36982:50;83043:124;37004:26;83090:7;82998:11;36982:50;83043:28;:124::i;:::-;83026:141;;;;83192:11;83182:21;;;;;;83220:10;83266:147;83308:7;;83334:6;83359;83384:14;;83266:23;:147::i;:::-;83245:168;-1:-1:-1;83245:168:0;-1:-1:-1;83245:168:0;83428:84;;83466:30;;-1:-1:-1;;;83466:30:0;;;;;;;;;;;83428:84;83528:23;36699:40;;36694:3;36690:50;83554:94;;;;-1:-1:-1;;;83554:94:0;;;;;;;;;83528:120;-1:-1:-1;83682:21:0;83667:11;:36;;;;-1:-1:-1;;;83667:36:0;;;;;;;;;;83663:218;;;83747:40;83769:14;;83785:1;83747:21;:40::i;:::-;83724:63;;-1:-1:-1;83724:63:0;-1:-1:-1;83663:218:0;;;83835:30;;-1:-1:-1;;;83835:30:0;;;;;;;;;;;83663:218;83897:38;;;;;82471:1483;;;;;;;;:::o;110988:330::-;111115:10;;111159:133;111166:19;;;111159:133;;;111226:13;111211:8;;111220:1;111211:11;;;;;-1:-1:-1;;;111211:11:0;;;;;;;;;;;;;;;:28;111207:74;;;111260:5;;111207:74;111187:3;;;;:::i;:::-;;;;111159:133;;111326:691;111586:7;111567:10;111578:1;111567:13;;;;;;-1:-1:-1;;;111567:13:0;;;;;;;;;;;;;;;:16;;:26;;;;;111632:4;:10;;;111604;111615:1;111604:13;;;;;;-1:-1:-1;;;111604:13:0;;;;;;;;;;;;;;;:19;;;:25;;:38;;;;;;;;;;;111680:4;:9;;;111653:10;111664:1;111653:13;;;;;;-1:-1:-1;;;111653:13:0;;;;;;;;;;;;;;;:19;;;:24;;:36;;;;;;;;;;;111727:4;:9;;;111700:10;111711:1;111700:13;;;;;;-1:-1:-1;;;111700:13:0;;;;;;;;;;;;;;;:19;;;:24;;:36;;;;;;;;;;;111781:11;111747:10;111758:1;111747:13;;;;;;-1:-1:-1;;;111747:13:0;;;;;;;;;;;;;;;:19;;;:31;;:45;;;;;111834:4;:13;;;111803:10;111814:1;111803:13;;;;;;-1:-1:-1;;;111803:13:0;;;;;;;;;;;;;;;:22;;;:28;;:44;;;;;;;;;;;111888:4;:12;;;111858:10;111869:1;111858:13;;;;;;-1:-1:-1;;;111858:13:0;;;;;;;;;;;;;;;:22;;;:27;;:42;;;;;;;;;;;111941:4;:9;;;111911:10;111922:1;111911:13;;;;;;-1:-1:-1;;;111911:13:0;;;;;;;;;;;;;;;:22;;;:27;;:39;;;;;;;;;;;111998:11;111961:10;111972:1;111961:13;;;;;;-1:-1:-1;;;111961:13:0;;;;;;;;;;;;;;;:22;;;:34;;:48;;;;;111326:691;;;;;:::o;102920:399::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103077:10:0;103118;66752:6;:15;-1:-1:-1;;;;;66752:15:0;;66672:104;103118:10;-1:-1:-1;;;;;103118:27:0;;103146:9;;103118:38;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;103118:38:0;;;;;;;;;;;;:::i;:::-;-1:-1:-1;103102:54:0;;-1:-1:-1;103102:54:0;-1:-1:-1;103102:54:0;103171:50;;103190:31;;-1:-1:-1;;;103190:31:0;;;;;;;;;;;103171:50;102920:399;103250:16;103263:2;103250:12;:16::i;:::-;103245:66;;103275:36;;;;;;;;;;;;;;100068:2844;100193:10;;;;100377:39;100401:7;100193:10;13986:3;13970:29;;;13964:36;;13778:268;100377:39;100362:54;;100444:1;100435:10;;;;100468:5;:19;;100477:10;100468:19;100464:62;;100496:30;;-1:-1:-1;;;100496:30:0;;;;;;;;;;;100464:62;13710:3;13694:29;;;;;13688:36;100627:10;;;100676:1;100660:17;;;;100656:60;;100686:30;;-1:-1:-1;;;100686:30:0;;;;;;;;;;;100656:60;100942:1;100933:10;;;;101214:14;101231:39;101255:7;101264:5;13710:3;13694:29;;;13688:36;;13502:268;101231:39;101214:56;;101298:1;101289:10;;;;102006:15;102024:38;102047:7;102056:5;13434:3;13418:29;;;13412:36;;13229:265;102024:38;102006:56;;102148:7;102139:16;;;;;;102244:9;:14;;102257:1;102244:14;102240:57;;102267:30;;-1:-1:-1;;;102267:30:0;;;;;;;;;;;102240:57;-1:-1:-1;;;;13694:29:0;;;13710:3;13694:29;13688:36;102378:55;;;;102457:1;102448:10;;;;102536:39;102560:7;102569:5;13710:3;13694:29;;;13688:36;;13502:268;102536:39;102518:57;;;;102599:1;102590:10;;;;102822:13;102804:15;:31;102795:5;:41;102776:7;:14;:61;102772:121;;102863:30;;-1:-1:-1;;;102863:30:0;;;;;;;;;;;102772:121;100068:2844;;;;;:::o;93703:4069::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15367:30:0;;;;;;15361:37;14246:29;;;14240:36;94472:110;;;;;;;;;14246:29;;;14240:36;94635:119;;;;;;;13970:29;;;13964:36;94807:109;;;;;;;;;14246:29;;;14240:36;94969:113;;;;;;;;14246:29;;;14240:36;95135:122;;;;;13418:29;;;13412:36;14246:29;;;;14240:36;96285:138;;;;;-1:-1:-1;;14246:29:0;96488:11;;;96498:1;96488:11;96484:1144;;;96586:2;96566:22;;;;96484:1144;;;96942:24;;;14246:29;;14262:3;14246:29;;14240:36;96839:150;;;;;;14246:29;;;14240:36;97097:211;;;;;;:10;;;:211;14246:29;;;;14240:36;97421:143;:9;;;:143;97587:21;;;;96484:1144;93703:4069;97682:15;97663:16;:34;97659:94;;;97723:30;;-1:-1:-1;;;97723:30:0;;;;;;;;;;;97659:94;93703:4069;;;;;;;:::o;55178:339::-;55281:6;55325:10;:6;55334:1;55325:10;:::i;:::-;55308:6;:13;:27;;55300:60;;;;-1:-1:-1;;;55300:60:0;;28035:2:1;55300:60:0;;;28017:21:1;28074:2;28054:18;;;28047:30;28113:22;28093:18;;;28086:50;28153:18;;55300:60:0;28007:170:1;55300:60:0;-1:-1:-1;55441:29:0;55457:3;55441:29;55435:36;;55178:339::o;54488:335::-;54590:5;54633:10;:6;54642:1;54633:10;:::i;:::-;54616:6;:13;:27;;54608:59;;;;-1:-1:-1;;;54608:59:0;;27275:2:1;54608:59:0;;;27257:21:1;27314:2;27294:18;;;27287:30;27353:21;27333:18;;;27326:49;27392:18;;54608:59:0;27247:169:1;54608:59:0;-1:-1:-1;54747:29:0;54763:3;54747:29;54741:36;;54488:335::o;54831:339::-;54934:6;54978:10;:6;54987:1;54978:10;:::i;:::-;54961:6;:13;:27;;54953:60;;;;-1:-1:-1;;;54953:60:0;;21928:2:1;54953:60:0;;;21910:21:1;21967:2;21947:18;;;21940:30;22006:22;21986:18;;;21979:50;22046:18;;54953:60:0;21900:170:1;54953:60:0;-1:-1:-1;55094:29:0;55110:3;55094:29;55088:36;;54831:339::o;50977:3058::-;51103:12;51152:7;51136:12;51152:7;51146:2;51136:12;:::i;:::-;:23;;51128:50;;;;-1:-1:-1;;;51128:50:0;;23039:2:1;51128:50:0;;;23021:21:1;23078:2;23058:18;;;23051:30;23117:16;23097:18;;;23090:44;23151:18;;51128:50:0;23011:164:1;51128:50:0;51214:16;51223:7;51214:6;:16;:::i;:::-;51197:6;:13;:33;;51189:63;;;;-1:-1:-1;;;51189:63:0;;26929:2:1;51189:63:0;;;26911:21:1;26968:2;26948:18;;;26941:30;27007:19;26987:18;;;26980:47;27044:18;;51189:63:0;26901:167:1;51189:63:0;51265:22;51331:15;;51360:2224;;;;53728:4;53722:11;53709:24;;53917:1;53906:9;53899:20;53967:4;53956:9;53952:20;53946:4;53939:34;51324:2664;;51360:2224;51545:4;51539:11;51526:24;;52214:2;52205:7;52201:16;52645:9;52638:17;52632:4;52628:28;52595:9;52584;52580:25;52554:121;52712:7;52708:2;52704:16;53105:6;53040:9;53033:17;53027:4;53023:28;52982:9;52974:6;52970:22;52936:142;52906:228;52740:592;53161:3;53157:2;53154:11;52740:592;;;53303:9;;53292:21;;53203:4;53195:13;;;;53236;52740:592;;;-1:-1:-1;;53352:26:0;;;53564:2;53547:11;-1:-1:-1;;53543:25:0;53537:4;53530:39;-1:-1:-1;51324:2664:0;-1:-1:-1;54018:9:0;50977:3058;-1:-1:-1;;;;50977:3058:0:o;33960:172::-;34013:4;34038:1;34034;:5;34030:95;;;34063:5;34067:1;34063;:5;:::i;:::-;34056:12;;;;34030:95;34108:5;34112:1;34108;:5;:::i;146850:132::-;146758:6;;-1:-1:-1;;;;;146758:6:0;144982:10;146914:23;146906:68;;;;-1:-1:-1;;;146906:68:0;;25811:2:1;146906:68:0;;;25793:21:1;;;25830:18;;;25823:30;25889:34;25869:18;;;25862:62;25941:18;;146906:68:0;25783:182:1;147952:191:0;148045:6;;;-1:-1:-1;;;;;148062:17:0;;;-1:-1:-1;;148062:17:0;;;;;;;148095:40;;148045:6;;;148062:17;148045:6;;148095:40;;148026:16;;148095:40;147952:191;;:::o;56926:354::-;57030:7;57075:11;:6;57084:2;57075:11;:::i;:::-;57058:6;:13;:28;;57050:62;;;;-1:-1:-1;;;57050:62:0;;25047:2:1;57050:62:0;;;25029:21:1;25086:2;25066:18;;;25059:30;25125:23;25105:18;;;25098:51;25166:18;;57050:62:0;25019:171:1;57050:62:0;-1:-1:-1;57200:30:0;57216:4;57200:30;57194:37;;56926:354::o;54043:437::-;54147:7;54192:11;:6;54201:2;54192:11;:::i;:::-;54175:6;:13;:28;;54167:62;;;;-1:-1:-1;;;54167:62:0;;26172:2:1;54167:62:0;;;26154:21:1;26211:2;26191:18;;;26184:30;26250:23;26230:18;;;26223:51;26291:18;;54167:62:0;26144:171:1;54167:62:0;-1:-1:-1;54339:30:0;54355:4;54339:30;54333:37;54389:27;54311:120;;;54043:437::o;175604:646::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;175732:22:0;175756:10;175772;66752:6;:15;-1:-1:-1;;;;;66752:15:0;;66672:104;175772:10;-1:-1:-1;;;;;175772:27:0;;175814:9;175772:62;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;175772:62:0;;;;;;;;;;;;:::i;:::-;175731:103;;;;;175852:5;175847:50;;175866:31;;-1:-1:-1;;;175866:31:0;;;;;;;;;;;175847:50;175915:65;175943:2;:17;;;175962:2;:17;;;175915:27;:65::i;:::-;175910:132;;176002:40;;;;;;;;;;;;;;175910:132;68324:37;;;;176059:47;;:2;:11;;;:47;;;176055:106;;176128:33;;;;;;;;;;;;;;176055:106;176208:11;;;;69973:37;:48;;-1:-1:-1;;69973:48:0;;;;;;;;;;;-1:-1:-1;176240:2:0;175604:646;-1:-1:-1;;175604:646:0:o;178223:274::-;178455:34;178481:7;178455:25;:34::i;178772:2291::-;178916:73;178992:22;-1:-1:-1;;;;;;;;;;;;;;;;;68691:34:0;;;;;;;;68698:27;68691:34;;;;;;;;;;;;68556:177;178992:22;178916:98;;179378:22;179402:10;179418;66752:6;:15;-1:-1:-1;;;;;66752:15:0;;66672:104;179418:10;179460:16;;179418:69;;;;;-1:-1:-1;;;;;179418:27:0;;;;;;;:69;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;179418:69:0;;;;;;;;;;;;:::i;:::-;179377:110;;;;;179503:5;179498:50;;179517:31;;-1:-1:-1;;;179517:31:0;;;;;;;;;;;179498:50;179561:31;179595:62;179636:2;:10;;;179595:26;:62::i;:::-;179561:96;;179692:9;:7;:9::i;:::-;179672:29;;:2;:16;;;:29;;;;:54;;;;-1:-1:-1;179705:16:0;;;;:21;;;;179672:54;179668:116;;;179748:36;;-1:-1:-1;;;179748:36:0;;;;;;;;;;;179668:116;179814:52;179801:2;:9;;;:65;;;;;;-1:-1:-1;;;179801:65:0;;;;;;;;;;179797:128;;179888:37;;-1:-1:-1;;;179888:37:0;;;;;;;;;;;179797:128;179938:75;180016:91;180082:2;:10;;;180016:47;:91::i;:::-;180294:38;;179938:169;;-1:-1:-1;180250:82:0;;:27;69069:32;;;;;68985:124;180250:27;:82;;;180232:152;;180351:33;;;;;;;;;;;;;;180232:152;180426:38;;70112:32;:43;;;;;;;;;;;;;;180547:117;;;;;;;;180596:17;;;;180547:117;;;;;180632:17;;;;180547:117;;;;;;;69834:27;:43;;-1:-1:-1;;69834:43:0;;;;;;;;;180870:11;;;;69973:37;:48;;-1:-1:-1;;69973:48:0;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;68691:34:0;;;;;;;;;;;;;;;180547:117;180900:155;;180938:22;;68324:37;;180900:155;;;14692:12:1;;14706:6;14688:25;;;14676:38;;14763:4;14752:16;;;14746:23;14730:14;;;14723:47;14692:12;;14688:25;29263:18;;;14676:38;;;;14752:16;;;;14746:23;14730:14;;;14723:47;68324:37:0;;29313:3:1;29298:19;;29291:60;29157:3;29142:19;180900:155:0;;;;;;;;178772:2291;;;;;;;:::o;181071:708::-;181153:67;181223:18;:16;:18::i;:::-;181153:88;;181259:6;181254:146;181275:14;:21;181271:1;:25;181254:146;;;181383:5;181321:6;:24;;:59;181346:33;181361:14;181376:1;181361:17;;;;;;-1:-1:-1;;;181361:17:0;;;;;;;;;;;;;;;181346:14;:33::i;:::-;181321:59;;;;;;;;;;;-1:-1:-1;181321:59:0;:67;;-1:-1:-1;;181321:67:0;;;;;;;;;;181298:6;-1:-1:-1;181298:6:0;;:::i;:::-;;;181254:146;;;-1:-1:-1;181412:30:0;181419:23;;181412:30;:::i;:::-;181458:6;181453:251;181474:19;;:26;181470:30;;181453:251;;;181551:19;;:22;;181522:23;;181551:19;181571:1;;181551:22;;;;-1:-1:-1;;;181551:22:0;;;;;;;;;;;;;;;;;;;;181522:52;;;;;;;;-1:-1:-1;181522:52:0;;;;;;;;;;;;;;;-1:-1:-1;;181522:52:0;;;;;;;;;;;;;;;;;;;;;;;181647:19;;:22;;181522:52;;181589:24;;-1:-1:-1;;181632:38:0;;181667:1;;181647:22;;;;-1:-1:-1;;;181647:22:0;;;;;;;;181632:38;181589:96;;;;;;;;;;;-1:-1:-1;181589:96:0;:103;;-1:-1:-1;;181589:103:0;;;;;;;;;;181502:3;;;;:::i;:::-;;;;181453:251;;;;181721:50;181736:14;181752:18;:16;:18::i;:::-;181721:50;;;;;;;:::i;:::-;;;;;;;;181071:708;;:::o;181787:216::-;181853:11;181867:22;68818:27;;;68741:112;181867:22;181924:14;;69509:27;:33;181853:36;-1:-1:-1;181957:38:0;181964:6;181972:22;68818:27;;;68741:112;181972:22;181957:38;;;33319:25:1;;;33375:2;33360:18;;33353:34;;;;33292:18;181957:38:0;33274:119:1;182011:270:0;182093:19;182115:24;68940:29;;;68861:116;182115:24;182176:22;;69642:29;:54;182093:46;-1:-1:-1;182217:56:0;182232:14;182248:24;68940:29;;;68861:116;182289:1777;182428:26;182465:10;66752:6;:15;-1:-1:-1;;;;;66752:15:0;;66672:104;182465:10;182499:26;;69214:6;:29;;-1:-1:-1;;69214:29:0;-1:-1:-1;;;;;69214:29:0;;;;;;;;182755:62;;;;;182428:48;;-1:-1:-1;;;;;69214:29:0;182755:27;;:62;;182797:9;;182755:62;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;182755:62:0;;;;;;;;;;;;:::i;:::-;182714:103;;;;;182835:5;182830:56;;182849:37;;-1:-1:-1;;;182849:37:0;;;;;;;;;;;182830:56;182904:65;182932:2;:17;;;182951:2;:17;;;182904:27;:65::i;:::-;182899:129;;182991:37;;-1:-1:-1;;;182991:37:0;;;;;;;;;;;182899:129;68324:37;;;;183045:47;;:2;:11;;;:47;;;183041:113;;183114:40;;-1:-1:-1;;;183114:40:0;;;;;;;;;;;183041:113;183167:31;183201:62;183242:2;:10;;;183201:26;:62::i;:::-;183167:96;-1:-1:-1;183293:35:0;183280:2;:9;;;:48;;;;;;-1:-1:-1;;;183280:48:0;;;;;;;;;;183276:114;;183350:40;;-1:-1:-1;;;183350:40:0;;;;;;;;;;;183276:114;183742:56;183801:42;183832:2;:10;;;183801:30;:42::i;:::-;183893:26;;183860:29;;183742:101;;-1:-1:-1;;;;;;183860:59:0;;;;;;183856:125;;183941:40;;-1:-1:-1;;;183941:40:0;;;;;;;;;;;183856:125;183999:59;184018:18;184046:10;66752:6;:15;-1:-1:-1;;;;;66752:15:0;;66672:104;184046:10;183999:59;;;-1:-1:-1;;;;;17453:15:1;;;17435:34;;17505:15;;;;17500:2;17485:18;;17478:43;17347:18;183999:59:0;17329:198:1;81989:474:0;82132:16;37004:26;;;36991:40;36986:3;36982:50;82291:11;82301:1;37004:26;82291:11;:::i;:::-;;-1:-1:-1;82313:21:0;;;;82291:11;82313:21;:::i;:::-;;-1:-1:-1;36712:26:0;;;36699:40;36694:3;36690:50;82358:97;82345:110;81989:474;-1:-1:-1;;;;;81989:474:0:o;110815:165::-;110896:16;110950:22;68818:27;;;68741:112;110950:22;110932:40;;:15;:40;:::i;86051:1682::-;86166:16;86210:18;86243:21;86278:57;86317:17;;86278:38;:57::i;:::-;86195:140;;-1:-1:-1;86195:140:0;-1:-1:-1;86366:25:0;86352:10;:39;;;;-1:-1:-1;;;86352:39:0;;;;;;;;;;86348:109;;86415:30;;-1:-1:-1;;;86415:30:0;;;;;;;;;;;86348:109;86469:11;86491:14;86516:22;;86652:148;86744:17;;86776:13;86652:77;:148::i;:::-;86549:251;;-1:-1:-1;86549:251:0;;-1:-1:-1;86549:251:0;;-1:-1:-1;86549:251:0;;-1:-1:-1;86549:251:0;-1:-1:-1;86843:6:0;86838:799;86859:10;86855:14;;:1;:14;86838:799;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87025:138:0;87079:6;87108:7;;87138:6;87025:31;:138::i;:::-;87182:24;67089:31;;;:22;:31;;;;;:43;87267:21;;86994:169;;-1:-1:-1;86994:169:0;;-1:-1:-1;67089:31:0;-1:-1:-1;67089:43:0;;;;;87267:41;;-1:-1:-1;87263:359:0;;;69392:31;;;;:22;:31;;;;;;;;;:38;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69392:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;69392:38:0;;;;;;;;;;;;;-1:-1:-1;69392:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87399:203;;34031:34:1;;;34081:18;;;34074:49;;;;34139:18;;;34132:43;;;;69392:31:0;;87399:203;;33967:18:1;87399:203:0;;;;;;;87263:359;-1:-1:-1;;;86871:3:0;;86838:799;;;-1:-1:-1;87662:24:0;;;87658:67;;87695:30;;-1:-1:-1;;;87695:30:0;;;;;;;;;;;87658:67;86051:1682;;;;;;;;;;:::o;89495:190::-;89572:105;89623:43;89656:9;;89623:32;:43::i;:::-;89572:36;:105::i;146333:113::-;126855:13;;;;;;;126847:69;;;;-1:-1:-1;;;126847:69:0;;27623:2:1;126847:69:0;;;27605:21:1;27662:2;27642:18;;;27635:30;27701:34;27681:18;;;27674:62;27772:13;27752:18;;;27745:41;27803:19;;126847:69:0;27595:233:1;126847:69:0;146406:32:::1;144982:10:::0;146406:18:::1;:32::i;133406:284::-:0;-1:-1:-1;;;;;114561:19:0;;;133480:106;;;;-1:-1:-1;;;133480:106:0;;25397:2:1;133480:106:0;;;25379:21:1;25436:2;25416:18;;;25409:30;25475:34;25455:18;;;25448:62;25546:15;25526:18;;;25519:43;25579:19;;133480:106:0;25369:235:1;133480:106:0;132876:66;133597:85;;-1:-1:-1;;133597:85:0;-1:-1:-1;;;;;133597:85:0;;;;;;;;;;133406:284::o;134099:297::-;134242:29;134253:17;134242:10;:29::i;:::-;134300:1;134286:4;:11;:15;:28;;;;134305:9;134286:28;134282:107;;;134331:46;134353:17;134372:4;134331:21;:46::i;35809:201::-;35937:14;;35971:6;35978;35971;35985:16;35994:7;35978:6;35985:16;:::i;:::-;35971:31;;;;;;;:::i;:::-;35964:38;;;;35809:201;;;;;;;:::o;76018:439::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76163:10:0;76204;66752:6;:15;-1:-1:-1;;;;;66752:15:0;;66672:104;76204:10;-1:-1:-1;;;;;76204:27:0;;76232:9;;76204:38;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;76204:38:0;;;;;;;;;;;;:::i;:::-;-1:-1:-1;76188:54:0;;-1:-1:-1;76188:54:0;-1:-1:-1;76188:54:0;76257:50;;76276:31;;-1:-1:-1;;;76276:31:0;;;;;;;;;;;76257:50;76018:439;76336:55;76354:2;:17;;;76373:2;:17;;;67597:134;;;15884:3:1;15880:16;;;;15898:66;15876:89;67597:134:0;;;;15864:102:1;;;;15982:11;;;;15975:27;;;;67597:134:0;;;;;;;;;;16018:12:1;;;;67597:134:0;;67565:185;;;;;;;;;-1:-1:-1;67522:243:0;;;:24;:243;;;;;;;;;67352:421;71774:969;71948:10;71960:14;72012:21;72036:29;72056:8;;72036:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72036:19:0;;-1:-1:-1;;;72036:29:0:i;:::-;72236:1;72221:16;;;72012:53;;-1:-1:-1;36712:26:0;;36699:40;36694:3;36690:50;72082:15;72254:387;72275:9;72271:13;;:1;:13;72254:387;;;72476:2;72461:17;;;36420:26;;36407:40;-1:-1:-1;;72334:108:0;72515:110;72557:13;72334:108;72515:19;:110::i;:::-;72499:126;-1:-1:-1;;72286:3:0;;72254:387;;;-1:-1:-1;;;;72665:21:0;;;;;;;;;;72713:11;;-1:-1:-1;71774:969:0;;-1:-1:-1;;;;;71774:969:0:o;83962:2081::-;-1:-1:-1;;;;;;;;;38752:26:0;;;-1:-1:-1;37588:26:0;;;37575:40;37566:50;;84417:114;;;;;;-1:-1:-1;;;84417:114:0;;;;84546:11;37588:26;;37575:40;37566:50;;-1:-1:-1;;;84574:123:0;84712:11;37296:26;;37283:40;37278:3;37274:50;84740:113;;;;;;-1:-1:-1;;;84740:113:0;37588:26;;;37575:40;37566:50;;85216:130;;37588:26;;;37575:40;37566:50;;85603:117;;;;;-1:-1:-1;;;85603:117:0;37588:26;;;37575:40;37566:50;;-1:-1:-1;;;85763:126:0;85904:11;;;;;-1:-1:-1;38739:40:0;85936:32;;;85932:92;;;85994:30;;-1:-1:-1;;;85994:30:0;;;;;;;;;;;85932:92;83962:2081;;;;;;:::o;91810:177::-;91894:10;91924:55;91942:2;:17;;;91961:2;:17;;;67597:134;;;15884:3:1;15880:16;;;;15898:66;15876:89;67597:134:0;;;;15864:102:1;;;;15982:11;;;;15975:27;;;;67597:134:0;;;;;;;;;;16018:12:1;;;;67597:134:0;;67565:185;;;;;;;;;-1:-1:-1;67522:243:0;;;:24;:243;;;;;;;;;67352:421;185640:657;185759:25;185787:20;132876:66;133237:65;-1:-1:-1;;;;;133237:65:0;;133157:153;185787:20;185840:25;;185759:48;;-1:-1:-1;185818:69:0;;185840:25;185867:12;;185818:69;186115:4;-1:-1:-1;;;;;186115:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:40;;186145:10;186115:40;186111:103;;186177:37;;-1:-1:-1;;;186177:37:0;;;;;;;;;;;186111:103;186232:57;186249:17;186268:20;132876:66;133237:65;-1:-1:-1;;;;;133237:65:0;;133157:153;186268:20;186232:57;;;-1:-1:-1;;;;;17453:15:1;;;17435:34;;17505:15;;;;17500:2;17485:18;;17478:43;17347:18;186232:57:0;17329:198:1;91995:1700:0;92397:10;;;;92374:20;;;92545:36;92397:10;92545:27;:36::i;:::-;92422:159;;;;;;92648:6;92643:960;92664:13;92660:1;:17;92643:960;;;92726:41;92790:15;92827:162;92885:7;92919:5;92951:15;92827:31;:162::i;:::-;93171:24;67089:31;;;:22;:31;;;;;:43;93258:16;;93084:24;;;;92703:286;;-1:-1:-1;67089:31:0;;-1:-1:-1;67089:43:0;;;;;93258:36;;-1:-1:-1;93254:334:0;;;69392:31;;;;:22;:31;;;;;;;;;:38;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;69392:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;69392:38:0;;;;;;;;;;;;;-1:-1:-1;69392:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93380:188;;34031:34:1;;;34081:18;;;34074:49;;;;34139:18;;;34132:43;;;;69392:31:0;;93380:188;;33967:18:1;93380:188:0;;;;;;;93254:334;-1:-1:-1;;;92679:3:0;;92643:960;;;-1:-1:-1;93645:17:0;;;;93664:11;;;;93624:52;;;32876:6:1;32864:19;;;32846:38;;32932:18;32920:31;;;32915:2;32900:18;;32893:59;93624:52:0;;32819:18:1;93624:52:0;;;;;;;91995:1700;;;;;:::o;133803:155::-;133870:37;133889:17;133870:18;:37::i;:::-;133923:27;;-1:-1:-1;;;;;133923:27:0;;;;;;;;133803:155;:::o;138836:461::-;138919:12;-1:-1:-1;;;;;114561:19:0;;;138944:88;;;;-1:-1:-1;;;138944:88:0;;26522:2:1;138944:88:0;;;26504:21:1;26561:2;26541:18;;;26534:30;26600:34;26580:18;;;26573:62;26671:8;26651:18;;;26644:36;26697:19;;138944:88:0;26494:228:1;138944:88:0;139106:12;139120:23;139147:6;-1:-1:-1;;;;;139147:19:0;139167:4;139147:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;139105:67;;;;139190:99;139226:7;139235:10;139190:99;;;;;;;;;;;;;;;;;:35;:99::i;70711:143::-;70771:7;70798:48;70343:1;70840:4;70803:42;;;;;;;;;:::i;:::-;;;;;;;;;;;;;70539:16;;;;;;;;70447:117;70862:284;70960:7;-1:-1:-1;;70984:15:0;;;;;;;70980:83;;;71036:6;;71044;70980:83;71085:52;;16238:16:1;71085:52:0;;;16222:102:1;-1:-1:-1;;16438:15:1;;;16425:11;;;16418:36;16484:15;;16470:12;;;16463:37;71080:58:0;;16516:12:1;;71085:52:0;16212:322:1;120676:305:0;120826:12;120855:7;120851:123;;;-1:-1:-1;120886:10:0;120879:17;;120851:123;120929:33;120937:10;120949:12;121150:17;;:21;121146:388;;121382:10;121376:17;121439:15;121426:10;121422:2;121418:19;121411:44;121334:136;121509:12;121502:20;;-1:-1:-1;;;121502:20:0;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:196:1:-;82:20;;-1:-1:-1;;;;;131:54:1;;121:65;;111:2;;200:1;197;190:12;111:2;63:147;;;:::o;215:395::-;278:8;288:6;342:3;335:4;327:6;323:17;319:27;309:2;;367:8;357;350:26;309:2;-1:-1:-1;397:20:1;;440:18;429:30;;426:2;;;479:8;469;462:26;426:2;523:4;515:6;511:17;499:29;;583:3;576:4;566:6;563:1;559:14;551:6;547:27;543:38;540:47;537:2;;;600:1;597;590:12;615:1169;689:5;742:3;735:4;727:6;723:17;719:27;709:2;;764:5;757;750:20;709:2;797:6;791:13;823:4;846:18;842:2;839:26;836:2;;;868:18;;:::i;:::-;908:36;940:2;935;932:1;928:10;924:19;908:36;:::i;:::-;966:3;990:2;985:3;978:15;1018:2;1013:3;1009:12;1002:19;;1053:2;1045:6;1041:15;1105:3;1100:2;1094;1091:1;1087:10;1079:6;1075:23;1071:32;1068:41;1065:2;;;1126:5;1119;1112:20;1065:2;1152:5;1166:589;1180:2;1177:1;1174:9;1166:589;;;1235:4;1274:2;1268:3;1263;1259:13;1255:22;1252:2;;;1294:5;1287;1280:20;1252:2;1328:22;;:::i;:::-;1383:3;1377:10;1370:5;1363:25;1439:2;1434:3;1430:12;1424:19;1419:2;1412:5;1408:14;1401:43;1467:2;1505:41;1542:2;1537:3;1533:12;1505:41;:::i;:::-;1489:14;;;1482:65;1570:2;1608:41;1636:12;;;1608:41;:::i;:::-;1592:14;;;1585:65;1663:18;;1701:12;;;;1733;;;;;1198:1;1191:9;1166:589;;;-1:-1:-1;1773:5:1;;699:1085;-1:-1:-1;;;;;;;699:1085:1:o;1789:164::-;1865:13;;1914;;1907:21;1897:32;;1887:2;;1943:1;1940;1933:12;1958:482;2000:5;2053:3;2046:4;2038:6;2034:17;2030:27;2020:2;;2075:5;2068;2061:20;2020:2;2115:6;2102:20;2146:48;2162:31;2190:2;2162:31;:::i;:::-;2146:48;:::i;:::-;2219:2;2210:7;2203:19;2265:3;2258:4;2253:2;2245:6;2241:15;2237:26;2234:35;2231:2;;;2286:5;2279;2272:20;2231:2;2355;2348:4;2340:6;2336:17;2329:4;2320:7;2316:18;2303:55;2378:16;;;2396:4;2374:27;2367:42;;;;2382:7;2010:430;-1:-1:-1;;2010:430:1:o;2445:444::-;2498:5;2551:3;2544:4;2536:6;2532:17;2528:27;2518:2;;2573:5;2566;2559:20;2518:2;2606:6;2600:13;2637:48;2653:31;2681:2;2653:31;:::i;2637:48::-;2710:2;2701:7;2694:19;2756:3;2749:4;2744:2;2736:6;2732:15;2728:26;2725:35;2722:2;;;2777:5;2770;2763:20;2722:2;2794:64;2855:2;2848:4;2839:7;2835:18;2828:4;2820:6;2816:17;2794:64;:::i;2894:136::-;2972:13;;2994:30;2972:13;2994:30;:::i;3035:167::-;3113:13;;3166:10;3155:22;;3145:33;;3135:2;;3192:1;3189;3182:12;3207:136;3285:13;;3307:30;3285:13;3307:30;:::i;3348:160::-;3425:13;;3478:4;3467:16;;3457:27;;3447:2;;3498:1;3495;3488:12;3513:196;3572:6;3625:2;3613:9;3604:7;3600:23;3596:32;3593:2;;;3646:6;3638;3631:22;3593:2;3674:29;3693:9;3674:29;:::i;3714:1357::-;3887:6;3895;3903;3911;3919;3927;3935;3943;3951;3959;4012:3;4000:9;3991:7;3987:23;3983:33;3980:2;;;4034:6;4026;4019:22;3980:2;4062:29;4081:9;4062:29;:::i;:::-;4052:39;;4142:2;4131:9;4127:18;4114:32;4165:18;4206:2;4198:6;4195:14;4192:2;;;4227:6;4219;4212:22;4192:2;4271:70;4333:7;4324:6;4313:9;4309:22;4271:70;:::i;:::-;4360:8;;-1:-1:-1;4245:96:1;-1:-1:-1;4448:2:1;4433:18;;4420:32;;-1:-1:-1;4464:16:1;;;4461:2;;;4498:6;4490;4483:22;4461:2;;4542:72;4606:7;4595:8;4584:9;4580:24;4542:72;:::i;:::-;4633:8;;-1:-1:-1;4516:98:1;-1:-1:-1;;4718:2:1;4703:18;;4690:32;4731:30;4690:32;4731:30;:::i;:::-;4780:5;-1:-1:-1;4832:3:1;4817:19;;4804:33;;-1:-1:-1;4889:3:1;4874:19;;4861:33;4903:32;4861:33;4903:32;:::i;:::-;4954:7;4944:17;;;5008:3;4997:9;4993:19;4980:33;4970:43;;5060:3;5049:9;5045:19;5032:33;5022:43;;3970:1101;;;;;;;;;;;;;:::o;5076:414::-;5153:6;5161;5214:2;5202:9;5193:7;5189:23;5185:32;5182:2;;;5235:6;5227;5220:22;5182:2;5263:29;5282:9;5263:29;:::i;:::-;5253:39;;5343:2;5332:9;5328:18;5315:32;5370:18;5362:6;5359:30;5356:2;;;5407:6;5399;5392:22;5356:2;5435:49;5476:7;5467:6;5456:9;5452:22;5435:49;:::i;:::-;5425:59;;;5172:318;;;;;:::o;5495:468::-;5592:6;5600;5653:2;5641:9;5632:7;5628:23;5624:32;5621:2;;;5674:6;5666;5659:22;5621:2;5719:9;5706:23;5752:18;5744:6;5741:30;5738:2;;;5789:6;5781;5774:22;5738:2;5833:70;5895:7;5886:6;5875:9;5871:22;5833:70;:::i;:::-;5922:8;;5807:96;;-1:-1:-1;5611:352:1;-1:-1:-1;;;;5611:352:1:o;5968:1138::-;6136:6;6144;6152;6160;6168;6176;6229:2;6217:9;6208:7;6204:23;6200:32;6197:2;;;6250:6;6242;6235:22;6197:2;6295:9;6282:23;6324:18;6365:2;6357:6;6354:14;6351:2;;;6386:6;6378;6371:22;6351:2;6430:70;6492:7;6483:6;6472:9;6468:22;6430:70;:::i;:::-;6519:8;;-1:-1:-1;6404:96:1;-1:-1:-1;6607:2:1;6592:18;;6579:32;;-1:-1:-1;6623:16:1;;;6620:2;;;6657:6;6649;6642:22;6620:2;6701:72;6765:7;6754:8;6743:9;6739:24;6701:72;:::i;:::-;6792:8;;-1:-1:-1;6675:98:1;-1:-1:-1;6880:2:1;6865:18;;6852:32;;-1:-1:-1;6896:16:1;;;6893:2;;;6930:6;6922;6915:22;6893:2;;6974:72;7038:7;7027:8;7016:9;7012:24;6974:72;:::i;:::-;6187:919;;;;-1:-1:-1;6187:919:1;;-1:-1:-1;6187:919:1;;7065:8;;6187:919;-1:-1:-1;;;6187:919:1:o;7111:1087::-;7260:6;7268;7276;7284;7292;7300;7353:3;7341:9;7332:7;7328:23;7324:33;7321:2;;;7375:6;7367;7360:22;7321:2;7420:9;7407:23;7449:18;7490:2;7482:6;7479:14;7476:2;;;7511:6;7503;7496:22;7476:2;7555:70;7617:7;7608:6;7597:9;7593:22;7555:70;:::i;:::-;7644:8;;-1:-1:-1;7529:96:1;-1:-1:-1;7732:2:1;7717:18;;7704:32;;-1:-1:-1;7748:16:1;;;7745:2;;;7782:6;7774;7767:22;7745:2;;7826:72;7890:7;7879:8;7868:9;7864:24;7826:72;:::i;:::-;7917:8;;-1:-1:-1;7800:98:1;-1:-1:-1;;8002:2:1;7987:18;;7974:32;8015:30;7974:32;8015:30;:::i;:::-;8064:5;-1:-1:-1;8121:2:1;8106:18;;8093:32;8134;8093;8134;:::i;:::-;8185:7;8175:17;;;7311:887;;;;;;;;:::o;8203:190::-;8262:6;8315:2;8303:9;8294:7;8290:23;8286:32;8283:2;;;8336:6;8328;8321:22;8283:2;-1:-1:-1;8364:23:1;;8273:120;-1:-1:-1;8273:120:1:o;8398:194::-;8468:6;8521:2;8509:9;8500:7;8496:23;8492:32;8489:2;;;8542:6;8534;8527:22;8489:2;-1:-1:-1;8570:16:1;;8479:113;-1:-1:-1;8479:113:1:o;8597:258::-;8665:6;8673;8726:2;8714:9;8705:7;8701:23;8697:32;8694:2;;;8747:6;8739;8732:22;8694:2;-1:-1:-1;;8775:23:1;;;8845:2;8830:18;;;8817:32;;-1:-1:-1;8684:171:1:o;8860:641::-;8930:6;8938;8991:2;8979:9;8970:7;8966:23;8962:32;8959:2;;;9012:6;9004;8997:22;8959:2;9057:9;9044:23;9086:18;9127:2;9119:6;9116:14;9113:2;;;9148:6;9140;9133:22;9113:2;9191:6;9180:9;9176:22;9166:32;;9236:7;9229:4;9225:2;9221:13;9217:27;9207:2;;9263:6;9255;9248:22;9207:2;9308;9295:16;9334:2;9326:6;9323:14;9320:2;;;9355:6;9347;9340:22;9320:2;9405:7;9400:2;9391:6;9387:2;9383:15;9379:24;9376:37;9373:2;;;9431:6;9423;9416:22;9373:2;9467;9459:11;;;;;9489:6;;-1:-1:-1;8949:552:1;;-1:-1:-1;;;;8949:552:1:o;9506:340::-;9574:6;9627:2;9615:9;9606:7;9602:23;9598:32;9595:2;;;9648:6;9640;9633:22;9595:2;9693:9;9680:23;9726:18;9718:6;9715:30;9712:2;;;9763:6;9755;9748:22;9712:2;9791:49;9832:7;9823:6;9812:9;9808:22;9791:49;:::i;9851:583::-;9938:6;9991:2;9979:9;9970:7;9966:23;9962:32;9959:2;;;10012:6;10004;9997:22;9959:2;10050;10044:9;10092:2;10084:6;10080:15;10161:6;10149:10;10146:22;10125:18;10113:10;10110:34;10107:62;10104:2;;;10172:18;;:::i;:::-;10208:2;10201:22;10245:23;;10277:30;10245:23;10277:30;:::i;:::-;10316:21;;10398:2;10383:18;;;10370:32;10353:15;;;10346:57;;;;-1:-1:-1;10323:6:1;9949:485;-1:-1:-1;9949:485:1:o;10439:1843::-;10553:6;10561;10569;10622:2;10610:9;10601:7;10597:23;10593:32;10590:2;;;10643:6;10635;10628:22;10590:2;10681:9;10675:16;10710:18;10751:2;10743:6;10740:14;10737:2;;;10772:6;10764;10757:22;10737:2;10800:22;;;;10856:6;10838:16;;;10834:29;10831:2;;;10881:6;10873;10866:22;10831:2;10912:22;;:::i;:::-;10957:31;10985:2;10957:31;:::i;:::-;10950:5;10943:46;11021:41;11058:2;11054;11050:11;11021:41;:::i;:::-;11016:2;11009:5;11005:14;10998:65;11095:41;11132:2;11128;11124:11;11095:41;:::i;:::-;11090:2;11083:5;11079:14;11072:65;11169:41;11206:2;11202;11198:11;11169:41;:::i;:::-;11164:2;11157:5;11153:14;11146:65;11258:3;11254:2;11250:12;11244:19;11238:3;11231:5;11227:15;11220:44;11297:42;11334:3;11330:2;11326:12;11297:42;:::i;:::-;11291:3;11284:5;11280:15;11273:67;11373:41;11409:3;11405:2;11401:12;11373:41;:::i;:::-;11367:3;11360:5;11356:15;11349:66;11454:3;11450:2;11446:12;11440:19;11484:2;11474:8;11471:16;11468:2;;;11505:6;11497;11490:22;11468:2;11547:55;11594:7;11583:8;11579:2;11575:17;11547:55;:::i;:::-;11541:3;11534:5;11530:15;11523:80;;11622:3;11657:41;11694:2;11690;11686:11;11657:41;:::i;:::-;11641:14;;;11634:65;11718:3;11752:11;;;11746:18;11776:16;;;11773:2;;;11810:6;11802;11795:22;11773:2;11851:76;11919:7;11908:8;11904:2;11900:17;11851:76;:::i;:::-;11835:14;;;11828:100;;;;-1:-1:-1;11947:3:1;11988:11;;;11982:18;11966:14;;;11959:42;11839:5;-1:-1:-1;12044:46:1;12086:2;12071:18;;12044:46;:::i;:::-;12034:56;;12136:2;12125:9;12121:18;12115:25;12099:41;;12165:2;12155:8;12152:16;12149:2;;;12186:6;12178;12171:22;12149:2;;12214:62;12268:7;12257:8;12246:9;12242:24;12214:62;:::i;:::-;12204:72;;;10580:1702;;;;;:::o;12287:255::-;12345:6;12398:2;12386:9;12377:7;12373:23;12369:32;12366:2;;;12419:6;12411;12404:22;12366:2;12463:9;12450:23;12482:30;12506:5;12482:30;:::i;12547:259::-;12616:6;12669:2;12657:9;12648:7;12644:23;12640:32;12637:2;;;12690:6;12682;12675:22;12637:2;12727:9;12721:16;12746:30;12770:5;12746:30;:::i;12811:323::-;12878:6;12886;12939:2;12927:9;12918:7;12914:23;12910:32;12907:2;;;12960:6;12952;12945:22;12907:2;13004:9;12991:23;13023:30;13047:5;13023:30;:::i;:::-;13072:5;13124:2;13109:18;;;;13096:32;;-1:-1:-1;;;12897:237:1:o;13334:216::-;13403:6;13456:2;13444:9;13435:7;13431:23;13427:32;13424:2;;;13477:6;13469;13462:22;13424:2;13505:39;13534:9;13505:39;:::i;13555:255::-;13613:6;13666:2;13654:9;13645:7;13641:23;13637:32;13634:2;;;13687:6;13679;13672:22;13634:2;13731:9;13718:23;13750:30;13774:5;13750:30;:::i;13815:471::-;13878:3;13916:5;13910:12;13943:6;13938:3;13931:19;13969:4;13998:2;13993:3;13989:12;13982:19;;14035:2;14028:5;14024:14;14056:3;14068:193;14082:6;14079:1;14076:13;14068:193;;;14131:48;14175:3;14166:6;14160:13;14692:12;;14706:6;14688:25;14676:38;;14763:4;14752:16;;;14746:23;14730:14;;14723:47;14666:110;14131:48;14208:4;14199:14;;;;;14236:15;;;;14104:1;14097:9;14068:193;;;-1:-1:-1;14277:3:1;;13886:400;-1:-1:-1;;;;;13886:400:1:o;14291:316::-;14332:3;14370:5;14364:12;14397:6;14392:3;14385:19;14413:63;14469:6;14462:4;14457:3;14453:14;14446:4;14439:5;14435:16;14413:63;:::i;:::-;14521:2;14509:15;-1:-1:-1;;14505:88:1;14496:98;;;;14596:4;14492:109;;14340:267;-1:-1:-1;;14340:267:1:o;14781:326::-;14862:5;14856:12;14851:3;14844:25;14915:4;14908:5;14904:16;14898:23;14930:53;14977:4;14972:3;14968:14;14954:12;15203:5;15197:12;15194:1;15183:27;15178:3;15171:40;15272:18;15264:4;15257:5;15253:16;15247:23;15243:48;15236:4;15231:3;15227:14;15220:72;15355:4;15348:5;15344:16;15338:23;15335:1;15324:38;15317:4;15312:3;15308:14;15301:62;15412:4;15405:5;15401:16;15395:23;15388:4;15383:3;15379:14;15372:47;15161:264;;;14930:53;-1:-1:-1;15031:4:1;15020:16;;;15014:23;15197:12;;15194:1;15183:27;15095:4;15086:14;;15171:40;15264:4;15253:16;;15247:23;15272:18;15243:48;15227:14;;;15220:72;15344:16;;;15338:23;15335:1;15324:38;15308:14;;;15301:62;15412:4;15401:16;15395:23;15379:14;;;;15372:47;134575:992:0:o;15430:274:1:-;15559:3;15597:6;15591:13;15613:53;15659:6;15654:3;15647:4;15639:6;15635:17;15613:53;:::i;:::-;15682:16;;;;;15567:137;-1:-1:-1;;15567:137:1:o;16539:425::-;16744:66;16735:6;16730:3;16726:16;16722:89;16717:3;16710:102;16692:3;16841:6;16835:13;16857:61;16911:6;16907:1;16902:3;16898:11;16891:4;16883:6;16879:17;16857:61;:::i;:::-;16938:16;;;;16956:1;16934:24;;16700:264;-1:-1:-1;;;16700:264:1:o;17532:327::-;17767:2;17756:9;17749:21;17730:4;17787:66;17849:2;17838:9;17834:18;17826:6;17787:66;:::i;17864:597::-;18233:2;18222:9;18215:21;18196:4;18259:66;18321:2;18310:9;18306:18;18298:6;18259:66;:::i;:::-;18373:9;18365:6;18361:22;18356:2;18345:9;18341:18;18334:50;18401:54;18448:6;18440;18401:54;:::i;18466:712::-;18689:2;18741:21;;;18811:13;;18714:18;;;18833:22;;;18660:4;;18689:2;18912:15;;;;18886:2;18871:18;;;18660:4;18958:194;18972:6;18969:1;18966:13;18958:194;;;19021:47;19064:3;19055:6;19049:13;19021:47;:::i;:::-;19127:15;;;;19097:6;19088:16;;;;;18994:1;18987:9;18958:194;;;-1:-1:-1;19169:3:1;;18669:509;-1:-1:-1;;;;;;18669:509:1:o;19557:450::-;19714:2;19703:9;19696:21;19753:6;19748:2;19737:9;19733:18;19726:34;19810:6;19802;19797:2;19786:9;19782:18;19769:48;19677:4;19837:22;;;19861:2;19833:31;;;19826:45;;;;19923:2;19911:15;;;-1:-1:-1;;19907:88:1;19892:104;19888:113;;19686:321;-1:-1:-1;19686:321:1:o;20012:217::-;20159:2;20148:9;20141:21;20122:4;20179:44;20219:2;20208:9;20204:18;20196:6;20179:44;:::i;28182:410::-;28435:2;28424:9;28417:21;28398:4;28473:6;28467:13;28516:2;28511;28500:9;28496:18;28489:30;28536:50;28582:2;28571:9;28567:18;28553:12;28536:50;:::i;28597:255::-;14692:12;;14706:6;14688:25;14676:38;;14763:4;14752:16;;;14746:23;14730:14;;;14723:47;28787:2;28772:18;;28799:47;14666:110;29362:739;29569:2;29558:9;29551:21;29532:4;29597:6;29591:13;29630:1;29626:2;29623:9;29613:2;;29636:18;;:::i;:::-;29692:2;29687;29676:9;29672:18;29665:30;;29742:2;29734:6;29730:15;29724:22;29782:1;29768:12;29765:19;29755:2;;29788:18;;:::i;:::-;29844:12;29839:2;29828:9;29824:18;29817:40;;29921:6;29915:2;29907:6;29903:15;29897:22;29893:35;29888:2;29877:9;29873:18;29866:63;29978:2;29970:6;29966:15;29960:22;30020:4;30013;30002:9;29998:20;29991:34;30042:53;30090:3;30079:9;30075:19;30059:14;30042:53;:::i;30106:251::-;30292:3;30277:19;;30305:46;30281:9;30333:6;30305:46;:::i;30362:239::-;15197:12;;15194:1;15183:27;15171:40;;15264:4;15253:16;;;15247:23;15272:18;15243:48;15227:14;;;15220:72;15355:4;15344:16;;;15338:23;15335:1;15324:38;15308:14;;;15301:62;15412:4;15401:16;;;15395:23;15379:14;;;15372:47;30540:3;30525:19;;30553:42;15161:264;30932:386;31139:2;31128:9;31121:21;31102:4;31177:6;31171:13;31220:2;31215;31204:9;31200:18;31193:30;31240:72;31308:2;31297:9;31293:18;31279:12;31240:72;:::i;34186:592::-;34263:4;34269:6;34329:11;34316:25;34419:66;34408:8;34392:14;34388:29;34384:102;34364:18;34360:127;34350:2;;34504:4;34498;34491:18;34350:2;34534:33;;34586:20;;;-1:-1:-1;34629:18:1;34618:30;;34615:2;;;34664:4;34658;34651:18;34615:2;34700:4;34688:17;;-1:-1:-1;34731:14:1;34727:27;;;34717:38;;34714:2;;;34768:1;34765;34758:12;34783:253;34855:2;34849:9;34897:4;34885:17;;34932:18;34917:34;;34953:22;;;34914:62;34911:2;;;34979:18;;:::i;:::-;35015:2;35008:22;34829:207;:::o;35041:255::-;35113:2;35107:9;35155:6;35143:19;;35192:18;35177:34;;35213:22;;;35174:62;35171:2;;;35239:18;;:::i;35301:334::-;35372:2;35366:9;35428:2;35418:13;;-1:-1:-1;;35414:86:1;35402:99;;35531:18;35516:34;;35552:22;;;35513:62;35510:2;;;35578:18;;:::i;:::-;35614:2;35607:22;35346:289;;-1:-1:-1;35346:289:1:o;35640:245::-;35688:4;35721:18;35713:6;35710:30;35707:2;;;35743:18;;:::i;:::-;-1:-1:-1;35800:2:1;35788:15;-1:-1:-1;;35784:88:1;35874:4;35780:99;;35697:188::o;35890:363::-;35995:9;36006;36048:8;36036:10;36033:24;36030:2;;;36078:9;36067;36060:28;36030:2;36115:6;36105:8;36102:20;36099:2;;;36143:9;36132;36125:28;36099:2;-1:-1:-1;;36177:23:1;;;36222:25;;;;;-1:-1:-1;36020:233:1:o;36258:128::-;36298:3;36329:1;36325:6;36322:1;36319:13;36316:2;;;36335:18;;:::i;:::-;-1:-1:-1;36371:9:1;;36306:80::o;36391:482::-;36480:1;36523:5;36480:1;36537:330;36558:7;36548:8;36545:21;36537:330;;;36677:4;-1:-1:-1;;36605:77:1;36599:4;36596:87;36593:2;;;36686:18;;:::i;:::-;36736:7;36726:8;36722:22;36719:2;;;36756:16;;;;36719:2;36835:22;;;;36795:15;;;;36537:330;;;36541:3;36455:418;;;;;:::o;36878:131::-;36938:5;36967:36;36994:8;36988:4;37063:5;37093:8;37083:2;;-1:-1:-1;37134:1:1;37148:5;;37083:2;37182:4;37172:2;;-1:-1:-1;37219:1:1;37233:5;;37172:2;37264:4;37282:1;37277:59;;;;37350:1;37345:130;;;;37257:218;;37277:59;37307:1;37298:10;;37321:5;;;37345:130;37382:3;37372:8;37369:17;37366:2;;;37389:18;;:::i;:::-;-1:-1:-1;;37445:1:1;37431:16;;37460:5;;37257:218;;37559:2;37549:8;37546:16;37540:3;37534:4;37531:13;37527:36;37521:2;37511:8;37508:16;37503:2;37497:4;37494:12;37490:35;37487:77;37484:2;;;-1:-1:-1;37596:19:1;;;37628:5;;37484:2;37675:34;37700:8;37694:4;37675:34;:::i;:::-;37805:6;-1:-1:-1;;37733:79:1;37724:7;37721:92;37718:2;;;37816:18;;:::i;:::-;37854:20;;37073:807;-1:-1:-1;;;37073:807:1:o;37885:228::-;37925:7;38051:1;-1:-1:-1;;37979:74:1;37976:1;37973:81;37968:1;37961:9;37954:17;37950:105;37947:2;;;38058:18;;:::i;:::-;-1:-1:-1;38098:9:1;;37937:176::o;38118:125::-;38158:4;38186:1;38183;38180:8;38177:2;;;38191:18;;:::i;:::-;-1:-1:-1;38228:9:1;;38167:76::o;38248:258::-;38320:1;38330:113;38344:6;38341:1;38338:13;38330:113;;;38420:11;;;38414:18;38401:11;;;38394:39;38366:2;38359:10;38330:113;;;38461:6;38458:1;38455:13;38452:2;;;-1:-1:-1;;38496:1:1;38478:16;;38471:27;38301:205::o;38511:195::-;38550:3;-1:-1:-1;;38574:5:1;38571:77;38568:2;;;38651:18;;:::i;:::-;-1:-1:-1;38698:1:1;38687:13;;38558:148::o;38711:184::-;-1:-1:-1;;;38760:1:1;38753:88;38860:4;38857:1;38850:15;38884:4;38881:1;38874:15;38900:184;-1:-1:-1;;;38949:1:1;38942:88;39049:4;39046:1;39039:15;39073:4;39070:1;39063:15;39089:184;-1:-1:-1;;;39138:1:1;39131:88;39238:4;39235:1;39228:15;39262:4;39259:1;39252:15;39278:117;39363:6;39356:5;39352:18;39345:5;39342:29;39332:2;;39385:1;39382;39375:12;39400:129;39485:18;39478:5;39474:30;39467:5;39464:41;39454:2;;39519:1;39516;39509:12
Swarm Source
ipfs://99b939a0e68f7cf23dd87f1d08ae171925bb84265dfec2ec4a23e360576bf683
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.