Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- PythUpgradable
- Optimization enabled
- true
- Compiler version
- v0.8.4+commit.c7e474f2
- Optimization runs
- 10000
- EVM Version
- default
- Verified at
- 2022-12-22T04:10:08.284522Z
Contract source code
/**
*Submitted for verification at cronoscan.com on 2022-12-07
*/
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/*
* @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/consumers/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;
}
}
/// @title IPythEvents contains the events that Pyth contract emits.
/// @dev This interface can be used for listening to the updates for off-chain and testing purposes.
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);
}
/// @title Consume prices from the Pyth Network (https://pyth.network/).
/// @dev Please refer to the guidance at https://docs.pyth.network/consumers/best-practices for how to consume prices safely.
/// @author Pyth Data Association
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)
error InvalidArgument();
// Update data is coming from an invalid data source.
error InvalidUpdateDataSource();
// Update data is invalid (e.g., deserialization error)
error InvalidUpdateData();
// Insufficient fee is paid to the method.
error InsufficientFee();
// There is no fresh update, whereas expected fresh updates.
error NoFreshUpdate();
// There is no price feed found within the given range or it does not exists.
error PriceFeedNotFoundWithinRange();
// Price feed not found or it is not pushed on-chain yet.
error PriceFeedNotFound();
// Requested price is stale.
error StalePrice();
// Given message is not a valid Wormhole VAA.
error InvalidWormholeVaa();
// Governance message is invalid (e.g., deserialization error).
error InvalidGovernanceMessage();
// Governance message is not for this contract.
error InvalidGovernanceTarget();
// Governance message is coming from an invalid data source.
error InvalidGovernanceDataSource();
// Governance message is old.
error OldGovernanceMessage();
}
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);
}
// contracts/Structs.sol
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;
}
}
// contracts/Messages.sol
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;
}
}
// contracts/Structs.sol
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;
}
}
// contracts/PythDeprecatedStructs.sol
// This contract contains self contained structs of all our deprecated structs.
// When deprecating the structs, make sure that there be no dependency to
// the sdk as the sdk might change.
//
// By storing these structs, we keep deprecated fields definitions correctly. Then,
// in the future, we can use them to cleanup their storage and redeem some gas back.
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;
}
}
// contracts/State.sol
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;
}
// contracts/Getters.sol
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;
}
}
// contracts/Setters.sol
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;
}
}
// contracts/Bridge.sol
abstract contract Pyth is PythGetters, PythSetters, AbstractPyth {
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 requiredFee = getUpdateFee(updateData);
if (msg.value < requiredFee) revert PythErrors.InsufficientFee();
for (uint i = 0; i < updateData.length; ) {
updatePriceBatchFromVm(updateData[i]);
unchecked {
i++;
}
}
}
/// 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) {
return singleUpdateFeeInWei() * updateData.length;
}
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)
{
unchecked {
{
uint requiredFee = getUpdateFee(updateData);
if (msg.value < requiredFee)
revert PythErrors.InsufficientFee();
}
priceFeeds = new PythStructs.PriceFeed[](priceIds.length);
for (uint i = 0; i < updateData.length; i++) {
bytes memory encoded;
{
IWormhole.VM memory vm = parseAndVerifyBatchAttestationVM(
updateData[i]
);
encoded = vm.payload;
}
(
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 the caller requested for this data.
uint k = 0;
for (; k < priceIds.length; k++) {
if (priceIds[k] == priceId) {
break;
}
}
// 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
);
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 = uint(info.publishTime);
priceFeeds[k].emaPrice.price = info.emaPrice;
priceFeeds[k].emaPrice.conf = info.emaConf;
priceFeeds[k].emaPrice.expo = info.expo;
priceFeeds[k].emaPrice.publishTime = uint(info.publishTime);
// Check the publish time of the price is within the given range
// if it is not, then set the id to 0 to indicate that this price id
// still does not have a valid price feed. This will allow other updates
// for this price id to be processed.
if (
priceFeeds[k].price.publishTime < minPublishTime ||
priceFeeds[k].price.publishTime > maxPublishTime
) {
priceFeeds[k].id = 0;
}
index += attestationSize;
}
}
for (uint k = 0; k < priceIds.length; k++) {
if (priceFeeds[k].id == 0) {
revert PythErrors.PriceFeedNotFoundWithinRange();
}
}
}
}
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.2.0";
}
}
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
/**
* @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 functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason 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 {
// 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
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/Initializable.sol)
/**
* @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.
*
* 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 initialize the implementation contract, you can either invoke the
* initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() initializer {}
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
// If the contract is initializing we ignore whether _initialized is set in order to support multiple
// inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
// contract may have been reentered.
require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} modifier, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
function _isConstructor() private view returns (bool) {
return !AddressUpgradeable.isContract(address(this));
}
}
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
/**
* @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);
}
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
/**
* @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);
}
// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)
/**
* @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) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
}
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
/**
* @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;
}
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/utils/UUPSUpgradeable.sol)
/**
* @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 that the this implementation remains valid after 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;
}
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
/**
* @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;
}
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
/**
* @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 Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
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;
}
// contracts/GovernanceStructs.sol
/**
* @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
}
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;
}
/// @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();
}
}
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
/**
* @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);
}
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
/**
* @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);
}
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
/**
* @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 functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason 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 {
// 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
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)
/**
* @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) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
}
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
/**
* @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);
}
}
}
// contracts/Governance.sol
/**
* @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);
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 {
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());
}
}
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 ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"error","name":"InsufficientFee","inputs":[]},{"type":"error","name":"InvalidArgument","inputs":[]},{"type":"error","name":"InvalidGovernanceDataSource","inputs":[]},{"type":"error","name":"InvalidGovernanceMessage","inputs":[]},{"type":"error","name":"InvalidGovernanceTarget","inputs":[]},{"type":"error","name":"InvalidUpdateData","inputs":[]},{"type":"error","name":"InvalidUpdateDataSource","inputs":[]},{"type":"error","name":"InvalidWormholeVaa","inputs":[]},{"type":"error","name":"NoFreshUpdate","inputs":[]},{"type":"error","name":"OldGovernanceMessage","inputs":[]},{"type":"error","name":"PriceFeedNotFound","inputs":[]},{"type":"error","name":"PriceFeedNotFoundWithinRange","inputs":[]},{"type":"error","name":"StalePrice","inputs":[]},{"type":"event","name":"AdminChanged","inputs":[{"type":"address","name":"previousAdmin","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"BatchPriceFeedUpdate","inputs":[{"type":"uint16","name":"chainId","internalType":"uint16","indexed":false},{"type":"uint64","name":"sequenceNumber","internalType":"uint64","indexed":false}],"anonymous":false},{"type":"event","name":"BeaconUpgraded","inputs":[{"type":"address","name":"beacon","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ContractUpgraded","inputs":[{"type":"address","name":"oldImplementation","internalType":"address","indexed":false},{"type":"address","name":"newImplementation","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"DataSourcesSet","inputs":[{"type":"tuple[]","name":"oldDataSources","internalType":"struct PythInternalStructs.DataSource[]","indexed":false,"components":[{"type":"uint16","name":"chainId","internalType":"uint16"},{"type":"bytes32","name":"emitterAddress","internalType":"bytes32"}]},{"type":"tuple[]","name":"newDataSources","internalType":"struct PythInternalStructs.DataSource[]","indexed":false,"components":[{"type":"uint16","name":"chainId","internalType":"uint16"},{"type":"bytes32","name":"emitterAddress","internalType":"bytes32"}]}],"anonymous":false},{"type":"event","name":"FeeSet","inputs":[{"type":"uint256","name":"oldFee","internalType":"uint256","indexed":false},{"type":"uint256","name":"newFee","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"GovernanceDataSourceSet","inputs":[{"type":"tuple","name":"oldDataSource","internalType":"struct PythInternalStructs.DataSource","indexed":false,"components":[{"type":"uint16","name":"chainId","internalType":"uint16"},{"type":"bytes32","name":"emitterAddress","internalType":"bytes32"}]},{"type":"tuple","name":"newDataSource","internalType":"struct PythInternalStructs.DataSource","indexed":false,"components":[{"type":"uint16","name":"chainId","internalType":"uint16"},{"type":"bytes32","name":"emitterAddress","internalType":"bytes32"}]},{"type":"uint64","name":"initialSequence","internalType":"uint64","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"PriceFeedUpdate","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32","indexed":true},{"type":"uint64","name":"publishTime","internalType":"uint64","indexed":false},{"type":"int64","name":"price","internalType":"int64","indexed":false},{"type":"uint64","name":"conf","internalType":"uint64","indexed":false}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"type":"address","name":"implementation","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ValidPeriodSet","inputs":[{"type":"uint256","name":"oldValidPeriod","internalType":"uint256","indexed":false},{"type":"uint256","name":"newValidPeriod","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"chainId","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeGovernanceInstruction","inputs":[{"type":"bytes","name":"encodedVM","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"price","internalType":"struct PythStructs.Price","components":[{"type":"int64","name":"price","internalType":"int64"},{"type":"uint64","name":"conf","internalType":"uint64"},{"type":"int32","name":"expo","internalType":"int32"},{"type":"uint256","name":"publishTime","internalType":"uint256"}]}],"name":"getEmaPrice","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"price","internalType":"struct PythStructs.Price","components":[{"type":"int64","name":"price","internalType":"int64"},{"type":"uint64","name":"conf","internalType":"uint64"},{"type":"int32","name":"expo","internalType":"int32"},{"type":"uint256","name":"publishTime","internalType":"uint256"}]}],"name":"getEmaPriceNoOlderThan","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32"},{"type":"uint256","name":"age","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"price","internalType":"struct PythStructs.Price","components":[{"type":"int64","name":"price","internalType":"int64"},{"type":"uint64","name":"conf","internalType":"uint64"},{"type":"int32","name":"expo","internalType":"int32"},{"type":"uint256","name":"publishTime","internalType":"uint256"}]}],"name":"getEmaPriceUnsafe","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"price","internalType":"struct PythStructs.Price","components":[{"type":"int64","name":"price","internalType":"int64"},{"type":"uint64","name":"conf","internalType":"uint64"},{"type":"int32","name":"expo","internalType":"int32"},{"type":"uint256","name":"publishTime","internalType":"uint256"}]}],"name":"getPrice","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"price","internalType":"struct PythStructs.Price","components":[{"type":"int64","name":"price","internalType":"int64"},{"type":"uint64","name":"conf","internalType":"uint64"},{"type":"int32","name":"expo","internalType":"int32"},{"type":"uint256","name":"publishTime","internalType":"uint256"}]}],"name":"getPriceNoOlderThan","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32"},{"type":"uint256","name":"age","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"price","internalType":"struct PythStructs.Price","components":[{"type":"int64","name":"price","internalType":"int64"},{"type":"uint64","name":"conf","internalType":"uint64"},{"type":"int32","name":"expo","internalType":"int32"},{"type":"uint256","name":"publishTime","internalType":"uint256"}]}],"name":"getPriceUnsafe","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"feeAmount","internalType":"uint256"}],"name":"getUpdateFee","inputs":[{"type":"bytes[]","name":"updateData","internalType":"bytes[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"feeAmount","internalType":"uint256"}],"name":"getUpdateFee","inputs":[{"type":"uint256","name":"updateDataSize","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getValidTimePeriod","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct PythInternalStructs.DataSource","components":[{"type":"uint16","name":"chainId","internalType":"uint16"},{"type":"bytes32","name":"emitterAddress","internalType":"bytes32"}]}],"name":"governanceDataSource","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"governanceDataSourceIndex","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"hashDataSource","inputs":[{"type":"tuple","name":"ds","internalType":"struct PythInternalStructs.DataSource","components":[{"type":"uint16","name":"chainId","internalType":"uint16"},{"type":"bytes32","name":"emitterAddress","internalType":"bytes32"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"wormhole","internalType":"address"},{"type":"uint16[]","name":"dataSourceEmitterChainIds","internalType":"uint16[]"},{"type":"bytes32[]","name":"dataSourceEmitterAddresses","internalType":"bytes32[]"},{"type":"uint16","name":"governanceEmitterChainId","internalType":"uint16"},{"type":"bytes32","name":"governanceEmitterAddress","internalType":"bytes32"},{"type":"uint64","name":"governanceInitialSequence","internalType":"uint64"},{"type":"uint256","name":"validTimePeriodSeconds","internalType":"uint256"},{"type":"uint256","name":"singleUpdateFeeInWei","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isValidDataSource","inputs":[{"type":"uint16","name":"dataSourceChainId","internalType":"uint16"},{"type":"bytes32","name":"dataSourceEmitterAddress","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isValidGovernanceDataSource","inputs":[{"type":"uint16","name":"governanceChainId","internalType":"uint16"},{"type":"bytes32","name":"governanceEmitterAddress","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"lastExecutedGovernanceSequence","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"latestPriceInfoPublishTime","inputs":[{"type":"bytes32","name":"priceId","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"tuple","name":"sgds","internalType":"struct PythGovernanceInstructions.AuthorizeGovernanceDataSourceTransferPayload","components":[{"type":"bytes","name":"claimVaa","internalType":"bytes"}]}],"name":"parseAuthorizeGovernanceDataSourceTransferPayload","inputs":[{"type":"bytes","name":"encodedPayload","internalType":"bytes"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"tuple","name":"gi","internalType":"struct PythGovernanceInstructions.GovernanceInstruction","components":[{"type":"uint8","name":"module","internalType":"enum PythGovernanceInstructions.GovernanceModule"},{"type":"uint8","name":"action","internalType":"enum PythGovernanceInstructions.GovernanceAction"},{"type":"uint16","name":"targetChainId","internalType":"uint16"},{"type":"bytes","name":"payload","internalType":"bytes"}]}],"name":"parseGovernanceInstruction","inputs":[{"type":"bytes","name":"encodedInstruction","internalType":"bytes"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"tuple[]","name":"priceFeeds","internalType":"struct PythStructs.PriceFeed[]","components":[{"type":"bytes32","name":"id","internalType":"bytes32"},{"type":"tuple","name":"price","internalType":"struct PythStructs.Price","components":[{"type":"int64","name":"price","internalType":"int64"},{"type":"uint64","name":"conf","internalType":"uint64"},{"type":"int32","name":"expo","internalType":"int32"},{"type":"uint256","name":"publishTime","internalType":"uint256"}]},{"type":"tuple","name":"emaPrice","internalType":"struct PythStructs.Price","components":[{"type":"int64","name":"price","internalType":"int64"},{"type":"uint64","name":"conf","internalType":"uint64"},{"type":"int32","name":"expo","internalType":"int32"},{"type":"uint256","name":"publishTime","internalType":"uint256"}]}]}],"name":"parsePriceFeedUpdates","inputs":[{"type":"bytes[]","name":"updateData","internalType":"bytes[]"},{"type":"bytes32[]","name":"priceIds","internalType":"bytes32[]"},{"type":"uint64","name":"minPublishTime","internalType":"uint64"},{"type":"uint64","name":"maxPublishTime","internalType":"uint64"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"tuple","name":"sgdsClaim","internalType":"struct PythGovernanceInstructions.RequestGovernanceDataSourceTransferPayload","components":[{"type":"uint32","name":"governanceDataSourceIndex","internalType":"uint32"}]}],"name":"parseRequestGovernanceDataSourceTransferPayload","inputs":[{"type":"bytes","name":"encodedPayload","internalType":"bytes"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"tuple","name":"sds","internalType":"struct PythGovernanceInstructions.SetDataSourcesPayload","components":[{"type":"tuple[]","name":"dataSources","internalType":"struct PythInternalStructs.DataSource[]","components":[{"type":"uint16","name":"chainId","internalType":"uint16"},{"type":"bytes32","name":"emitterAddress","internalType":"bytes32"}]}]}],"name":"parseSetDataSourcesPayload","inputs":[{"type":"bytes","name":"encodedPayload","internalType":"bytes"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"tuple","name":"sf","internalType":"struct PythGovernanceInstructions.SetFeePayload","components":[{"type":"uint256","name":"newFee","internalType":"uint256"}]}],"name":"parseSetFeePayload","inputs":[{"type":"bytes","name":"encodedPayload","internalType":"bytes"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"tuple","name":"svp","internalType":"struct PythGovernanceInstructions.SetValidPeriodPayload","components":[{"type":"uint256","name":"newValidPeriod","internalType":"uint256"}]}],"name":"parseSetValidPeriodPayload","inputs":[{"type":"bytes","name":"encodedPayload","internalType":"bytes"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"tuple","name":"uc","internalType":"struct PythGovernanceInstructions.UpgradeContractPayload","components":[{"type":"address","name":"newImplementation","internalType":"address"}]}],"name":"parseUpgradeContractPayload","inputs":[{"type":"bytes","name":"encodedPayload","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"priceFeedExists","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"proxiableUUID","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"pythUpgradableMagic","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"priceFeed","internalType":"struct PythStructs.PriceFeed","components":[{"type":"bytes32","name":"id","internalType":"bytes32"},{"type":"tuple","name":"price","internalType":"struct PythStructs.Price","components":[{"type":"int64","name":"price","internalType":"int64"},{"type":"uint64","name":"conf","internalType":"uint64"},{"type":"int32","name":"expo","internalType":"int32"},{"type":"uint256","name":"publishTime","internalType":"uint256"}]},{"type":"tuple","name":"emaPrice","internalType":"struct PythStructs.Price","components":[{"type":"int64","name":"price","internalType":"int64"},{"type":"uint64","name":"conf","internalType":"uint64"},{"type":"int32","name":"expo","internalType":"int32"},{"type":"uint256","name":"publishTime","internalType":"uint256"}]}]}],"name":"queryPriceFeed","inputs":[{"type":"bytes32","name":"id","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"singleUpdateFeeInWei","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"updatePriceFeeds","inputs":[{"type":"bytes[]","name":"updateData","internalType":"bytes[]"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"updatePriceFeedsIfNecessary","inputs":[{"type":"bytes[]","name":"updateData","internalType":"bytes[]"},{"type":"bytes32[]","name":"priceIds","internalType":"bytes32[]"},{"type":"uint64[]","name":"publishTimes","internalType":"uint64[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"upgradeTo","inputs":[{"type":"address","name":"newImplementation","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"upgradeToAndCall","inputs":[{"type":"address","name":"newImplementation","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct PythInternalStructs.DataSource[]","components":[{"type":"uint16","name":"chainId","internalType":"uint16"},{"type":"bytes32","name":"emitterAddress","internalType":"bytes32"}]}],"name":"validDataSources","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"validTimePeriodSeconds","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"version","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IWormhole"}],"name":"wormhole","inputs":[]}]
Contract Creation Code
0x60a06040523060601b6080523480156200001857600080fd5b50600054610100900460ff16620000365760005460ff161562000040565b62000040620000e5565b620000a85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b600054610100900460ff16158015620000cb576000805461ffff19166101011790555b8015620000de576000805461ff00191690555b5062000112565b6000620000fd306200010360201b6200271c1760201c565b15905090565b6001600160a01b03163b151590565b60805160601c6154a86200014d60003960008181610bbe01528181610c540152818161142e015281816114c401526115f301526154a86000f3fe6080604052600436106102dc5760003560e01c806387c5bd1b11610184578063b6ed701e116100d6578063d82d58a51161008a578063e3795cc111610064578063e3795cc114610994578063ef9e5e28146109ab578063f2fde38b146109be57600080fd5b8063d82d58a514610926578063e17efd481461095f578063e18910a31461097f57600080fd5b8063caaf43f1116100bb578063caaf43f1146108c4578063cb718a9b146108f1578063d47eed451461090657600080fd5b8063b6ed701e14610891578063b9256d28146108b157600080fd5b806396834ad311610138578063a4ae35e011610112578063a4ae35e014610818578063b5dcc91114610838578063b5ec02611461085857600080fd5b806396834ad3146107ae5780639a8a0592146107ce578063a38d81c6146107f657600080fd5b806389a5bb4d1161016957806389a5bb4d146107435780638da5cb5b146107635780639474f45b1461078e57600080fd5b806387c5bd1b146106d15780638881016f146106fe57600080fd5b80634f1ef2861161023d5780636b7f53ca116101f1578063715018a6116101cb578063715018a61461063b5780637b72bcae1461065057806384acd1bb1461068557600080fd5b80636b7f53ca146105c25780636c72f51b146105ef578063711a2e281461061b57600080fd5b806354fd4d501161022257806354fd4d5014610537578063586d3cf81461058357806358c67635146105a257600080fd5b80634f1ef2861461050f57806352d1902d1461052257600080fd5b8063437209a71161029457806348b6404d1161027957806348b6404d146104805780634c469d8c1461049f5780634d7a734e146104ef57600080fd5b8063437209a7146103ca5780634716e9c51461046057600080fd5b806331d98b3f116102c557806331d98b3f146103375780633659cfe614610364578063426234e41461038457600080fd5b8063146faf77146102e157806314dd317f14610303575b600080fd5b3480156102ed57600080fd5b506103016102fc366004614856565b6109de565b005b34801561030f57600080fd5b5061032361031e366004614b89565b610afc565b604051905181526020015b60405180910390f35b34801561034357600080fd5b50610357610352366004614acb565b610b70565b60405161032e919061508c565b34801561037057600080fd5b5061030161037f36600461483c565b610ba6565b34801561039057600080fd5b506040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015260405161032e9190615001565b3480156103d657600080fd5b506104506103e5366004614d9d565b6040805160f09390931b7fffff000000000000000000000000000000000000000000000000000000000000166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b604051901515815260200161032e565b61047361046e366004614a39565b610d95565b60405161032e9190614f55565b34801561048c57600080fd5b5060ce545b60405190815260200161032e565b3480156104ab57600080fd5b506104d66104ba366004614acb565b600090815260d5602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff909116815260200161032e565b3480156104fb57600080fd5b5061032361050a366004614b89565b611363565b61030161051d366004614917565b611416565b34801561052e57600080fd5b506104916115d9565b34801561054357600080fd5b50604080518082018252600581527f312e322e300000000000000000000000000000000000000000000000000000006020820152905161032e9190614fd3565b34801561058f57600080fd5b5060d25467ffffffffffffffff166104d6565b3480156105ae57600080fd5b506104506105bd366004614d9d565b6116ab565b3480156105ce57600080fd5b506105e26105dd366004614b89565b6116ce565b60405161032e919061501c565b3480156105fb57600080fd5b5060d45463ffffffff165b60405163ffffffff909116815260200161032e565b34801561062757600080fd5b50610357610636366004614afb565b611904565b34801561064757600080fd5b5061030161197a565b34801561065c57600080fd5b5061067061066b366004614b89565b6119ed565b604051905163ffffffff16815260200161032e565b34801561069157600080fd5b5060c95473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161032e565b3480156106dd57600080fd5b506106f16106ec366004614b89565b611a1b565b60405161032e91906150c7565b34801561070a57600080fd5b5061071e610719366004614b89565b611bb1565b604051905173ffffffffffffffffffffffffffffffffffffffff16815260200161032e565b34801561074f57600080fd5b5061049161075e366004614bbc565b611bef565b34801561076f57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166106ac565b34801561079a57600080fd5b506103576107a9366004614acb565b611c59565b3480156107ba57600080fd5b506103576107c9366004614acb565b611d05565b3480156107da57600080fd5b506107e3611dd1565b60405161ffff909116815260200161032e565b34801561080257600080fd5b5061080b611e74565b60405161032e9190614f1d565b34801561082457600080fd5b50610357610833366004614afb565b611ee7565b34801561084457600080fd5b50610357610853366004614acb565b611f14565b34801561086457600080fd5b50610450610873366004614acb565b600090815260d5602052604090205467ffffffffffffffff16151590565b34801561089d57600080fd5b506103016108ac366004614b1c565b611f44565b6103016108bf3660046149a3565b612224565b3480156108d057600080fd5b506108e46108df366004614acb565b612350565b60405161032e919061507d565b3480156108fd57600080fd5b5060cf54610491565b34801561091257600080fd5b50610491610921366004614963565b612557565b34801561093257600080fd5b50610952610941366004614b89565b604080516020810190915290815290565b60405161032e9190614fe6565b34801561096b57600080fd5b5061049161097a366004614acb565b61256d565b34801561098b57600080fd5b50610491612583565b3480156109a057600080fd5b506397a6f304610606565b6103016109b9366004614963565b61258e565b3480156109ca57600080fd5b506103016109d936600461483c565b612623565b600054610100900460ff166109f95760005460ff16156109fd565b303b155b610a745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600054610100900460ff16158015610a96576000805461ffff19166101011790555b610a9e612738565b610aa66127bd565b610ab88b8b8b8b8b8b8b8b8b8b61283a565b610ac061197a565b8015610aef57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b5050505050505050505050565b6040805160208101909152600081526000610b178382612b2d565b67ffffffffffffffff168252610b2e6008826151eb565b905080835114610b6a576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50919050565b604080516080810182526000808252602082018190529181018290526060810191909152610ba082610833612583565b92915050565b3073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161415610c525760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610a6b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610cc77f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610d505760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610a6b565b610d5981612b93565b610d928160005b6040519080825280601f01601f191660200182016040528015610d8a576020820181803683370190505b506000612bfa565b50565b60606000610da38888612557565b905080341015610ddf576040517f025dbdd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b508367ffffffffffffffff811115610e0757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610e9757816020015b610e84604080516060808201835260008083528351608081018552818152602081810183905294810182905291820152909182019081526040805160808101825260008082526020828101829052928201819052606082015291015290565b815260200190600190039081610e255790505b50905060005b868110156112e25760606000610ee38a8a85818110610ecc57634e487b7160e01b600052603260045260246000fd5b9050602002810190610ede91906150e2565b612dbb565b60e001519150600090508080610ef884612f3f565b92509250925060005b828110156112d1576040848601015160209060005b8c811015610f5957818e8e83818110610f3f57634e487b7160e01b600052603260045260246000fd5b905060200201351415610f5157610f59565b600101610f16565b808d1480610f915750898181518110610f8257634e487b7160e01b600052603260045260246000fd5b60209081029190910101515115155b15610fa257505050928101926112c9565b6000610faf8989886130d2565b509050828b8381518110610fd357634e487b7160e01b600052603260045260246000fd5b6020026020010151600001818152505080604001518b838151811061100857634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516000019060070b908160070b8152505080606001518b838151811061104957634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516020019067ffffffffffffffff16908167ffffffffffffffff168152505080602001518b838151811061109857634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516040019060030b908160030b81525050806000015167ffffffffffffffff168b83815181106110e357634e487b7160e01b600052603260045260246000fd5b602002602001015160200151606001818152505080608001518b838151811061111c57634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516000019060070b908160070b815250508060a001518b838151811061115d57634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516020019067ffffffffffffffff16908167ffffffffffffffff168152505080602001518b83815181106111ac57634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516040019060030b908160030b81525050806000015167ffffffffffffffff168b83815181106111f757634e487b7160e01b600052603260045260246000fd5b60200260200101516040015160600181815250508c67ffffffffffffffff168b838151811061123657634e487b7160e01b600052603260045260246000fd5b60200260200101516020015160600151108061128a57508b67ffffffffffffffff168b838151811061127857634e487b7160e01b600052603260045260246000fd5b60200260200101516020015160600151115b156112c0576000801b8b83815181106112b357634e487b7160e01b600052603260045260246000fd5b6020908102919091010151525b50505093820193505b600101610f01565b505060019093019250610e9d915050565b5060005b848110156113585781818151811061130e57634e487b7160e01b600052603260045260246000fd5b602090810291909101015151611350576040517f45805f5d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016112e6565b509695505050505050565b60408051602081019091526000815260008061137f8482612b2d565b905061138c6008836151eb565b9150600061139a8584612b2d565b90506113a76008846151eb565b92506113be67ffffffffffffffff8216600a615264565b6113d29067ffffffffffffffff841661532a565b84528451831461140e576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050919050565b3073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614156114c25760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610a6b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166115377f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16146115c05760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610a6b565b6115c982612b93565b6115d582826001612bfa565b5050565b60003073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146116865760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610a6b565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b60d05460009061ffff84811691161480156116c7575060d15482145b9392505050565b6116fa604080516080810190915280600081526020016000815260006020820152606060409091015290565b60008061170784826131fb565b905063ffffffff8116635054474d1461174c576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117576004836151eb565b915060006117658584613261565b90508060ff16600181111561178a57634e487b7160e01b600052602160045260246000fd5b849060018111156117ab57634e487b7160e01b600052602160045260246000fd5b908160018111156117cc57634e487b7160e01b600052602160045260246000fd5b9052506117da6001846151eb565b92506001845160018111156117ff57634e487b7160e01b600052602160045260246000fd5b14611836576040517f63daeb7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006118428685613261565b90508060ff16600581111561186757634e487b7160e01b600052602160045260246000fd5b8560200190600581111561188b57634e487b7160e01b600052602160045260246000fd5b908160058111156118ac57634e487b7160e01b600052602160045260246000fd5b9052506118ba6001856151eb565b93506118c686856132c7565b61ffff1660408601526118da6002856151eb565b93506118f5848588516118ed9190615367565b88919061332d565b60608601525092949350505050565b60408051608081018252600080825260208201819052918101829052606081019190915261193183611c59565b905081611942428360600151613455565b1115610ba0576040517f19abf40e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60335473ffffffffffffffffffffffffffffffffffffffff1633146119e15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a6b565b6119eb600061347a565b565b6040805160208101909152600081526000611a0883826131fb565b63ffffffff168252610b2e6004826151eb565b604080516020810190915260608152600080611a378482613261565b9050611a446001836151eb565b91508060ff1667ffffffffffffffff811115611a7057634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611ab557816020015b6040805180820190915260008082526020820152815260200190600190039081611a8e5790505b50835260005b8160ff16811015611b6f57611ad085846132c7565b8451805183908110611af257634e487b7160e01b600052603260045260246000fd5b602090810291909101015161ffff9091169052611b106002846151eb565b9250611b1c85846134f1565b8451805183908110611b3e57634e487b7160e01b600052603260045260246000fd5b60200260200101516020018181525050602083611b5b91906151eb565b925080611b67816153aa565b915050611abb565b5081845114611baa576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050919050565b6040805160208101909152600081526000611bcc8382613557565b73ffffffffffffffffffffffffffffffffffffffff168252610b2e6014826151eb565b600081600001518260200151604051602001611c3c92919060f09290921b7fffff000000000000000000000000000000000000000000000000000000000000168252600282015260220190565b604051602081830303815290604052805190602001209050919050565b60408051608081018252600080825260208083018281528385018381526060850184815287855260d590935294909220805467ffffffffffffffff808216938490526801000000000000000091829004600390810b810b900b9096526001820154600781810b810b900b865204909416909152909190610b6a576040517f14aebe6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051608081018252600080825260208083018281528385018381526060850184815287855260d590935294909220805467ffffffffffffffff80821693849052680100000000000000008204600390810b810b900b9096526c010000000000000000000000008104600790810b810b900b8552740100000000000000000000000000000000000000009004909416909152909190610b6a576040517f14aebe6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611df260c95473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16639a8a05926040518163ffffffff1660e01b815260040160206040518083038186803b158015611e3757600080fd5b505afa158015611e4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6f9190614d81565b905090565b606060c9600301805480602002602001604051908101604052809291908181526020016000905b82821015611ede5760008481526020908190206040805180820190915260028502909101805461ffff168252600190810154828401529083529092019101611e9b565b50505050905090565b60408051608081018252600080825260208201819052918101829052606081019190915261193183611d05565b604080516080810182526000808252602082018190529181018290526060810191909152610ba082610636612583565b6000611f8583838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506135cd92505050565b90506000611f968260e001516116ce565b9050611fa0611dd1565b61ffff16816040015161ffff1614158015611fc25750604081015161ffff1615155b15611ff9576040517f63daeb7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008160200151600581111561201f57634e487b7160e01b600052602160045260246000fd5b141561207e57604081015161ffff16612064576040517f63daeb7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120796120748260600151611bb1565b6137f8565b61221e565b6001816020015160058111156120a457634e487b7160e01b600052602160045260246000fd5b14156120cb576120796120c68260600151604080516020810190915290815290565b613801565b6002816020015160058111156120f157634e487b7160e01b600052602160045260246000fd5b141561210c576120796121078260600151611a1b565b613baf565b60038160200151600581111561213257634e487b7160e01b600052602160045260246000fd5b141561214d576120796121488260600151611363565b613d94565b60048160200151600581111561217357634e487b7160e01b600052602160045260246000fd5b141561218e576120796121898260600151610afc565b613de6565b6005816020015160058111156121b457634e487b7160e01b600052602160045260246000fd5b14156121ec576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b82811461225d576040517fa9cb9e0d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b838110156123155782828281811061228857634e487b7160e01b600052603260045260246000fd5b905060200201602081019061229d9190614de2565b67ffffffffffffffff166122ed8686848181106122ca57634e487b7160e01b600052603260045260246000fd5b90506020020135600090815260d5602052604090205467ffffffffffffffff1690565b67ffffffffffffffff16101561230d57612307878761258e565b50612348565b600101612260565b506040517fde2c57fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6123af604080516060808201835260008083528351608081018552818152602081810183905294810182905291820152909182019081526040805160808101825260008082526020828101829052928201819052606082015291015290565b6040805160c08082018352600080835260208084018290528385018290526060808501839052608080860184905260a095860184905288845260d5835286842087519586018852805467ffffffffffffffff808216885268010000000000000000808304600390810b810b900b968901969096526c010000000000000000000000008204600790810b810b810b9a89019a909a52740100000000000000000000000000000000000000009091048116938701939093526001015480880b880b90970b90850152940490931691810191909152805190915067ffffffffffffffff166124c6576040517f14aebe6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b91815260408083015160208084018051600793840b840b9052606080870151825167ffffffffffffffff9182169085015283880180518451600391820b820b9089015289519451948316948401949094526080890151878901805191880b90970b905260a089015186519083169501949094529251845190830b90920b919094015293519051931692019190915290565b60008161256360ce5490565b6116c7919061532a565b60008161257960ce5490565b610ba0919061532a565b6000611e6f60cf5490565b600061259a8383612557565b9050803410156125d6576040517f025dbdd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561221e5761261b84848381811061260457634e487b7160e01b600052603260045260246000fd5b905060200281019061261691906150e2565b613e23565b6001016125d9565b60335473ffffffffffffffffffffffffffffffffffffffff16331461268a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a6b565b73ffffffffffffffffffffffffffffffffffffffff81166127135760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a6b565b610d928161347a565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166127b55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a6b565b6119eb613e35565b600054610100900460ff166119eb5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a6b565b60c980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8c161790558786146128b3576040517fa9cb9e0d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b88811015612aad57600060405180604001604052808c8c858181106128eb57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906129009190614d65565b61ffff1681526020018a8a8581811061292957634e487b7160e01b600052603260045260246000fd5b602090810292909201359092528251838201516040805160f09390931b7fffff00000000000000000000000000000000000000000000000000000000000016838501526022808401929092528051808403909201825260429092018252805190830120600090815260cd9092529020549192505060ff16156129d7576040517fa9cb9e0d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160cd60006129e684611bef565b8152602080820192909252604001600090812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169315159390931790925560cc8054600181018255925282517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebe6002909302928301805461ffff191661ffff90921691909117905591909101517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebf9091015580612aa5816153aa565b9150506128b6565b506040805180820190915261ffff86168082526020820186905260d0805461ffff1916909117905560d185905560d280547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861617905550612b188260cf55565b612b218160ce55565b50505050505050505050565b6000612b3a8260086151eb565b83511015612b8a5760405162461bcd60e51b815260206004820152601460248201527f746f55696e7436345f6f75744f66426f756e64730000000000000000000000006044820152606401610a6b565b50016008015190565b60335473ffffffffffffffffffffffffffffffffffffffff163314610d925760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a6b565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612c3257612c2d83613ebb565b505050565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c7857600080fd5b505afa925050508015612ca8575060408051601f3d908101601f19168201909252612ca591810190614ae3565b60015b612d1a5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401610a6b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612daf5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401610a6b565b50612c2d838383613fab565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820181905261010082018390526101208201526101408101919091526000612e3460c95473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1663c0fd8bde85856040518363ffffffff1660e01b8152600401612e6e929190614fa4565b60006040518083038186803b158015612e8657600080fd5b505afa158015612e9a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612ec29190810190614c13565b50909250905080612eff576040517f2acbe91500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50612f0981613fd0565b610ba0576040517fe60dce7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808080612f52858260049101015190565b90506004840193508063ffffffff16635032574814612f9d576040517fe69ffece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002858501810151940193600361ffff821614612fe6576040517fe69ffece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002850194506000612ffc878760029101015190565b90506002860195506000613014888860019101015190565b90508161ffff16870196508060ff1660021461305c576040517fe69ffece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050508284016002015161ffff169150600283019250613081848460029101015190565b61ffff16905060028301925081810283018451146130cb576040517fe69ffece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9193909250565b6040805160c081018252600080825260208201818152828401828152606084018381526080850184815260a08601948552888a01968701516048880151600790810b810b909452605088015167ffffffffffffffff9081169093526054880151600390810b900b909452605c870151830b90920b909152606485015181169092526065840151607d94850151909216835291929060ff81166001141561317d576018820191506131b7565b8582018701600881015167ffffffffffffffff90811686526010820151600790810b900b6040870152601891820151166060860152909101905b50838111156131f2576040517fe69ffece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50935093915050565b60006132088260046151eb565b835110156132585760405162461bcd60e51b815260206004820152601460248201527f746f55696e7433325f6f75744f66426f756e64730000000000000000000000006044820152606401610a6b565b50016004015190565b600061326e8260016151eb565b835110156132be5760405162461bcd60e51b815260206004820152601360248201527f746f55696e74385f6f75744f66426f756e6473000000000000000000000000006044820152606401610a6b565b50016001015190565b60006132d48260026151eb565b835110156133245760405162461bcd60e51b815260206004820152601460248201527f746f55696e7431365f6f75744f66426f756e64730000000000000000000000006044820152606401610a6b565b50016002015190565b60608161333b81601f6151eb565b10156133895760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610a6b565b61339382846151eb565b845110156133e35760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610a6b565b606082158015613402576040519150600082526020820160405261344c565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561343b578051835260209283019201613423565b5050858452601f01601f1916604052505b50949350505050565b600081831115613470576134698284615367565b9050610ba0565b6134698383615367565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006134fe8260206151eb565b8351101561354e5760405162461bcd60e51b815260206004820152601560248201527f746f427974657333325f6f75744f66426f756e647300000000000000000000006044820152606401610a6b565b50016020015190565b60006135648260146151eb565b835110156135b45760405162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606401610a6b565b5001602001516c01000000000000000000000000900490565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201819052610100820183905261012082015261014081019190915260008061364760c95473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1663c0fd8bde856040518263ffffffff1660e01b815260040161367f9190614fd3565b60006040518083038186803b15801561369757600080fd5b505afa1580156136ab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526136d39190810190614c13565b50915091508061370f576040517f2acbe91500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613721826060015183608001516116ab565b613757576040517f360f2d8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60d25467ffffffffffffffff1667ffffffffffffffff168260a0015167ffffffffffffffff16116137b4576040517f88d1b84700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a082015160d280547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790555092915050565b610d928161404a565b60006138356040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b905060008061385960c95473ffffffffffffffffffffffffffffffffffffffff1690565b84516040517fc0fd8bde00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff929092169163c0fd8bde916138ad91600401614fd3565b60006040518083038186803b1580156138c557600080fd5b505afa1580156138d9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139019190810190614c13565b50915091508061393d576040517f2acbe91500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061394c8360e001516116ce565b9050613956611dd1565b61ffff16816040015161ffff16141580156139785750604081015161ffff1615155b156139af576040517f63daeb7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005816020015160058111156139d557634e487b7160e01b600052602160045260246000fd5b14613a0c576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613a1b82606001516119ed565b805190915063ffffffff16613a3560d45463ffffffff1690565b63ffffffff1610613a72576040517f88d1b84700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160d480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff909216919091179055604080518082018252606086015161ffff168082526080870151602080840182905260d0805461ffff19168417905560d182905560a089015160d280547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff90921691909117905584518086018652600080825290820152845180860190955291845290830152907f6bce23ef3d34e51710fe4700b43ba5f1733a6215c883f384671a4ece3ea8aa2090879060d25460408051845161ffff908116825260209586015186830152845116918101919091529290910151606083015267ffffffffffffffff16608082015260a00160405180910390a150505050505050565b6000613bb9611e74565b905060005b8151811015613c4f57600060c96004016000613c00858581518110613bf357634e487b7160e01b600052603260045260246000fd5b6020026020010151611bef565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055613c486001826151eb565b9050613bbe565b50613c5c60cc60006145d8565b60005b825151811015613d4f578251805160cc919083908110613c8f57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015182546001808201855560009485528385208351600290930201805461ffff191661ffff90931692909217825591909201519181019190915584518051919260cd929091613d009186908110613bf357634e487b7160e01b600052603260045260246000fd5b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905580613d47816153aa565b915050613c5f565b507fd451e0fcb7c5b9e13de533604d158069dad159841c45f39f09d379bfc423080d81613d7a611e74565b604051613d88929190614f30565b60405180910390a15050565b6000613d9f60ce5490565b825160ce5590507f74dbbbe280ef27b79a8a0c449d5ae2ba7a31849103241d0f98df70bbc9d03e3781613dd160ce5490565b60408051928352602083019190915201613d88565b6000613df160cf5490565b825160cf5590507fcdb88a22f82ddd76115ab7c66cf08eb1e40afe80c9b31017eb2cbdb1570b33ae81613dd160cf5490565b6115d5613e308383612dbb565b6141e7565b600054610100900460ff16613eb25760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a6b565b6119eb3361347a565b73ffffffffffffffffffffffffffffffffffffffff81163b613f455760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610a6b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b613fb48361442d565b600082511180613fc15750805b15612c2d5761221e838361447a565b6000610ba0826060015183608001516040805160f09390931b7fffff000000000000000000000000000000000000000000000000000000000000166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b600061408a7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b825190915061409a906000610d60565b3073ffffffffffffffffffffffffffffffffffffffff1663e3795cc16040518163ffffffff1660e01b815260040160206040518083038186803b1580156140e057600080fd5b505afa1580156140f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141189190614dc8565b63ffffffff166397a6f3041461415a576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a49816141ba7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b6040805173ffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201613d88565b60e0810151600080806141f984612f3f565b92509250925060005b828110156143d3576000806142188787866130d2565b600081815260d5602052604090205482519887019892945090925067ffffffffffffffff90811691168110156143c857600082815260d560209081526040918290208551815487840151888601516060808b015167ffffffffffffffff9586167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090951685176801000000000000000063ffffffff60039690960b959095168502177fffffffff00000000000000000000000000000000ffffffffffffffffffffffff166c01000000000000000000000000600794850b808916919091027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff16919091177401000000000000000000000000000000000000000092881692830217885560808d01516001909801805460a08f01519990950b88167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090951694909417979096169093029590951790558551918252938101919091529283019190915283917fd06a6b7f4918494b3719217d1802786c1f5112a6c1d88fe2cfec00b4584f6aec910160405180910390a25b505050600101614202565b50606085015160a08601516040805161ffff909316835267ffffffffffffffff90911660208301527f943f0e8a16c19895fb87cbeb1a349ed86d7f31923089dd36c1a1ed5e300f267b910160405180910390a15050505050565b61443681613ebb565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606073ffffffffffffffffffffffffffffffffffffffff83163b6145065760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e747261637400000000000000000000000000000000000000000000000000006064820152608401610a6b565b6000808473ffffffffffffffffffffffffffffffffffffffff168460405161452e9190614f01565b600060405180830381855af49150503d8060008114614569576040519150601f19603f3d011682016040523d82523d6000602084013e61456e565b606091505b5091509150614596828260405180606001604052806027815260200161544c6027913961459f565b95945050505050565b606083156145ae5750816116c7565b8251156145be5782518084602001fd5b8160405162461bcd60e51b8152600401610a6b9190614fd3565b5080546000825560020290600052602060002090810190610d9291905b8082111561461557805461ffff19168155600060018201556002016145f5565b5090565b803573ffffffffffffffffffffffffffffffffffffffff8116811461463d57600080fd5b919050565b60008083601f840112614653578182fd5b50813567ffffffffffffffff81111561466a578182fd5b6020830191508360208260051b850101111561468557600080fd5b9250929050565b600082601f83011261469c578081fd5b8151602067ffffffffffffffff8211156146b8576146b861540f565b6146c6818360051b01615192565b80838252828201915082860187848660071b89010111156146e5578586fd5b855b8581101561474857608080838b0312156146ff578788fd5b614707615145565b835181528684015187820152604061472081860161482b565b90820152606061473185820161482b565b9082015285529385019391909101906001016146e7565b5090979650505050505050565b8051801515811461463d57600080fd5b600082601f830112614775578081fd5b8135614788614783826151c3565b615192565b81815284602083860101111561479c578283fd5b816020850160208301379081016020019190915292915050565b600082601f8301126147c6578081fd5b81516147d4614783826151c3565b8181528460208386010111156147e8578283fd5b6147f982602083016020870161537e565b949350505050565b805161463d81615425565b805163ffffffff8116811461463d57600080fd5b805161463d81615435565b805160ff8116811461463d57600080fd5b60006020828403121561484d578081fd5b6116c782614619565b6000806000806000806000806000806101008b8d031215614875578586fd5b61487e8b614619565b995060208b013567ffffffffffffffff8082111561489a578788fd5b6148a68e838f01614642565b909b50995060408d01359150808211156148be578788fd5b506148cb8d828e01614642565b90985096505060608b01356148df81615425565b945060808b0135935060a08b01356148f681615435565b8093505060c08b0135915060e08b013590509295989b9194979a5092959850565b60008060408385031215614929578182fd5b61493283614619565b9150602083013567ffffffffffffffff81111561494d578182fd5b61495985828601614765565b9150509250929050565b60008060208385031215614975578182fd5b823567ffffffffffffffff81111561498b578283fd5b61499785828601614642565b90969095509350505050565b600080600080600080606087890312156149bb578384fd5b863567ffffffffffffffff808211156149d2578586fd5b6149de8a838b01614642565b909850965060208901359150808211156149f6578586fd5b614a028a838b01614642565b90965094506040890135915080821115614a1a578384fd5b50614a2789828a01614642565b979a9699509497509295939492505050565b60008060008060008060808789031215614a51578384fd5b863567ffffffffffffffff80821115614a68578586fd5b614a748a838b01614642565b90985096506020890135915080821115614a8c578586fd5b50614a9989828a01614642565b9095509350506040870135614aad81615435565b91506060870135614abd81615435565b809150509295509295509295565b600060208284031215614adc578081fd5b5035919050565b600060208284031215614af4578081fd5b5051919050565b60008060408385031215614b0d578182fd5b50508035926020909101359150565b60008060208385031215614b2e578182fd5b823567ffffffffffffffff80821115614b45578384fd5b818501915085601f830112614b58578384fd5b813581811115614b66578485fd5b866020828501011115614b77578485fd5b60209290920196919550909350505050565b600060208284031215614b9a578081fd5b813567ffffffffffffffff811115614bb0578182fd5b6147f984828501614765565b600060408284031215614bcd578081fd5b6040516040810181811067ffffffffffffffff82111715614bf057614bf061540f565b6040528235614bfe81615425565b81526020928301359281019290925250919050565b600080600060608486031215614c27578081fd5b835167ffffffffffffffff80821115614c3e578283fd5b908501906101608288031215614c52578283fd5b614c5a61516e565b614c638361482b565b8152614c716020840161480c565b6020820152614c826040840161480c565b6040820152614c9360608401614801565b606082015260808301516080820152614cae60a08401614820565b60a0820152614cbf60c0840161482b565b60c082015260e083015182811115614cd5578485fd5b614ce1898286016147b6565b60e083015250610100614cf581850161480c565b908201526101208381015183811115614d0c578586fd5b614d188a82870161468c565b918301919091525061014083810151908201529450614d3960208701614755565b93506040860151915080821115614d4e578283fd5b50614d5b868287016147b6565b9150509250925092565b600060208284031215614d76578081fd5b81356116c781615425565b600060208284031215614d92578081fd5b81516116c781615425565b60008060408385031215614daf578182fd5b8235614dba81615425565b946020939093013593505050565b600060208284031215614dd9578081fd5b6116c78261480c565b600060208284031215614df3578081fd5b81356116c781615435565b6000815180845260208085019450808401835b83811015614e4557614e32878351805161ffff168252602090810151910152565b6040969096019590820190600101614e11565b509495945050505050565b60008151808452614e6881602086016020860161537e565b601f01601f19169290920160200192915050565b805182526020810151614ec36020840182805160070b825267ffffffffffffffff6020820151166020830152604081015160030b6040830152606081015160608301525050565b50604090810151805160070b60a0840152602081015167ffffffffffffffff1660c08401529081015160030b60e08301526060015161010090910152565b60008251614f1381846020870161537e565b9190910192915050565b6020815260006116c76020830184614dfe565b604081526000614f436040830185614dfe565b82810360208401526145968185614dfe565b6020808252825182820181905260009190848201906040850190845b81811015614f9857614f84838551614e7c565b928401926101209290920191600101614f71565b50909695505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b6020815260006116c76020830184614e50565b60208152600082516020808401526147f96040840182614e50565b815161ffff1681526020808301519082015260408101610ba0565b602081526000825160028110615034576150346153f9565b80602084015250602083015160068110615050576150506153f9565b8060408401525061ffff604084015116606083015260608301516080808401526147f960a0840182614e50565b6101208101610ba08284614e7c565b815160070b815260208083015167ffffffffffffffff169082015260408083015160030b908201526060808301519082015260808101610ba0565b60208152600082516020808401526147f96040840182614dfe565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615116578283fd5b83018035915067ffffffffffffffff821115615130578283fd5b60200191503681900382131561468557600080fd5b6040516080810167ffffffffffffffff811182821017156151685761516861540f565b60405290565b604051610160810167ffffffffffffffff811182821017156151685761516861540f565b604051601f8201601f1916810167ffffffffffffffff811182821017156151bb576151bb61540f565b604052919050565b600067ffffffffffffffff8211156151dd576151dd61540f565b50601f01601f191660200190565b600082198211156151fe576151fe6153e3565b500190565b600181815b8085111561525c57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615242576152426153e3565b8085161561524f57918102915b93841c9390800290615208565b509250929050565b60006116c7838360008261527a57506001610ba0565b8161528757506000610ba0565b816001811461529d57600281146152a7576152c3565b6001915050610ba0565b60ff8411156152b8576152b86153e3565b50506001821b610ba0565b5060208310610133831016604e8410600b84101617156152e6575081810a610ba0565b6152f08383615203565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615322576153226153e3565b029392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615362576153626153e3565b500290565b600082821015615379576153796153e3565b500390565b60005b83811015615399578181015183820152602001615381565b8381111561221e5750506000910152565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156153dc576153dc6153e3565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b61ffff81168114610d9257600080fd5b67ffffffffffffffff81168114610d9257600080fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208b6bf04961e1e9107ec331071c06bf2701a68c6d300e06fb182fdaa500269b5e64736f6c63430008040033
Deployed ByteCode
0x6080604052600436106102dc5760003560e01c806387c5bd1b11610184578063b6ed701e116100d6578063d82d58a51161008a578063e3795cc111610064578063e3795cc114610994578063ef9e5e28146109ab578063f2fde38b146109be57600080fd5b8063d82d58a514610926578063e17efd481461095f578063e18910a31461097f57600080fd5b8063caaf43f1116100bb578063caaf43f1146108c4578063cb718a9b146108f1578063d47eed451461090657600080fd5b8063b6ed701e14610891578063b9256d28146108b157600080fd5b806396834ad311610138578063a4ae35e011610112578063a4ae35e014610818578063b5dcc91114610838578063b5ec02611461085857600080fd5b806396834ad3146107ae5780639a8a0592146107ce578063a38d81c6146107f657600080fd5b806389a5bb4d1161016957806389a5bb4d146107435780638da5cb5b146107635780639474f45b1461078e57600080fd5b806387c5bd1b146106d15780638881016f146106fe57600080fd5b80634f1ef2861161023d5780636b7f53ca116101f1578063715018a6116101cb578063715018a61461063b5780637b72bcae1461065057806384acd1bb1461068557600080fd5b80636b7f53ca146105c25780636c72f51b146105ef578063711a2e281461061b57600080fd5b806354fd4d501161022257806354fd4d5014610537578063586d3cf81461058357806358c67635146105a257600080fd5b80634f1ef2861461050f57806352d1902d1461052257600080fd5b8063437209a71161029457806348b6404d1161027957806348b6404d146104805780634c469d8c1461049f5780634d7a734e146104ef57600080fd5b8063437209a7146103ca5780634716e9c51461046057600080fd5b806331d98b3f116102c557806331d98b3f146103375780633659cfe614610364578063426234e41461038457600080fd5b8063146faf77146102e157806314dd317f14610303575b600080fd5b3480156102ed57600080fd5b506103016102fc366004614856565b6109de565b005b34801561030f57600080fd5b5061032361031e366004614b89565b610afc565b604051905181526020015b60405180910390f35b34801561034357600080fd5b50610357610352366004614acb565b610b70565b60405161032e919061508c565b34801561037057600080fd5b5061030161037f36600461483c565b610ba6565b34801561039057600080fd5b506040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015260405161032e9190615001565b3480156103d657600080fd5b506104506103e5366004614d9d565b6040805160f09390931b7fffff000000000000000000000000000000000000000000000000000000000000166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b604051901515815260200161032e565b61047361046e366004614a39565b610d95565b60405161032e9190614f55565b34801561048c57600080fd5b5060ce545b60405190815260200161032e565b3480156104ab57600080fd5b506104d66104ba366004614acb565b600090815260d5602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff909116815260200161032e565b3480156104fb57600080fd5b5061032361050a366004614b89565b611363565b61030161051d366004614917565b611416565b34801561052e57600080fd5b506104916115d9565b34801561054357600080fd5b50604080518082018252600581527f312e322e300000000000000000000000000000000000000000000000000000006020820152905161032e9190614fd3565b34801561058f57600080fd5b5060d25467ffffffffffffffff166104d6565b3480156105ae57600080fd5b506104506105bd366004614d9d565b6116ab565b3480156105ce57600080fd5b506105e26105dd366004614b89565b6116ce565b60405161032e919061501c565b3480156105fb57600080fd5b5060d45463ffffffff165b60405163ffffffff909116815260200161032e565b34801561062757600080fd5b50610357610636366004614afb565b611904565b34801561064757600080fd5b5061030161197a565b34801561065c57600080fd5b5061067061066b366004614b89565b6119ed565b604051905163ffffffff16815260200161032e565b34801561069157600080fd5b5060c95473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161032e565b3480156106dd57600080fd5b506106f16106ec366004614b89565b611a1b565b60405161032e91906150c7565b34801561070a57600080fd5b5061071e610719366004614b89565b611bb1565b604051905173ffffffffffffffffffffffffffffffffffffffff16815260200161032e565b34801561074f57600080fd5b5061049161075e366004614bbc565b611bef565b34801561076f57600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166106ac565b34801561079a57600080fd5b506103576107a9366004614acb565b611c59565b3480156107ba57600080fd5b506103576107c9366004614acb565b611d05565b3480156107da57600080fd5b506107e3611dd1565b60405161ffff909116815260200161032e565b34801561080257600080fd5b5061080b611e74565b60405161032e9190614f1d565b34801561082457600080fd5b50610357610833366004614afb565b611ee7565b34801561084457600080fd5b50610357610853366004614acb565b611f14565b34801561086457600080fd5b50610450610873366004614acb565b600090815260d5602052604090205467ffffffffffffffff16151590565b34801561089d57600080fd5b506103016108ac366004614b1c565b611f44565b6103016108bf3660046149a3565b612224565b3480156108d057600080fd5b506108e46108df366004614acb565b612350565b60405161032e919061507d565b3480156108fd57600080fd5b5060cf54610491565b34801561091257600080fd5b50610491610921366004614963565b612557565b34801561093257600080fd5b50610952610941366004614b89565b604080516020810190915290815290565b60405161032e9190614fe6565b34801561096b57600080fd5b5061049161097a366004614acb565b61256d565b34801561098b57600080fd5b50610491612583565b3480156109a057600080fd5b506397a6f304610606565b6103016109b9366004614963565b61258e565b3480156109ca57600080fd5b506103016109d936600461483c565b612623565b600054610100900460ff166109f95760005460ff16156109fd565b303b155b610a745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600054610100900460ff16158015610a96576000805461ffff19166101011790555b610a9e612738565b610aa66127bd565b610ab88b8b8b8b8b8b8b8b8b8b61283a565b610ac061197a565b8015610aef57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555b5050505050505050505050565b6040805160208101909152600081526000610b178382612b2d565b67ffffffffffffffff168252610b2e6008826151eb565b905080835114610b6a576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50919050565b604080516080810182526000808252602082018190529181018290526060810191909152610ba082610833612583565b92915050565b3073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000e5483bf7fc740675b44dcd4b0f90983f8689d804161415610c525760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610a6b565b7f000000000000000000000000e5483bf7fc740675b44dcd4b0f90983f8689d80473ffffffffffffffffffffffffffffffffffffffff16610cc77f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610d505760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610a6b565b610d5981612b93565b610d928160005b6040519080825280601f01601f191660200182016040528015610d8a576020820181803683370190505b506000612bfa565b50565b60606000610da38888612557565b905080341015610ddf576040517f025dbdd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b508367ffffffffffffffff811115610e0757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610e9757816020015b610e84604080516060808201835260008083528351608081018552818152602081810183905294810182905291820152909182019081526040805160808101825260008082526020828101829052928201819052606082015291015290565b815260200190600190039081610e255790505b50905060005b868110156112e25760606000610ee38a8a85818110610ecc57634e487b7160e01b600052603260045260246000fd5b9050602002810190610ede91906150e2565b612dbb565b60e001519150600090508080610ef884612f3f565b92509250925060005b828110156112d1576040848601015160209060005b8c811015610f5957818e8e83818110610f3f57634e487b7160e01b600052603260045260246000fd5b905060200201351415610f5157610f59565b600101610f16565b808d1480610f915750898181518110610f8257634e487b7160e01b600052603260045260246000fd5b60209081029190910101515115155b15610fa257505050928101926112c9565b6000610faf8989886130d2565b509050828b8381518110610fd357634e487b7160e01b600052603260045260246000fd5b6020026020010151600001818152505080604001518b838151811061100857634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516000019060070b908160070b8152505080606001518b838151811061104957634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516020019067ffffffffffffffff16908167ffffffffffffffff168152505080602001518b838151811061109857634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516040019060030b908160030b81525050806000015167ffffffffffffffff168b83815181106110e357634e487b7160e01b600052603260045260246000fd5b602002602001015160200151606001818152505080608001518b838151811061111c57634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516000019060070b908160070b815250508060a001518b838151811061115d57634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516020019067ffffffffffffffff16908167ffffffffffffffff168152505080602001518b83815181106111ac57634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516040019060030b908160030b81525050806000015167ffffffffffffffff168b83815181106111f757634e487b7160e01b600052603260045260246000fd5b60200260200101516040015160600181815250508c67ffffffffffffffff168b838151811061123657634e487b7160e01b600052603260045260246000fd5b60200260200101516020015160600151108061128a57508b67ffffffffffffffff168b838151811061127857634e487b7160e01b600052603260045260246000fd5b60200260200101516020015160600151115b156112c0576000801b8b83815181106112b357634e487b7160e01b600052603260045260246000fd5b6020908102919091010151525b50505093820193505b600101610f01565b505060019093019250610e9d915050565b5060005b848110156113585781818151811061130e57634e487b7160e01b600052603260045260246000fd5b602090810291909101015151611350576040517f45805f5d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016112e6565b509695505050505050565b60408051602081019091526000815260008061137f8482612b2d565b905061138c6008836151eb565b9150600061139a8584612b2d565b90506113a76008846151eb565b92506113be67ffffffffffffffff8216600a615264565b6113d29067ffffffffffffffff841661532a565b84528451831461140e576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050919050565b3073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000e5483bf7fc740675b44dcd4b0f90983f8689d8041614156114c25760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c00000000000000000000000000000000000000006064820152608401610a6b565b7f000000000000000000000000e5483bf7fc740675b44dcd4b0f90983f8689d80473ffffffffffffffffffffffffffffffffffffffff166115377f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16146115c05760405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f787900000000000000000000000000000000000000006064820152608401610a6b565b6115c982612b93565b6115d582826001612bfa565b5050565b60003073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000e5483bf7fc740675b44dcd4b0f90983f8689d80416146116865760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610a6b565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b60d05460009061ffff84811691161480156116c7575060d15482145b9392505050565b6116fa604080516080810190915280600081526020016000815260006020820152606060409091015290565b60008061170784826131fb565b905063ffffffff8116635054474d1461174c576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117576004836151eb565b915060006117658584613261565b90508060ff16600181111561178a57634e487b7160e01b600052602160045260246000fd5b849060018111156117ab57634e487b7160e01b600052602160045260246000fd5b908160018111156117cc57634e487b7160e01b600052602160045260246000fd5b9052506117da6001846151eb565b92506001845160018111156117ff57634e487b7160e01b600052602160045260246000fd5b14611836576040517f63daeb7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006118428685613261565b90508060ff16600581111561186757634e487b7160e01b600052602160045260246000fd5b8560200190600581111561188b57634e487b7160e01b600052602160045260246000fd5b908160058111156118ac57634e487b7160e01b600052602160045260246000fd5b9052506118ba6001856151eb565b93506118c686856132c7565b61ffff1660408601526118da6002856151eb565b93506118f5848588516118ed9190615367565b88919061332d565b60608601525092949350505050565b60408051608081018252600080825260208201819052918101829052606081019190915261193183611c59565b905081611942428360600151613455565b1115610ba0576040517f19abf40e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60335473ffffffffffffffffffffffffffffffffffffffff1633146119e15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a6b565b6119eb600061347a565b565b6040805160208101909152600081526000611a0883826131fb565b63ffffffff168252610b2e6004826151eb565b604080516020810190915260608152600080611a378482613261565b9050611a446001836151eb565b91508060ff1667ffffffffffffffff811115611a7057634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611ab557816020015b6040805180820190915260008082526020820152815260200190600190039081611a8e5790505b50835260005b8160ff16811015611b6f57611ad085846132c7565b8451805183908110611af257634e487b7160e01b600052603260045260246000fd5b602090810291909101015161ffff9091169052611b106002846151eb565b9250611b1c85846134f1565b8451805183908110611b3e57634e487b7160e01b600052603260045260246000fd5b60200260200101516020018181525050602083611b5b91906151eb565b925080611b67816153aa565b915050611abb565b5081845114611baa576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050919050565b6040805160208101909152600081526000611bcc8382613557565b73ffffffffffffffffffffffffffffffffffffffff168252610b2e6014826151eb565b600081600001518260200151604051602001611c3c92919060f09290921b7fffff000000000000000000000000000000000000000000000000000000000000168252600282015260220190565b604051602081830303815290604052805190602001209050919050565b60408051608081018252600080825260208083018281528385018381526060850184815287855260d590935294909220805467ffffffffffffffff808216938490526801000000000000000091829004600390810b810b900b9096526001820154600781810b810b900b865204909416909152909190610b6a576040517f14aebe6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051608081018252600080825260208083018281528385018381526060850184815287855260d590935294909220805467ffffffffffffffff80821693849052680100000000000000008204600390810b810b900b9096526c010000000000000000000000008104600790810b810b900b8552740100000000000000000000000000000000000000009004909416909152909190610b6a576040517f14aebe6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611df260c95473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16639a8a05926040518163ffffffff1660e01b815260040160206040518083038186803b158015611e3757600080fd5b505afa158015611e4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6f9190614d81565b905090565b606060c9600301805480602002602001604051908101604052809291908181526020016000905b82821015611ede5760008481526020908190206040805180820190915260028502909101805461ffff168252600190810154828401529083529092019101611e9b565b50505050905090565b60408051608081018252600080825260208201819052918101829052606081019190915261193183611d05565b604080516080810182526000808252602082018190529181018290526060810191909152610ba082610636612583565b6000611f8583838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506135cd92505050565b90506000611f968260e001516116ce565b9050611fa0611dd1565b61ffff16816040015161ffff1614158015611fc25750604081015161ffff1615155b15611ff9576040517f63daeb7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008160200151600581111561201f57634e487b7160e01b600052602160045260246000fd5b141561207e57604081015161ffff16612064576040517f63daeb7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120796120748260600151611bb1565b6137f8565b61221e565b6001816020015160058111156120a457634e487b7160e01b600052602160045260246000fd5b14156120cb576120796120c68260600151604080516020810190915290815290565b613801565b6002816020015160058111156120f157634e487b7160e01b600052602160045260246000fd5b141561210c576120796121078260600151611a1b565b613baf565b60038160200151600581111561213257634e487b7160e01b600052602160045260246000fd5b141561214d576120796121488260600151611363565b613d94565b60048160200151600581111561217357634e487b7160e01b600052602160045260246000fd5b141561218e576120796121898260600151610afc565b613de6565b6005816020015160058111156121b457634e487b7160e01b600052602160045260246000fd5b14156121ec576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b82811461225d576040517fa9cb9e0d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b838110156123155782828281811061228857634e487b7160e01b600052603260045260246000fd5b905060200201602081019061229d9190614de2565b67ffffffffffffffff166122ed8686848181106122ca57634e487b7160e01b600052603260045260246000fd5b90506020020135600090815260d5602052604090205467ffffffffffffffff1690565b67ffffffffffffffff16101561230d57612307878761258e565b50612348565b600101612260565b506040517fde2c57fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6123af604080516060808201835260008083528351608081018552818152602081810183905294810182905291820152909182019081526040805160808101825260008082526020828101829052928201819052606082015291015290565b6040805160c08082018352600080835260208084018290528385018290526060808501839052608080860184905260a095860184905288845260d5835286842087519586018852805467ffffffffffffffff808216885268010000000000000000808304600390810b810b900b968901969096526c010000000000000000000000008204600790810b810b810b9a89019a909a52740100000000000000000000000000000000000000009091048116938701939093526001015480880b880b90970b90850152940490931691810191909152805190915067ffffffffffffffff166124c6576040517f14aebe6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b91815260408083015160208084018051600793840b840b9052606080870151825167ffffffffffffffff9182169085015283880180518451600391820b820b9089015289519451948316948401949094526080890151878901805191880b90970b905260a089015186519083169501949094529251845190830b90920b919094015293519051931692019190915290565b60008161256360ce5490565b6116c7919061532a565b60008161257960ce5490565b610ba0919061532a565b6000611e6f60cf5490565b600061259a8383612557565b9050803410156125d6576040517f025dbdd400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561221e5761261b84848381811061260457634e487b7160e01b600052603260045260246000fd5b905060200281019061261691906150e2565b613e23565b6001016125d9565b60335473ffffffffffffffffffffffffffffffffffffffff16331461268a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a6b565b73ffffffffffffffffffffffffffffffffffffffff81166127135760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a6b565b610d928161347a565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166127b55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a6b565b6119eb613e35565b600054610100900460ff166119eb5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a6b565b60c980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8c161790558786146128b3576040517fa9cb9e0d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b88811015612aad57600060405180604001604052808c8c858181106128eb57634e487b7160e01b600052603260045260246000fd5b90506020020160208101906129009190614d65565b61ffff1681526020018a8a8581811061292957634e487b7160e01b600052603260045260246000fd5b602090810292909201359092528251838201516040805160f09390931b7fffff00000000000000000000000000000000000000000000000000000000000016838501526022808401929092528051808403909201825260429092018252805190830120600090815260cd9092529020549192505060ff16156129d7576040517fa9cb9e0d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160cd60006129e684611bef565b8152602080820192909252604001600090812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169315159390931790925560cc8054600181018255925282517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebe6002909302928301805461ffff191661ffff90921691909117905591909101517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebf9091015580612aa5816153aa565b9150506128b6565b506040805180820190915261ffff86168082526020820186905260d0805461ffff1916909117905560d185905560d280547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861617905550612b188260cf55565b612b218160ce55565b50505050505050505050565b6000612b3a8260086151eb565b83511015612b8a5760405162461bcd60e51b815260206004820152601460248201527f746f55696e7436345f6f75744f66426f756e64730000000000000000000000006044820152606401610a6b565b50016008015190565b60335473ffffffffffffffffffffffffffffffffffffffff163314610d925760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a6b565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612c3257612c2d83613ebb565b505050565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c7857600080fd5b505afa925050508015612ca8575060408051601f3d908101601f19168201909252612ca591810190614ae3565b60015b612d1a5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f7420555550530000000000000000000000000000000000006064820152608401610a6b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612daf5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c655555494400000000000000000000000000000000000000000000006064820152608401610a6b565b50612c2d838383613fab565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820181905261010082018390526101208201526101408101919091526000612e3460c95473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1663c0fd8bde85856040518363ffffffff1660e01b8152600401612e6e929190614fa4565b60006040518083038186803b158015612e8657600080fd5b505afa158015612e9a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612ec29190810190614c13565b50909250905080612eff576040517f2acbe91500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50612f0981613fd0565b610ba0576040517fe60dce7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808080612f52858260049101015190565b90506004840193508063ffffffff16635032574814612f9d576040517fe69ffece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002858501810151940193600361ffff821614612fe6576040517fe69ffece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002850194506000612ffc878760029101015190565b90506002860195506000613014888860019101015190565b90508161ffff16870196508060ff1660021461305c576040517fe69ffece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050508284016002015161ffff169150600283019250613081848460029101015190565b61ffff16905060028301925081810283018451146130cb576040517fe69ffece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9193909250565b6040805160c081018252600080825260208201818152828401828152606084018381526080850184815260a08601948552888a01968701516048880151600790810b810b909452605088015167ffffffffffffffff9081169093526054880151600390810b900b909452605c870151830b90920b909152606485015181169092526065840151607d94850151909216835291929060ff81166001141561317d576018820191506131b7565b8582018701600881015167ffffffffffffffff90811686526010820151600790810b900b6040870152601891820151166060860152909101905b50838111156131f2576040517fe69ffece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50935093915050565b60006132088260046151eb565b835110156132585760405162461bcd60e51b815260206004820152601460248201527f746f55696e7433325f6f75744f66426f756e64730000000000000000000000006044820152606401610a6b565b50016004015190565b600061326e8260016151eb565b835110156132be5760405162461bcd60e51b815260206004820152601360248201527f746f55696e74385f6f75744f66426f756e6473000000000000000000000000006044820152606401610a6b565b50016001015190565b60006132d48260026151eb565b835110156133245760405162461bcd60e51b815260206004820152601460248201527f746f55696e7431365f6f75744f66426f756e64730000000000000000000000006044820152606401610a6b565b50016002015190565b60608161333b81601f6151eb565b10156133895760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610a6b565b61339382846151eb565b845110156133e35760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610a6b565b606082158015613402576040519150600082526020820160405261344c565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561343b578051835260209283019201613423565b5050858452601f01601f1916604052505b50949350505050565b600081831115613470576134698284615367565b9050610ba0565b6134698383615367565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006134fe8260206151eb565b8351101561354e5760405162461bcd60e51b815260206004820152601560248201527f746f427974657333325f6f75744f66426f756e647300000000000000000000006044820152606401610a6b565b50016020015190565b60006135648260146151eb565b835110156135b45760405162461bcd60e51b815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606401610a6b565b5001602001516c01000000000000000000000000900490565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201819052610100820183905261012082015261014081019190915260008061364760c95473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1663c0fd8bde856040518263ffffffff1660e01b815260040161367f9190614fd3565b60006040518083038186803b15801561369757600080fd5b505afa1580156136ab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526136d39190810190614c13565b50915091508061370f576040517f2acbe91500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613721826060015183608001516116ab565b613757576040517f360f2d8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60d25467ffffffffffffffff1667ffffffffffffffff168260a0015167ffffffffffffffff16116137b4576040517f88d1b84700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a082015160d280547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790555092915050565b610d928161404a565b60006138356040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b905060008061385960c95473ffffffffffffffffffffffffffffffffffffffff1690565b84516040517fc0fd8bde00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff929092169163c0fd8bde916138ad91600401614fd3565b60006040518083038186803b1580156138c557600080fd5b505afa1580156138d9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139019190810190614c13565b50915091508061393d576040517f2acbe91500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061394c8360e001516116ce565b9050613956611dd1565b61ffff16816040015161ffff16141580156139785750604081015161ffff1615155b156139af576040517f63daeb7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005816020015160058111156139d557634e487b7160e01b600052602160045260246000fd5b14613a0c576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613a1b82606001516119ed565b805190915063ffffffff16613a3560d45463ffffffff1690565b63ffffffff1610613a72576040517f88d1b84700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160d480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff909216919091179055604080518082018252606086015161ffff168082526080870151602080840182905260d0805461ffff19168417905560d182905560a089015160d280547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff90921691909117905584518086018652600080825290820152845180860190955291845290830152907f6bce23ef3d34e51710fe4700b43ba5f1733a6215c883f384671a4ece3ea8aa2090879060d25460408051845161ffff908116825260209586015186830152845116918101919091529290910151606083015267ffffffffffffffff16608082015260a00160405180910390a150505050505050565b6000613bb9611e74565b905060005b8151811015613c4f57600060c96004016000613c00858581518110613bf357634e487b7160e01b600052603260045260246000fd5b6020026020010151611bef565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055613c486001826151eb565b9050613bbe565b50613c5c60cc60006145d8565b60005b825151811015613d4f578251805160cc919083908110613c8f57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015182546001808201855560009485528385208351600290930201805461ffff191661ffff90931692909217825591909201519181019190915584518051919260cd929091613d009186908110613bf357634e487b7160e01b600052603260045260246000fd5b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905580613d47816153aa565b915050613c5f565b507fd451e0fcb7c5b9e13de533604d158069dad159841c45f39f09d379bfc423080d81613d7a611e74565b604051613d88929190614f30565b60405180910390a15050565b6000613d9f60ce5490565b825160ce5590507f74dbbbe280ef27b79a8a0c449d5ae2ba7a31849103241d0f98df70bbc9d03e3781613dd160ce5490565b60408051928352602083019190915201613d88565b6000613df160cf5490565b825160cf5590507fcdb88a22f82ddd76115ab7c66cf08eb1e40afe80c9b31017eb2cbdb1570b33ae81613dd160cf5490565b6115d5613e308383612dbb565b6141e7565b600054610100900460ff16613eb25760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610a6b565b6119eb3361347a565b73ffffffffffffffffffffffffffffffffffffffff81163b613f455760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610a6b565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b613fb48361442d565b600082511180613fc15750805b15612c2d5761221e838361447a565b6000610ba0826060015183608001516040805160f09390931b7fffff000000000000000000000000000000000000000000000000000000000000166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b600061408a7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b825190915061409a906000610d60565b3073ffffffffffffffffffffffffffffffffffffffff1663e3795cc16040518163ffffffff1660e01b815260040160206040518083038186803b1580156140e057600080fd5b505afa1580156140f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141189190614dc8565b63ffffffff166397a6f3041461415a576040517f97363b3500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a49816141ba7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b6040805173ffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201613d88565b60e0810151600080806141f984612f3f565b92509250925060005b828110156143d3576000806142188787866130d2565b600081815260d5602052604090205482519887019892945090925067ffffffffffffffff90811691168110156143c857600082815260d560209081526040918290208551815487840151888601516060808b015167ffffffffffffffff9586167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090951685176801000000000000000063ffffffff60039690960b959095168502177fffffffff00000000000000000000000000000000ffffffffffffffffffffffff166c01000000000000000000000000600794850b808916919091027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff16919091177401000000000000000000000000000000000000000092881692830217885560808d01516001909801805460a08f01519990950b88167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090951694909417979096169093029590951790558551918252938101919091529283019190915283917fd06a6b7f4918494b3719217d1802786c1f5112a6c1d88fe2cfec00b4584f6aec910160405180910390a25b505050600101614202565b50606085015160a08601516040805161ffff909316835267ffffffffffffffff90911660208301527f943f0e8a16c19895fb87cbeb1a349ed86d7f31923089dd36c1a1ed5e300f267b910160405180910390a15050505050565b61443681613ebb565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606073ffffffffffffffffffffffffffffffffffffffff83163b6145065760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e747261637400000000000000000000000000000000000000000000000000006064820152608401610a6b565b6000808473ffffffffffffffffffffffffffffffffffffffff168460405161452e9190614f01565b600060405180830381855af49150503d8060008114614569576040519150601f19603f3d011682016040523d82523d6000602084013e61456e565b606091505b5091509150614596828260405180606001604052806027815260200161544c6027913961459f565b95945050505050565b606083156145ae5750816116c7565b8251156145be5782518084602001fd5b8160405162461bcd60e51b8152600401610a6b9190614fd3565b5080546000825560020290600052602060002090810190610d9291905b8082111561461557805461ffff19168155600060018201556002016145f5565b5090565b803573ffffffffffffffffffffffffffffffffffffffff8116811461463d57600080fd5b919050565b60008083601f840112614653578182fd5b50813567ffffffffffffffff81111561466a578182fd5b6020830191508360208260051b850101111561468557600080fd5b9250929050565b600082601f83011261469c578081fd5b8151602067ffffffffffffffff8211156146b8576146b861540f565b6146c6818360051b01615192565b80838252828201915082860187848660071b89010111156146e5578586fd5b855b8581101561474857608080838b0312156146ff578788fd5b614707615145565b835181528684015187820152604061472081860161482b565b90820152606061473185820161482b565b9082015285529385019391909101906001016146e7565b5090979650505050505050565b8051801515811461463d57600080fd5b600082601f830112614775578081fd5b8135614788614783826151c3565b615192565b81815284602083860101111561479c578283fd5b816020850160208301379081016020019190915292915050565b600082601f8301126147c6578081fd5b81516147d4614783826151c3565b8181528460208386010111156147e8578283fd5b6147f982602083016020870161537e565b949350505050565b805161463d81615425565b805163ffffffff8116811461463d57600080fd5b805161463d81615435565b805160ff8116811461463d57600080fd5b60006020828403121561484d578081fd5b6116c782614619565b6000806000806000806000806000806101008b8d031215614875578586fd5b61487e8b614619565b995060208b013567ffffffffffffffff8082111561489a578788fd5b6148a68e838f01614642565b909b50995060408d01359150808211156148be578788fd5b506148cb8d828e01614642565b90985096505060608b01356148df81615425565b945060808b0135935060a08b01356148f681615435565b8093505060c08b0135915060e08b013590509295989b9194979a5092959850565b60008060408385031215614929578182fd5b61493283614619565b9150602083013567ffffffffffffffff81111561494d578182fd5b61495985828601614765565b9150509250929050565b60008060208385031215614975578182fd5b823567ffffffffffffffff81111561498b578283fd5b61499785828601614642565b90969095509350505050565b600080600080600080606087890312156149bb578384fd5b863567ffffffffffffffff808211156149d2578586fd5b6149de8a838b01614642565b909850965060208901359150808211156149f6578586fd5b614a028a838b01614642565b90965094506040890135915080821115614a1a578384fd5b50614a2789828a01614642565b979a9699509497509295939492505050565b60008060008060008060808789031215614a51578384fd5b863567ffffffffffffffff80821115614a68578586fd5b614a748a838b01614642565b90985096506020890135915080821115614a8c578586fd5b50614a9989828a01614642565b9095509350506040870135614aad81615435565b91506060870135614abd81615435565b809150509295509295509295565b600060208284031215614adc578081fd5b5035919050565b600060208284031215614af4578081fd5b5051919050565b60008060408385031215614b0d578182fd5b50508035926020909101359150565b60008060208385031215614b2e578182fd5b823567ffffffffffffffff80821115614b45578384fd5b818501915085601f830112614b58578384fd5b813581811115614b66578485fd5b866020828501011115614b77578485fd5b60209290920196919550909350505050565b600060208284031215614b9a578081fd5b813567ffffffffffffffff811115614bb0578182fd5b6147f984828501614765565b600060408284031215614bcd578081fd5b6040516040810181811067ffffffffffffffff82111715614bf057614bf061540f565b6040528235614bfe81615425565b81526020928301359281019290925250919050565b600080600060608486031215614c27578081fd5b835167ffffffffffffffff80821115614c3e578283fd5b908501906101608288031215614c52578283fd5b614c5a61516e565b614c638361482b565b8152614c716020840161480c565b6020820152614c826040840161480c565b6040820152614c9360608401614801565b606082015260808301516080820152614cae60a08401614820565b60a0820152614cbf60c0840161482b565b60c082015260e083015182811115614cd5578485fd5b614ce1898286016147b6565b60e083015250610100614cf581850161480c565b908201526101208381015183811115614d0c578586fd5b614d188a82870161468c565b918301919091525061014083810151908201529450614d3960208701614755565b93506040860151915080821115614d4e578283fd5b50614d5b868287016147b6565b9150509250925092565b600060208284031215614d76578081fd5b81356116c781615425565b600060208284031215614d92578081fd5b81516116c781615425565b60008060408385031215614daf578182fd5b8235614dba81615425565b946020939093013593505050565b600060208284031215614dd9578081fd5b6116c78261480c565b600060208284031215614df3578081fd5b81356116c781615435565b6000815180845260208085019450808401835b83811015614e4557614e32878351805161ffff168252602090810151910152565b6040969096019590820190600101614e11565b509495945050505050565b60008151808452614e6881602086016020860161537e565b601f01601f19169290920160200192915050565b805182526020810151614ec36020840182805160070b825267ffffffffffffffff6020820151166020830152604081015160030b6040830152606081015160608301525050565b50604090810151805160070b60a0840152602081015167ffffffffffffffff1660c08401529081015160030b60e08301526060015161010090910152565b60008251614f1381846020870161537e565b9190910192915050565b6020815260006116c76020830184614dfe565b604081526000614f436040830185614dfe565b82810360208401526145968185614dfe565b6020808252825182820181905260009190848201906040850190845b81811015614f9857614f84838551614e7c565b928401926101209290920191600101614f71565b50909695505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b6020815260006116c76020830184614e50565b60208152600082516020808401526147f96040840182614e50565b815161ffff1681526020808301519082015260408101610ba0565b602081526000825160028110615034576150346153f9565b80602084015250602083015160068110615050576150506153f9565b8060408401525061ffff604084015116606083015260608301516080808401526147f960a0840182614e50565b6101208101610ba08284614e7c565b815160070b815260208083015167ffffffffffffffff169082015260408083015160030b908201526060808301519082015260808101610ba0565b60208152600082516020808401526147f96040840182614dfe565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615116578283fd5b83018035915067ffffffffffffffff821115615130578283fd5b60200191503681900382131561468557600080fd5b6040516080810167ffffffffffffffff811182821017156151685761516861540f565b60405290565b604051610160810167ffffffffffffffff811182821017156151685761516861540f565b604051601f8201601f1916810167ffffffffffffffff811182821017156151bb576151bb61540f565b604052919050565b600067ffffffffffffffff8211156151dd576151dd61540f565b50601f01601f191660200190565b600082198211156151fe576151fe6153e3565b500190565b600181815b8085111561525c57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615242576152426153e3565b8085161561524f57918102915b93841c9390800290615208565b509250929050565b60006116c7838360008261527a57506001610ba0565b8161528757506000610ba0565b816001811461529d57600281146152a7576152c3565b6001915050610ba0565b60ff8411156152b8576152b86153e3565b50506001821b610ba0565b5060208310610133831016604e8410600b84101617156152e6575081810a610ba0565b6152f08383615203565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615322576153226153e3565b029392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615362576153626153e3565b500290565b600082821015615379576153796153e3565b500390565b60005b83811015615399578181015183820152602001615381565b8381111561221e5750506000910152565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156153dc576153dc6153e3565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b61ffff81168114610d9257600080fd5b67ffffffffffffffff81168114610d9257600080fdfe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212208b6bf04961e1e9107ec331071c06bf2701a68c6d300e06fb182fdaa500269b5e64736f6c63430008040033