Source Code
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
PythUpgradable
Compiler Version
v0.8.29+commit.ab55807c
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "./Pyth.sol";
import "./PythInternalStructs.sol";
import "./PythGetters.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "./PythGovernance.sol";
import "./Pyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythErrors.sol";
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());
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "../libraries/external/UnsafeBytesLib.sol";
import "@pythnetwork/pyth-sdk-solidity/AbstractPyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
import "@pythnetwork/pyth-sdk-solidity/PythErrors.sol";
import "./PythAccumulator.sol";
import "./PythGetters.sol";
import "./PythSetters.sol";
import "./PythInternalStructs.sol";
abstract contract Pyth is
PythGetters,
PythSetters,
AbstractPyth,
PythAccumulator
{
function _initialize(
address wormhole,
uint16[] calldata dataSourceEmitterChainIds,
bytes32[] calldata dataSourceEmitterAddresses,
uint16 governanceEmitterChainId,
bytes32 governanceEmitterAddress,
uint64 governanceInitialSequence,
uint validTimePeriodSeconds,
uint singleUpdateFeeInWei
) internal {
setWormhole(wormhole);
if (
dataSourceEmitterChainIds.length !=
dataSourceEmitterAddresses.length
) revert PythErrors.InvalidArgument();
for (uint i = 0; i < dataSourceEmitterChainIds.length; i++) {
PythInternalStructs.DataSource memory ds = PythInternalStructs
.DataSource(
dataSourceEmitterChainIds[i],
dataSourceEmitterAddresses[i]
);
if (PythGetters.isValidDataSource(ds.chainId, ds.emitterAddress))
revert PythErrors.InvalidArgument();
_state.isValidDataSource[hashDataSource(ds)] = true;
_state.validDataSources.push(ds);
}
{
PythInternalStructs.DataSource memory ds = PythInternalStructs
.DataSource(governanceEmitterChainId, governanceEmitterAddress);
PythSetters.setGovernanceDataSource(ds);
PythSetters.setLastExecutedGovernanceSequence(
governanceInitialSequence
);
}
PythSetters.setValidTimePeriodSeconds(validTimePeriodSeconds);
PythSetters.setSingleUpdateFeeInWei(singleUpdateFeeInWei);
}
function updatePriceFeeds(
bytes[] calldata updateData
) public payable override {
uint totalNumUpdates = 0;
for (uint i = 0; i < updateData.length; ) {
totalNumUpdates += updatePriceInfosFromAccumulatorUpdate(
updateData[i]
);
unchecked {
i++;
}
}
uint requiredFee = getTotalFee(totalNumUpdates);
if (msg.value < requiredFee) revert PythErrors.InsufficientFee();
}
/// This method is deprecated, please use the `getUpdateFee(bytes[])` instead.
function getUpdateFee(
uint updateDataSize
) public view returns (uint feeAmount) {
// In the accumulator update data a single update can contain
// up to 255 messages and we charge a singleUpdateFee per each
// message
return
255 *
singleUpdateFeeInWei() *
updateDataSize +
transactionFeeInWei();
}
function getUpdateFee(
bytes[] calldata updateData
) public view override returns (uint feeAmount) {
uint totalNumUpdates = 0;
for (uint i = 0; i < updateData.length; i++) {
if (
updateData[i].length > 4 &&
UnsafeCalldataBytesLib.toUint32(updateData[i], 0) ==
ACCUMULATOR_MAGIC
) {
(
uint offset,
UpdateType updateType
) = extractUpdateTypeFromAccumulatorHeader(updateData[i]);
if (updateType != UpdateType.WormholeMerkle) {
revert PythErrors.InvalidUpdateData();
}
totalNumUpdates += parseWormholeMerkleHeaderNumUpdates(
updateData[i],
offset
);
} else {
revert PythErrors.InvalidUpdateData();
}
}
return getTotalFee(totalNumUpdates);
}
function getTwapUpdateFee(
bytes[] calldata updateData
) public view override returns (uint feeAmount) {
uint totalNumUpdates = 0;
// For TWAP updates, updateData is always length 2 (start and end points),
// but each VAA can contain multiple price feeds. We only need to count
// the number of updates in the first VAA since both VAAs will have the
// same number of price feeds.
if (
updateData[0].length > 4 &&
UnsafeCalldataBytesLib.toUint32(updateData[0], 0) ==
ACCUMULATOR_MAGIC
) {
(
uint offset,
UpdateType updateType
) = extractUpdateTypeFromAccumulatorHeader(updateData[0]);
if (updateType != UpdateType.WormholeMerkle) {
revert PythErrors.InvalidUpdateData();
}
totalNumUpdates += parseWormholeMerkleHeaderNumUpdates(
updateData[0],
offset
);
} else {
revert PythErrors.InvalidUpdateData();
}
return getTotalFee(totalNumUpdates);
}
// 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();
}
/// @dev Helper function to parse a single price update within a Merkle proof.
/// Parsed price feeds will be stored in the context.
function _parseSingleMerkleUpdate(
PythInternalStructs.MerkleData memory merkleData,
bytes calldata encoded,
uint offset,
PythInternalStructs.UpdateParseContext memory context
) internal pure returns (uint newOffset) {
PythInternalStructs.PriceInfo memory priceInfo;
bytes32 priceId;
uint64 prevPublishTime;
(
newOffset,
priceInfo,
priceId,
prevPublishTime
) = extractPriceInfoFromMerkleProof(merkleData.digest, encoded, offset);
uint k = 0;
for (; k < context.priceIds.length; k++) {
if (context.priceIds[k] == priceId) {
break;
}
}
// Check if the priceId was requested and not already filled
if (k < context.priceIds.length && context.priceFeeds[k].id == 0) {
uint publishTime = uint(priceInfo.publishTime);
if (
publishTime >= context.minAllowedPublishTime &&
publishTime <= context.maxAllowedPublishTime &&
(!context.checkUniqueness ||
context.minAllowedPublishTime > prevPublishTime)
) {
context.priceFeeds[k].id = priceId;
context.priceFeeds[k].price.price = priceInfo.price;
context.priceFeeds[k].price.conf = priceInfo.conf;
context.priceFeeds[k].price.expo = priceInfo.expo;
context.priceFeeds[k].price.publishTime = publishTime;
context.priceFeeds[k].emaPrice.price = priceInfo.emaPrice;
context.priceFeeds[k].emaPrice.conf = priceInfo.emaConf;
context.priceFeeds[k].emaPrice.expo = priceInfo.expo;
context.priceFeeds[k].emaPrice.publishTime = publishTime;
context.slots[k] = merkleData.slot;
}
}
}
/// @dev Processes a single entry from the updateData array.
function _processSingleUpdateDataBlob(
bytes calldata singleUpdateData,
PythInternalStructs.UpdateParseContext memory context
) internal view returns (uint64 numUpdates) {
// Check magic number and length first
if (
singleUpdateData.length <= 4 ||
UnsafeCalldataBytesLib.toUint32(singleUpdateData, 0) !=
ACCUMULATOR_MAGIC
) {
revert PythErrors.InvalidUpdateData();
}
uint offset;
{
UpdateType updateType;
(offset, updateType) = extractUpdateTypeFromAccumulatorHeader(
singleUpdateData
);
if (updateType != UpdateType.WormholeMerkle) {
revert PythErrors.InvalidUpdateData();
}
}
// Extract Merkle data
PythInternalStructs.MerkleData memory merkleData;
bytes calldata encoded;
(
offset,
merkleData.digest,
merkleData.numUpdates,
encoded,
merkleData.slot
) = extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedAndSlotFromAccumulatorUpdate(
singleUpdateData,
offset
);
// Process each update within the Merkle proof
for (uint j = 0; j < merkleData.numUpdates; j++) {
offset = _parseSingleMerkleUpdate(
merkleData,
encoded,
offset,
context
);
}
// Check final offset
if (offset != encoded.length) {
revert PythErrors.InvalidUpdateData();
}
// Return the number of updates in this blob for tracking
return merkleData.numUpdates;
}
function parsePriceFeedUpdatesWithConfig(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minAllowedPublishTime,
uint64 maxAllowedPublishTime,
bool checkUniqueness,
bool checkUpdateDataIsMinimal,
bool storeUpdatesIfFresh
)
public
payable
returns (
PythStructs.PriceFeed[] memory priceFeeds,
uint64[] memory slots
)
{
if (msg.value < getUpdateFee(updateData))
revert PythErrors.InsufficientFee();
// Create the context struct that holds all shared parameters
PythInternalStructs.UpdateParseContext
memory context = PythInternalStructs.UpdateParseContext({
priceIds: priceIds,
minAllowedPublishTime: minAllowedPublishTime,
maxAllowedPublishTime: maxAllowedPublishTime,
checkUniqueness: checkUniqueness,
checkUpdateDataIsMinimal: checkUpdateDataIsMinimal,
priceFeeds: new PythStructs.PriceFeed[](priceIds.length),
slots: new uint64[](priceIds.length)
});
// Track total updates for minimal update data check
uint64 totalUpdatesAcrossBlobs = 0;
unchecked {
// Process each update, passing the context struct
// Parsed results will be filled in context.priceFeeds and context.slots
for (uint i = 0; i < updateData.length; i++) {
totalUpdatesAcrossBlobs += _processSingleUpdateDataBlob(
updateData[i],
context
);
}
for (uint j = 0; j < priceIds.length; j++) {
PythStructs.PriceFeed memory pf = context.priceFeeds[j];
if (storeUpdatesIfFresh && pf.id != 0) {
updateLatestPriceIfNecessary(
priceIds[j],
PythInternalStructs.PriceInfo({
publishTime: uint64(pf.price.publishTime),
expo: pf.price.expo,
price: pf.price.price,
conf: pf.price.conf,
emaPrice: pf.emaPrice.price,
emaConf: pf.emaPrice.conf
})
);
}
}
}
// In minimal update data mode, revert if we have more or less updates than price IDs
if (
checkUpdateDataIsMinimal &&
totalUpdatesAcrossBlobs != priceIds.length
) {
revert PythErrors.InvalidArgument();
}
// Check all price feeds were found
for (uint k = 0; k < priceIds.length; k++) {
if (context.priceFeeds[k].id == 0) {
revert PythErrors.PriceFeedNotFoundWithinRange();
}
}
// Return results
return (context.priceFeeds, context.slots);
}
function parsePriceFeedUpdates(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minPublishTime,
uint64 maxPublishTime
)
external
payable
override
returns (PythStructs.PriceFeed[] memory priceFeeds)
{
(priceFeeds, ) = parsePriceFeedUpdatesWithConfig(
updateData,
priceIds,
minPublishTime,
maxPublishTime,
false,
false,
false
);
}
function extractTwapPriceInfos(
bytes calldata updateData
)
private
view
returns (
/// @return newOffset The next position in the update data after processing this TWAP update
/// @return priceInfos Array of extracted TWAP price information
/// @return priceIds Array of corresponding price feed IDs
uint newOffset,
PythStructs.TwapPriceInfo[] memory twapPriceInfos,
bytes32[] memory priceIds
)
{
UpdateType updateType;
uint offset;
bytes20 digest;
uint8 numUpdates;
bytes calldata encoded;
// Extract and validate the header for start data
(offset, updateType) = extractUpdateTypeFromAccumulatorHeader(
updateData
);
if (updateType != UpdateType.WormholeMerkle) {
revert PythErrors.InvalidUpdateData();
}
(
offset,
digest,
numUpdates,
encoded,
// slot ignored
) = extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedAndSlotFromAccumulatorUpdate(
updateData,
offset
);
// Add additional validation before extracting TWAP price info
if (offset >= updateData.length) {
revert PythErrors.InvalidUpdateData();
}
// Initialize arrays to store all price infos and ids from this update
twapPriceInfos = new PythStructs.TwapPriceInfo[](numUpdates);
priceIds = new bytes32[](numUpdates);
// Extract each TWAP price info from the merkle proof
for (uint i = 0; i < numUpdates; i++) {
PythStructs.TwapPriceInfo memory twapPriceInfo;
bytes32 priceId;
(
offset,
twapPriceInfo,
priceId
) = extractTwapPriceInfoFromMerkleProof(digest, encoded, offset);
twapPriceInfos[i] = twapPriceInfo;
priceIds[i] = priceId;
}
if (offset != encoded.length) {
revert PythErrors.InvalidTwapUpdateData();
}
newOffset = offset;
}
function parseTwapPriceFeedUpdates(
bytes[] calldata updateData,
bytes32[] calldata priceIds
)
external
payable
override
returns (PythStructs.TwapPriceFeed[] memory twapPriceFeeds)
{
// TWAP requires exactly 2 updates: one for the start point and one for the end point
if (updateData.length != 2) {
revert PythErrors.InvalidUpdateData();
}
uint requiredFee = getTwapUpdateFee(updateData);
if (msg.value < requiredFee) revert PythErrors.InsufficientFee();
// Process start update data
PythStructs.TwapPriceInfo[] memory startTwapPriceInfos;
bytes32[] memory startPriceIds;
{
uint offsetStart;
(
offsetStart,
startTwapPriceInfos,
startPriceIds
) = extractTwapPriceInfos(updateData[0]);
}
// Process end update data
PythStructs.TwapPriceInfo[] memory endTwapPriceInfos;
bytes32[] memory endPriceIds;
{
uint offsetEnd;
(offsetEnd, endTwapPriceInfos, endPriceIds) = extractTwapPriceInfos(
updateData[1]
);
}
// Verify that we have the same number of price feeds in start and end updates
if (startPriceIds.length != endPriceIds.length) {
revert PythErrors.InvalidTwapUpdateDataSet();
}
// Hermes always returns price feeds in the same order for start and end updates
// This allows us to assume startPriceIds[i] == endPriceIds[i] for efficiency
for (uint i = 0; i < startPriceIds.length; i++) {
if (startPriceIds[i] != endPriceIds[i]) {
revert PythErrors.InvalidTwapUpdateDataSet();
}
}
// Initialize the output array
twapPriceFeeds = new PythStructs.TwapPriceFeed[](priceIds.length);
// For each requested price ID, find matching start and end data points
for (uint i = 0; i < priceIds.length; i++) {
bytes32 requestedPriceId = priceIds[i];
int startIdx = -1;
// Find the index of this price ID in the startPriceIds array
// (which is the same as the endPriceIds array based on our validation above)
for (uint j = 0; j < startPriceIds.length; j++) {
if (startPriceIds[j] == requestedPriceId) {
startIdx = int(j);
break;
}
}
// If we found the price ID
if (startIdx >= 0) {
uint idx = uint(startIdx);
// Validate the pair of price infos
validateTwapPriceInfo(
startTwapPriceInfos[idx],
endTwapPriceInfos[idx]
);
// Calculate TWAP from these data points
twapPriceFeeds[i] = calculateTwap(
requestedPriceId,
startTwapPriceInfos[idx],
endTwapPriceInfos[idx]
);
}
}
// Ensure all requested price IDs were found
for (uint k = 0; k < priceIds.length; k++) {
if (twapPriceFeeds[k].id == 0) {
revert PythErrors.PriceFeedNotFoundWithinRange();
}
}
}
function validateTwapPriceInfo(
PythStructs.TwapPriceInfo memory twapPriceInfoStart,
PythStructs.TwapPriceInfo memory twapPriceInfoEnd
) private pure {
// First validate each individual price's uniqueness
if (
twapPriceInfoStart.prevPublishTime >= twapPriceInfoStart.publishTime
) {
revert PythErrors.InvalidTwapUpdateData();
}
if (twapPriceInfoEnd.prevPublishTime >= twapPriceInfoEnd.publishTime) {
revert PythErrors.InvalidTwapUpdateData();
}
// Then validate the relationship between the two data points
if (twapPriceInfoStart.expo != twapPriceInfoEnd.expo) {
revert PythErrors.InvalidTwapUpdateDataSet();
}
if (twapPriceInfoStart.publishSlot > twapPriceInfoEnd.publishSlot) {
revert PythErrors.InvalidTwapUpdateDataSet();
}
if (twapPriceInfoStart.publishTime > twapPriceInfoEnd.publishTime) {
revert PythErrors.InvalidTwapUpdateDataSet();
}
}
function parsePriceFeedUpdatesUnique(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minPublishTime,
uint64 maxPublishTime
)
external
payable
override
returns (PythStructs.PriceFeed[] memory priceFeeds)
{
(priceFeeds, ) = parsePriceFeedUpdatesWithConfig(
updateData,
priceIds,
minPublishTime,
maxPublishTime,
true,
false,
false
);
}
function getTotalFee(
uint totalNumUpdates
) private view returns (uint requiredFee) {
return
(totalNumUpdates * singleUpdateFeeInWei()) + transactionFeeInWei();
}
function findIndexOfPriceId(
bytes32[] calldata priceIds,
bytes32 targetPriceId
) private pure returns (uint index) {
uint k = 0;
for (; k < priceIds.length; k++) {
if (priceIds[k] == targetPriceId) {
break;
}
}
return k;
}
function fillPriceFeedFromPriceInfo(
PythStructs.PriceFeed[] memory priceFeeds,
uint k,
bytes32 priceId,
PythInternalStructs.PriceInfo memory info,
uint publishTime,
uint64[] memory slots,
uint64 slot
) private pure {
priceFeeds[k].id = priceId;
priceFeeds[k].price.price = info.price;
priceFeeds[k].price.conf = info.conf;
priceFeeds[k].price.expo = info.expo;
priceFeeds[k].price.publishTime = publishTime;
priceFeeds[k].emaPrice.price = info.emaPrice;
priceFeeds[k].emaPrice.conf = info.emaConf;
priceFeeds[k].emaPrice.expo = info.expo;
priceFeeds[k].emaPrice.publishTime = publishTime;
slots[k] = slot;
}
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.4.5-alpha.1";
}
/// @notice Calculates TWAP from two price points
/// @dev The calculation is done by taking the difference of cumulative values and dividing by the time difference
/// @param priceId The price feed ID
/// @param twapPriceInfoStart The starting price point
/// @param twapPriceInfoEnd The ending price point
/// @return twapPriceFeed The calculated TWAP price feed
function calculateTwap(
bytes32 priceId,
PythStructs.TwapPriceInfo memory twapPriceInfoStart,
PythStructs.TwapPriceInfo memory twapPriceInfoEnd
) private pure returns (PythStructs.TwapPriceFeed memory twapPriceFeed) {
twapPriceFeed.id = priceId;
twapPriceFeed.startTime = twapPriceInfoStart.publishTime;
twapPriceFeed.endTime = twapPriceInfoEnd.publishTime;
// Calculate differences between start and end points for slots and cumulative values
uint64 slotDiff = twapPriceInfoEnd.publishSlot -
twapPriceInfoStart.publishSlot;
int128 priceDiff = twapPriceInfoEnd.cumulativePrice -
twapPriceInfoStart.cumulativePrice;
uint128 confDiff = twapPriceInfoEnd.cumulativeConf -
twapPriceInfoStart.cumulativeConf;
// Calculate time-weighted average price (TWAP) and confidence by dividing
// the difference in cumulative values by the number of slots between data points
int128 twapPrice = priceDiff / int128(uint128(slotDiff));
uint128 twapConf = confDiff / uint128(slotDiff);
// The conversion from int128 to int64 is safe because:
// 1. Individual prices fit within int64 by protocol design
// 2. TWAP is essentially an average price over time (cumulativePrice₂-cumulativePrice₁)/slotDiff
// 3. This average must be within the range of individual prices that went into the calculation
// We use int128 only as an intermediate type to safely handle cumulative sums
twapPriceFeed.twap.price = int64(twapPrice);
twapPriceFeed.twap.conf = uint64(twapConf);
twapPriceFeed.twap.expo = twapPriceInfoStart.expo;
twapPriceFeed.twap.publishTime = twapPriceInfoEnd.publishTime;
// Calculate downSlotsRatio as a value between 0 and 1,000,000
// 0 means no slots were missed, 1,000,000 means all slots were missed
uint64 totalDownSlots = twapPriceInfoEnd.numDownSlots -
twapPriceInfoStart.numDownSlots;
uint64 downSlotsRatio = (totalDownSlots * 1_000_000) / slotDiff;
// Safely downcast to uint32 (sufficient for value range 0-1,000,000)
twapPriceFeed.downSlotsRatio = uint32(downSlotsRatio);
return twapPriceFeed;
}
}// contracts/Structs.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "../libraries/external/BytesLib.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
contract PythInternalStructs {
using BytesLib for bytes;
/// Internal struct to hold parameters for update processing
/// @dev Storing these variable in a struct rather than local variables
/// helps reduce stack depth when passing arguments to functions.
struct UpdateParseContext {
bytes32[] priceIds;
uint64 minAllowedPublishTime;
uint64 maxAllowedPublishTime;
bool checkUniqueness;
/// When checkUpdateDataIsMinimal is true, parsing will revert
/// if the number of passed in updates exceeds or is less than
/// the length of priceIds.
bool checkUpdateDataIsMinimal;
PythStructs.PriceFeed[] priceFeeds;
uint64[] slots;
}
/// The initial Merkle header data in an AccumulatorUpdate. The encoded bytes
/// are kept in calldata for gas efficiency.
/// @dev Storing these variable in a struct rather than local variables
/// helps reduce stack depth when passing arguments to functions.
struct MerkleData {
bytes20 digest;
uint8 numUpdates;
uint64 slot;
}
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/Getters.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "../wormhole/interfaces/IWormhole.sol";
import "./PythInternalStructs.sol";
import "./PythState.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;
}
function transactionFeeInWei() public view returns (uint) {
return _state.transactionFeeInWei;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.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.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import "./Initializable.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 the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*/
function upgradeTo(address newImplementation) external virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*/
function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.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 Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// contracts/Governance.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "./PythGovernanceInstructions.sol";
import "./PythInternalStructs.sol";
import "./PythGetters.sol";
import "./PythSetters.sol";
import "@pythnetwork/pyth-sdk-solidity/PythErrors.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.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);
event WormholeAddressSet(
address oldWormholeAddress,
address newWormholeAddress
);
event TransactionFeeSet(uint oldFee, uint newFee);
event FeeWithdrawn(address targetAddress, uint fee);
function verifyGovernanceVM(
bytes memory encodedVM
) internal returns (IWormhole.VM memory parsedVM) {
(IWormhole.VM memory vm, bool valid, ) = wormhole().parseAndVerifyVM(
encodedVM
);
if (!valid) revert PythErrors.InvalidWormholeVaa();
if (!isValidGovernanceDataSource(vm.emitterChainId, vm.emitterAddress))
revert PythErrors.InvalidGovernanceDataSource();
if (vm.sequence <= lastExecutedGovernanceSequence())
revert PythErrors.OldGovernanceMessage();
setLastExecutedGovernanceSequence(vm.sequence);
return vm;
}
function executeGovernanceInstruction(bytes calldata encodedVM) public {
IWormhole.VM memory vm = verifyGovernanceVM(encodedVM);
GovernanceInstruction memory gi = parseGovernanceInstruction(
vm.payload
);
if (gi.targetChainId != chainId() && gi.targetChainId != 0)
revert PythErrors.InvalidGovernanceTarget();
if (gi.action == GovernanceAction.UpgradeContract) {
if (gi.targetChainId == 0)
revert PythErrors.InvalidGovernanceTarget();
upgradeContract(parseUpgradeContractPayload(gi.payload));
} else if (
gi.action == GovernanceAction.AuthorizeGovernanceDataSourceTransfer
) {
AuthorizeGovernanceDataSourceTransfer(
parseAuthorizeGovernanceDataSourceTransferPayload(gi.payload)
);
} else if (gi.action == GovernanceAction.SetDataSources) {
setDataSources(parseSetDataSourcesPayload(gi.payload));
} else if (gi.action == GovernanceAction.SetFee) {
setFee(parseSetFeePayload(gi.payload));
} else if (gi.action == GovernanceAction.SetValidPeriod) {
setValidPeriod(parseSetValidPeriodPayload(gi.payload));
} else if (
gi.action == GovernanceAction.RequestGovernanceDataSourceTransfer
) {
// RequestGovernanceDataSourceTransfer can be only part of AuthorizeGovernanceDataSourceTransfer message
revert PythErrors.InvalidGovernanceMessage();
} else if (gi.action == GovernanceAction.SetWormholeAddress) {
if (gi.targetChainId == 0)
revert PythErrors.InvalidGovernanceTarget();
setWormholeAddress(
parseSetWormholeAddressPayload(gi.payload),
encodedVM
);
} else if (gi.action == GovernanceAction.SetFeeInToken) {
// No-op for EVM chains
} else if (gi.action == GovernanceAction.SetTransactionFee) {
setTransactionFee(parseSetTransactionFeePayload(gi.payload));
} else if (gi.action == GovernanceAction.WithdrawFee) {
withdrawFee(parseWithdrawFeePayload(gi.payload));
} else {
revert PythErrors.InvalidGovernanceMessage();
}
}
function upgradeContract(UpgradeContractPayload memory payload) internal {
// This method on this contract does not have enough access to execute this, it should be executed on the
// upgradable contract.
upgradeUpgradableContract(payload);
}
function upgradeUpgradableContract(
UpgradeContractPayload memory payload
) internal virtual;
// Transfer the governance data source to a new value with sanity checks
// to ensure the new governance data source can manage the contract.
function AuthorizeGovernanceDataSourceTransfer(
AuthorizeGovernanceDataSourceTransferPayload memory payload
) internal {
PythInternalStructs.DataSource
memory oldGovernanceDatSource = governanceDataSource();
// Make sure the claimVaa is a valid VAA with RequestGovernanceDataSourceTransfer governance message
// If it's valid then its emitter can take over the governance from the current emitter.
// The VAA is checked here to ensure that the new governance data source is valid and can send message
// through wormhole.
(IWormhole.VM memory vm, bool valid, ) = wormhole().parseAndVerifyVM(
payload.claimVaa
);
if (!valid) revert PythErrors.InvalidWormholeVaa();
GovernanceInstruction memory gi = parseGovernanceInstruction(
vm.payload
);
if (gi.targetChainId != chainId() && gi.targetChainId != 0)
revert PythErrors.InvalidGovernanceTarget();
if (gi.action != GovernanceAction.RequestGovernanceDataSourceTransfer)
revert PythErrors.InvalidGovernanceMessage();
RequestGovernanceDataSourceTransferPayload
memory claimPayload = parseRequestGovernanceDataSourceTransferPayload(
gi.payload
);
// Governance data source index is used to prevent replay attacks, so a claimVaa cannot be used twice.
if (
governanceDataSourceIndex() >=
claimPayload.governanceDataSourceIndex
) revert PythErrors.OldGovernanceMessage();
setGovernanceDataSourceIndex(claimPayload.governanceDataSourceIndex);
PythInternalStructs.DataSource
memory newGovernanceDS = PythInternalStructs.DataSource(
vm.emitterChainId,
vm.emitterAddress
);
setGovernanceDataSource(newGovernanceDS);
// Setting the last executed governance to the claimVaa sequence to avoid using older sequences.
setLastExecutedGovernanceSequence(vm.sequence);
emit GovernanceDataSourceSet(
oldGovernanceDatSource,
governanceDataSource(),
lastExecutedGovernanceSequence()
);
}
function setDataSources(SetDataSourcesPayload memory payload) internal {
PythInternalStructs.DataSource[]
memory oldDataSources = validDataSources();
for (uint i = 0; i < oldDataSources.length; i += 1) {
_state.isValidDataSource[hashDataSource(oldDataSources[i])] = false;
}
delete _state.validDataSources;
for (uint i = 0; i < payload.dataSources.length; i++) {
_state.validDataSources.push(payload.dataSources[i]);
_state.isValidDataSource[
hashDataSource(payload.dataSources[i])
] = true;
}
emit DataSourcesSet(oldDataSources, validDataSources());
}
function setFee(SetFeePayload memory payload) internal {
uint oldFee = singleUpdateFeeInWei();
setSingleUpdateFeeInWei(payload.newFee);
emit FeeSet(oldFee, singleUpdateFeeInWei());
}
function setValidPeriod(SetValidPeriodPayload memory payload) internal {
uint oldValidPeriod = validTimePeriodSeconds();
setValidTimePeriodSeconds(payload.newValidPeriod);
emit ValidPeriodSet(oldValidPeriod, validTimePeriodSeconds());
}
function setWormholeAddress(
SetWormholeAddressPayload memory payload,
bytes memory encodedVM
) internal {
address oldWormholeAddress = address(wormhole());
setWormhole(payload.newWormholeAddress);
// We want to verify that the new wormhole address is valid, so we make sure that it can
// parse and verify the same governance VAA that is used to set it.
(IWormhole.VM memory vm, bool valid, ) = wormhole().parseAndVerifyVM(
encodedVM
);
if (!valid) revert PythErrors.InvalidGovernanceMessage();
if (!isValidGovernanceDataSource(vm.emitterChainId, vm.emitterAddress))
revert PythErrors.InvalidGovernanceMessage();
if (vm.sequence != lastExecutedGovernanceSequence())
revert PythErrors.InvalidWormholeAddressToSet();
GovernanceInstruction memory gi = parseGovernanceInstruction(
vm.payload
);
if (gi.action != GovernanceAction.SetWormholeAddress)
revert PythErrors.InvalidWormholeAddressToSet();
// Purposefully, we don't check whether the chainId is the same as the current chainId because
// we might want to change the chain id of the wormhole contract.
// The following check is not necessary for security, but is a sanity check that the new wormhole
// contract parses the payload correctly.
SetWormholeAddressPayload
memory newPayload = parseSetWormholeAddressPayload(gi.payload);
if (newPayload.newWormholeAddress != payload.newWormholeAddress)
revert PythErrors.InvalidWormholeAddressToSet();
emit WormholeAddressSet(oldWormholeAddress, address(wormhole()));
}
function setTransactionFee(
SetTransactionFeePayload memory payload
) internal {
uint oldFee = transactionFeeInWei();
setTransactionFeeInWei(payload.newFee);
emit TransactionFeeSet(oldFee, transactionFeeInWei());
}
function withdrawFee(WithdrawFeePayload memory payload) internal {
if (payload.fee > address(this).balance)
revert PythErrors.InsufficientFee();
(bool success, ) = payload.targetAddress.call{value: payload.fee}("");
require(success, "Failed to withdraw fees");
emit FeeWithdrawn(payload.targetAddress, payload.fee);
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
library PythErrors {
// Function arguments are invalid (e.g., the arguments lengths mismatch)
// Signature: 0xa9cb9e0d
error InvalidArgument();
// Update data is coming from an invalid data source.
// Signature: 0xe60dce71
error InvalidUpdateDataSource();
// Update data is invalid (e.g., deserialization error)
// Signature: 0xe69ffece
error InvalidUpdateData();
// Insufficient fee is paid to the method.
// Signature: 0x025dbdd4
error InsufficientFee();
// There is no fresh update, whereas expected fresh updates.
// Signature: 0xde2c57fa
error NoFreshUpdate();
// There is no price feed found within the given range or it does not exists.
// Signature: 0x45805f5d
error PriceFeedNotFoundWithinRange();
// Price feed not found or it is not pushed on-chain yet.
// Signature: 0x14aebe68
error PriceFeedNotFound();
// Requested price is stale.
// Signature: 0x19abf40e
error StalePrice();
// Given message is not a valid Wormhole VAA.
// Signature: 0x2acbe915
error InvalidWormholeVaa();
// Governance message is invalid (e.g., deserialization error).
// Signature: 0x97363b35
error InvalidGovernanceMessage();
// Governance message is not for this contract.
// Signature: 0x63daeb77
error InvalidGovernanceTarget();
// Governance message is coming from an invalid data source.
// Signature: 0x360f2d87
error InvalidGovernanceDataSource();
// Governance message is old.
// Signature: 0x88d1b847
error OldGovernanceMessage();
// The wormhole address to set in SetWormholeAddress governance is invalid.
// Signature: 0x13d3ed82
error InvalidWormholeAddressToSet();
// The twap update data is invalid.
error InvalidTwapUpdateData();
// The twap update data set is invalid.
error InvalidTwapUpdateDataSet();
// The Input Price is negative.
error NegativeInputPrice();
// The Input Exponent is invalid.
error InvalidInputExpo();
// The combined price is greater than int64.max.
error CombinedPriceOverflow();
// The exponent is greater than 77 or less than -77.
error ExponentOverflow();
}// SPDX-License-Identifier: Unlicense /* * @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. */ pragma solidity >=0.8.0 <0.9.0; 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; } }
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "./PythStructs.sol";
import "./IPyth.sol";
import "./PythErrors.sol";
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);
/// @notice This function is deprecated and is only kept for backward compatibility.
function getValidTimePeriod()
public
view
virtual
returns (uint validTimePeriod);
/// @notice This function is deprecated and is only kept for backward compatibility.
function getPrice(
bytes32 id
) external view virtual returns (PythStructs.Price memory price) {
return getPriceNoOlderThan(id, getValidTimePeriod());
}
/// @notice This function is deprecated and is only kept for backward compatibility.
function getEmaPrice(
bytes32 id
) external view virtual 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);
function parsePriceFeedUpdatesUnique(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minPublishTime,
uint64 maxPublishTime
)
external
payable
virtual
override
returns (PythStructs.PriceFeed[] memory priceFeeds);
function parseTwapPriceFeedUpdates(
bytes[] calldata updateData,
bytes32[] calldata priceIds
)
external
payable
virtual
override
returns (PythStructs.TwapPriceFeed[] memory twapPriceFeeds);
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
contract PythStructs {
// A price with a degree of uncertainty, represented as a price +- a confidence interval.
//
// The confidence interval roughly corresponds to the standard error of a normal distribution.
// Both the price and confidence are stored in a fixed-point numeric representation,
// `x * (10^expo)`, where `expo` is the exponent.
//
// Please refer to the documentation at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how
// to how this price safely.
struct Price {
// Price
int64 price;
// Confidence interval around the price
uint64 conf;
// Price exponent
int32 expo;
// Unix timestamp describing when the price was published
uint publishTime;
}
// PriceFeed represents a current aggregate price from pyth publisher feeds.
struct PriceFeed {
// The price ID.
bytes32 id;
// Latest available price
Price price;
// Latest available exponentially-weighted moving average price
Price emaPrice;
}
struct TwapPriceFeed {
// The price ID.
bytes32 id;
// Start time of the TWAP
uint64 startTime;
// End time of the TWAP
uint64 endTime;
// TWAP price
Price twap;
// Down slot ratio represents the ratio of price feed updates that were missed or unavailable
// during the TWAP period, expressed as a fixed-point number between 0 and 1e6 (100%).
// For example:
// - 0 means all price updates were available
// - 500_000 means 50% of updates were missed
// - 1_000_000 means all updates were missed
// This can be used to assess the quality/reliability of the TWAP calculation.
// Applications should define a maximum acceptable ratio (e.g. 100000 for 10%)
// and revert if downSlotsRatio exceeds it.
uint32 downSlotsRatio;
}
// Information used to calculate time-weighted average prices (TWAP)
struct TwapPriceInfo {
// slot 1
int128 cumulativePrice;
uint128 cumulativeConf;
// slot 2
uint64 numDownSlots;
uint64 publishSlot;
uint64 publishTime;
uint64 prevPublishTime;
// slot 3
int32 expo;
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "../libraries/external/UnsafeBytesLib.sol";
import "../libraries/external/UnsafeCalldataBytesLib.sol";
import "@pythnetwork/pyth-sdk-solidity/AbstractPyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
import "@pythnetwork/pyth-sdk-solidity/PythErrors.sol";
import "./PythGetters.sol";
import "./PythSetters.sol";
import "./PythInternalStructs.sol";
import "../libraries/MerkleTree.sol";
abstract contract PythAccumulator is PythGetters, PythSetters, AbstractPyth {
uint32 constant ACCUMULATOR_MAGIC = 0x504e4155; // Stands for PNAU (Pyth Network Accumulator Update)
uint32 constant ACCUMULATOR_WORMHOLE_MAGIC = 0x41555756; // Stands for AUWV (Accumulator Update Wormhole Verficiation)
uint8 constant MINIMUM_ALLOWED_MINOR_VERSION = 0;
uint8 constant MAJOR_VERSION = 1;
enum UpdateType {
WormholeMerkle
}
enum MessageType {
PriceFeed,
TwapPriceFeed
}
// This method is also used by batch attestation but moved here
// as the batch attestation will deprecate soon.
function parseAndVerifyPythVM(
bytes calldata encodedVm
) internal view returns (IWormhole.VM memory vm) {
{
bool valid;
(vm, valid, ) = wormhole().parseAndVerifyVM(encodedVm);
if (!valid) revert PythErrors.InvalidWormholeVaa();
}
if (!isValidDataSource(vm.emitterChainId, vm.emitterAddress))
revert PythErrors.InvalidUpdateDataSource();
}
function extractUpdateTypeFromAccumulatorHeader(
bytes calldata accumulatorUpdate
) internal pure returns (uint offset, UpdateType updateType) {
unchecked {
offset = 0;
{
uint32 magic = UnsafeCalldataBytesLib.toUint32(
accumulatorUpdate,
offset
);
offset += 4;
if (magic != ACCUMULATOR_MAGIC)
revert PythErrors.InvalidUpdateData();
uint8 majorVersion = UnsafeCalldataBytesLib.toUint8(
accumulatorUpdate,
offset
);
offset += 1;
if (majorVersion != MAJOR_VERSION)
revert PythErrors.InvalidUpdateData();
uint8 minorVersion = UnsafeCalldataBytesLib.toUint8(
accumulatorUpdate,
offset
);
offset += 1;
// Minor versions are forward compatible, so we only check
// that the minor version is not less than the minimum allowed
if (minorVersion < MINIMUM_ALLOWED_MINOR_VERSION)
revert PythErrors.InvalidUpdateData();
// This field ensure that we can add headers in the future
// without breaking the contract (future compatibility)
uint8 trailingHeaderSize = UnsafeCalldataBytesLib.toUint8(
accumulatorUpdate,
offset
);
offset += 1;
// We use another offset for the trailing header and in the end add the
// offset by trailingHeaderSize to skip the future headers.
//
// An example would be like this:
// uint trailingHeaderOffset = offset
// uint x = UnsafeBytesLib.ToUint8(accumulatorUpdate, trailingHeaderOffset)
// trailingHeaderOffset += 1
offset += trailingHeaderSize;
}
updateType = UpdateType(
UnsafeCalldataBytesLib.toUint8(accumulatorUpdate, offset)
);
offset += 1;
if (accumulatorUpdate.length < offset)
revert PythErrors.InvalidUpdateData();
}
}
function extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedAndSlotFromAccumulatorUpdate(
bytes calldata accumulatorUpdate,
uint encodedOffset
)
internal
view
returns (
uint offset,
bytes20 digest,
uint8 numUpdates,
bytes calldata encoded,
uint64 slot
)
{
unchecked {
encoded = UnsafeCalldataBytesLib.slice(
accumulatorUpdate,
encodedOffset,
accumulatorUpdate.length - encodedOffset
);
offset = 0;
uint16 whProofSize = UnsafeCalldataBytesLib.toUint16(
encoded,
offset
);
offset += 2;
{
bytes memory encodedPayload;
{
IWormhole.VM memory vm = parseAndVerifyPythVM(
UnsafeCalldataBytesLib.slice(
encoded,
offset,
whProofSize
)
);
offset += whProofSize;
// TODO: Do we need to emit an update for accumulator update? If so what should we emit?
// emit AccumulatorUpdate(vm.chainId, vm.sequence);
encodedPayload = vm.payload;
}
uint payloadOffset = 0;
{
uint32 magic = UnsafeBytesLib.toUint32(
encodedPayload,
payloadOffset
);
payloadOffset += 4;
if (magic != ACCUMULATOR_WORMHOLE_MAGIC)
revert PythErrors.InvalidUpdateData();
UpdateType updateType = UpdateType(
UnsafeBytesLib.toUint8(encodedPayload, payloadOffset)
);
++payloadOffset;
if (updateType != UpdateType.WormholeMerkle)
revert PythErrors.InvalidUpdateData();
slot = UnsafeBytesLib.toUint64(
encodedPayload,
payloadOffset
);
payloadOffset += 8;
// This field is not used
// uint32 ringSize = UnsafeBytesLib.toUint32(encodedPayload, payloadoffset);
payloadOffset += 4;
digest = bytes20(
UnsafeBytesLib.toAddress(encodedPayload, payloadOffset)
);
payloadOffset += 20;
// We don't check equality to enable future compatibility.
if (payloadOffset > encodedPayload.length)
revert PythErrors.InvalidUpdateData();
}
}
numUpdates = UnsafeCalldataBytesLib.toUint8(encoded, offset);
offset += 1;
}
}
function parseWormholeMerkleHeaderNumUpdates(
bytes calldata wormholeMerkleUpdate,
uint offset
) internal pure returns (uint8 numUpdates) {
uint16 whProofSize = UnsafeCalldataBytesLib.toUint16(
wormholeMerkleUpdate,
offset
);
offset += 2;
offset += whProofSize;
numUpdates = UnsafeCalldataBytesLib.toUint8(
wormholeMerkleUpdate,
offset
);
}
function extractPriceInfoFromMerkleProof(
bytes20 digest,
bytes calldata encoded,
uint offset
)
internal
pure
returns (
uint endOffset,
PythInternalStructs.PriceInfo memory priceInfo,
bytes32 priceId,
uint64 prevPublishTime
)
{
bytes calldata encodedMessage;
MessageType messageType;
(
encodedMessage,
messageType,
endOffset
) = extractAndValidateEncodedMessage(encoded, offset, digest);
if (messageType == MessageType.PriceFeed) {
(priceInfo, priceId, prevPublishTime) = parsePriceFeedMessage(
encodedMessage,
1
);
} else revert PythErrors.InvalidUpdateData();
return (endOffset, priceInfo, priceId, prevPublishTime);
}
function extractTwapPriceInfoFromMerkleProof(
bytes20 digest,
bytes calldata encoded,
uint offset
)
internal
pure
returns (
uint endOffset,
PythStructs.TwapPriceInfo memory twapPriceInfo,
bytes32 priceId
)
{
bytes calldata encodedMessage;
MessageType messageType;
(
encodedMessage,
messageType,
endOffset
) = extractAndValidateEncodedMessage(encoded, offset, digest);
if (messageType == MessageType.TwapPriceFeed) {
(twapPriceInfo, priceId) = parseTwapPriceFeedMessage(
encodedMessage,
1
);
} else revert PythErrors.InvalidUpdateData();
return (endOffset, twapPriceInfo, priceId);
}
function extractAndValidateEncodedMessage(
bytes calldata encoded,
uint offset,
bytes20 digest
)
private
pure
returns (
bytes calldata encodedMessage,
MessageType messageType,
uint endOffset
)
{
uint16 messageSize = UnsafeCalldataBytesLib.toUint16(encoded, offset);
offset += 2;
encodedMessage = UnsafeCalldataBytesLib.slice(
encoded,
offset,
messageSize
);
offset += messageSize;
bool valid;
(valid, endOffset) = MerkleTree.isProofValid(
encoded,
offset,
digest,
encodedMessage
);
if (!valid) {
revert PythErrors.InvalidUpdateData();
}
messageType = MessageType(
UnsafeCalldataBytesLib.toUint8(encodedMessage, 0)
);
if (
messageType != MessageType.PriceFeed &&
messageType != MessageType.TwapPriceFeed
) {
revert PythErrors.InvalidUpdateData();
}
return (encodedMessage, messageType, endOffset);
}
function parsePriceFeedMessage(
bytes calldata encodedPriceFeed,
uint offset
)
private
pure
returns (
PythInternalStructs.PriceInfo memory priceInfo,
bytes32 priceId,
uint64 prevPublishTime
)
{
unchecked {
priceId = UnsafeCalldataBytesLib.toBytes32(
encodedPriceFeed,
offset
);
offset += 32;
priceInfo.price = int64(
UnsafeCalldataBytesLib.toUint64(encodedPriceFeed, offset)
);
offset += 8;
priceInfo.conf = UnsafeCalldataBytesLib.toUint64(
encodedPriceFeed,
offset
);
offset += 8;
priceInfo.expo = int32(
UnsafeCalldataBytesLib.toUint32(encodedPriceFeed, offset)
);
offset += 4;
// Publish time is i64 in some environments due to the standard in that
// environment. This would not cause any problem because since the signed
// integer is represented in two's complement, the value would be the same
// in both cases (for a million year at least)
priceInfo.publishTime = UnsafeCalldataBytesLib.toUint64(
encodedPriceFeed,
offset
);
offset += 8;
// We do not store this field because it is not used on the latest feed queries.
prevPublishTime = UnsafeBytesLib.toUint64(encodedPriceFeed, offset);
offset += 8;
priceInfo.emaPrice = int64(
UnsafeCalldataBytesLib.toUint64(encodedPriceFeed, offset)
);
offset += 8;
priceInfo.emaConf = UnsafeCalldataBytesLib.toUint64(
encodedPriceFeed,
offset
);
offset += 8;
if (offset > encodedPriceFeed.length)
revert PythErrors.InvalidUpdateData();
}
}
function parseTwapPriceFeedMessage(
bytes calldata encodedTwapPriceFeed,
uint offset
)
private
pure
returns (
PythStructs.TwapPriceInfo memory twapPriceInfo,
bytes32 priceId
)
{
unchecked {
priceId = UnsafeCalldataBytesLib.toBytes32(
encodedTwapPriceFeed,
offset
);
offset += 32;
twapPriceInfo.cumulativePrice = int128(
UnsafeCalldataBytesLib.toUint128(encodedTwapPriceFeed, offset)
);
offset += 16;
twapPriceInfo.cumulativeConf = UnsafeCalldataBytesLib.toUint128(
encodedTwapPriceFeed,
offset
);
offset += 16;
twapPriceInfo.numDownSlots = UnsafeCalldataBytesLib.toUint64(
encodedTwapPriceFeed,
offset
);
offset += 8;
twapPriceInfo.publishSlot = UnsafeCalldataBytesLib.toUint64(
encodedTwapPriceFeed,
offset
);
offset += 8;
twapPriceInfo.publishTime = UnsafeCalldataBytesLib.toUint64(
encodedTwapPriceFeed,
offset
);
offset += 8;
twapPriceInfo.prevPublishTime = UnsafeCalldataBytesLib.toUint64(
encodedTwapPriceFeed,
offset
);
offset += 8;
twapPriceInfo.expo = int32(
UnsafeCalldataBytesLib.toUint32(encodedTwapPriceFeed, offset)
);
offset += 4;
if (offset > encodedTwapPriceFeed.length)
revert PythErrors.InvalidUpdateData();
}
}
function updatePriceInfosFromAccumulatorUpdate(
bytes calldata accumulatorUpdate
) internal returns (uint8 numUpdates) {
(
uint encodedOffset,
UpdateType updateType
) = extractUpdateTypeFromAccumulatorHeader(accumulatorUpdate);
if (updateType != UpdateType.WormholeMerkle) {
revert PythErrors.InvalidUpdateData();
}
uint offset;
bytes20 digest;
bytes calldata encoded;
uint64 slot;
(
offset,
digest,
numUpdates,
encoded,
slot
) = extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedAndSlotFromAccumulatorUpdate(
accumulatorUpdate,
encodedOffset
);
unchecked {
for (uint i = 0; i < numUpdates; i++) {
PythInternalStructs.PriceInfo memory priceInfo;
bytes32 priceId;
uint64 prevPublishTime;
(
offset,
priceInfo,
priceId,
prevPublishTime
) = extractPriceInfoFromMerkleProof(digest, encoded, offset);
updateLatestPriceIfNecessary(priceId, priceInfo);
}
}
if (offset != encoded.length) revert PythErrors.InvalidUpdateData();
}
}// contracts/Setters.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "./PythState.sol";
import "@pythnetwork/pyth-sdk-solidity/IPythEvents.sol";
contract PythSetters is PythState, IPythEvents {
function setWormhole(address wh) internal {
_state.wormhole = payable(wh);
}
function updateLatestPriceIfNecessary(
bytes32 priceId,
PythInternalStructs.PriceInfo memory info
) internal {
uint64 latestPublishTime = _state.latestPriceInfo[priceId].publishTime;
if (info.publishTime > latestPublishTime) {
_state.latestPriceInfo[priceId] = info;
emit PriceFeedUpdate(
priceId,
info.publishTime,
info.price,
info.conf
);
}
}
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;
}
function setTransactionFeeInWei(uint fee) internal {
_state.transactionFeeInWei = fee;
}
}// SPDX-License-Identifier: Unlicense /* * @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. */ pragma solidity >=0.8.0 <0.9.0; 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/Messages.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "../Structs.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);
}// contracts/State.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "./PythInternalStructs.sol";
import "./PythDeprecatedStructs.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;
// Fee charged per transaction, in addition to per-update fees
uint transactionFeeInWei;
}
}
contract PythState {
PythStorage.State _state;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeaconUpgradeable.sol";
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/StorageSlotUpgradeable.sol";
import "../utils/Initializable.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;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.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;
}// contracts/GovernanceStructs.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "../libraries/external/BytesLib.sol";
import "./PythInternalStructs.sol";
import "@pythnetwork/pyth-sdk-solidity/PythErrors.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
EvmExecutor, // 2
// The stacks target chain contract has custom governance instructions and needs its own module.
StacksTarget // 3
}
GovernanceModule constant MODULE = GovernanceModule.Target;
enum GovernanceAction {
UpgradeContract, // 0
AuthorizeGovernanceDataSourceTransfer, // 1
SetDataSources, // 2
SetFee, // 3
SetValidPeriod, // 4
RequestGovernanceDataSourceTransfer, // 5
SetWormholeAddress, // 6
SetFeeInToken, // 7 - No-op for EVM chains
SetTransactionFee, // 8
WithdrawFee // 9
}
struct GovernanceInstruction {
GovernanceModule module;
GovernanceAction action;
uint16 targetChainId;
bytes payload;
}
struct UpgradeContractPayload {
address newImplementation;
}
struct AuthorizeGovernanceDataSourceTransferPayload {
// Transfer governance control over this contract to another data source.
// The claimVaa field is a VAA created by the new data source; using a VAA prevents mistakes
// in the handoff by ensuring that the new data source can send VAAs (i.e., is not an invalid address).
bytes claimVaa;
}
struct RequestGovernanceDataSourceTransferPayload {
// Governance data source index is used to prevent replay attacks
// So a claimVaa cannot be used twice.
uint32 governanceDataSourceIndex;
}
struct SetDataSourcesPayload {
PythInternalStructs.DataSource[] dataSources;
}
struct SetFeePayload {
uint newFee;
}
struct SetValidPeriodPayload {
uint newValidPeriod;
}
struct SetWormholeAddressPayload {
address newWormholeAddress;
}
struct SetTransactionFeePayload {
uint newFee;
}
struct WithdrawFeePayload {
address targetAddress;
// Fee in wei, matching the native uint256 type used for address.balance in EVM
uint256 fee;
}
/// @dev Parse a GovernanceInstruction
function parseGovernanceInstruction(
bytes memory encodedInstruction
) public pure returns (GovernanceInstruction memory gi) {
uint index = 0;
uint32 magic = encodedInstruction.toUint32(index);
if (magic != MAGIC) revert PythErrors.InvalidGovernanceMessage();
index += 4;
uint8 modNumber = encodedInstruction.toUint8(index);
gi.module = GovernanceModule(modNumber);
index += 1;
if (gi.module != MODULE) revert PythErrors.InvalidGovernanceTarget();
uint8 actionNumber = encodedInstruction.toUint8(index);
gi.action = GovernanceAction(actionNumber);
index += 1;
gi.targetChainId = encodedInstruction.toUint16(index);
index += 2;
// As solidity performs math operations in a checked mode
// if the length of the encoded instruction be smaller than index
// it will revert. So we don't need any extra check.
gi.payload = encodedInstruction.slice(
index,
encodedInstruction.length - index
);
}
/// @dev Parse a UpgradeContractPayload (action 1) with minimal validation
function parseUpgradeContractPayload(
bytes memory encodedPayload
) public pure returns (UpgradeContractPayload memory uc) {
uint index = 0;
uc.newImplementation = address(encodedPayload.toAddress(index));
index += 20;
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a AuthorizeGovernanceDataSourceTransferPayload (action 2) with minimal validation
function parseAuthorizeGovernanceDataSourceTransferPayload(
bytes memory encodedPayload
)
public
pure
returns (AuthorizeGovernanceDataSourceTransferPayload memory sgds)
{
sgds.claimVaa = encodedPayload;
}
/// @dev Parse a AuthorizeGovernanceDataSourceTransferPayload (action 2) with minimal validation
function parseRequestGovernanceDataSourceTransferPayload(
bytes memory encodedPayload
)
public
pure
returns (RequestGovernanceDataSourceTransferPayload memory sgdsClaim)
{
uint index = 0;
sgdsClaim.governanceDataSourceIndex = encodedPayload.toUint32(index);
index += 4;
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a SetDataSourcesPayload (action 3) with minimal validation
function parseSetDataSourcesPayload(
bytes memory encodedPayload
) public pure returns (SetDataSourcesPayload memory sds) {
uint index = 0;
uint8 dataSourcesLength = encodedPayload.toUint8(index);
index += 1;
sds.dataSources = new PythInternalStructs.DataSource[](
dataSourcesLength
);
for (uint i = 0; i < dataSourcesLength; i++) {
sds.dataSources[i].chainId = encodedPayload.toUint16(index);
index += 2;
sds.dataSources[i].emitterAddress = encodedPayload.toBytes32(index);
index += 32;
}
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a SetFeePayload (action 4) with minimal validation
function parseSetFeePayload(
bytes memory encodedPayload
) public pure returns (SetFeePayload memory sf) {
uint index = 0;
uint64 val = encodedPayload.toUint64(index);
index += 8;
uint64 expo = encodedPayload.toUint64(index);
index += 8;
sf.newFee = uint256(val) * uint256(10) ** uint256(expo);
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a SetValidPeriodPayload (action 5) with minimal validation
function parseSetValidPeriodPayload(
bytes memory encodedPayload
) public pure returns (SetValidPeriodPayload memory svp) {
uint index = 0;
svp.newValidPeriod = uint256(encodedPayload.toUint64(index));
index += 8;
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a UpdateWormholeAddressPayload (action 6) with minimal validation
function parseSetWormholeAddressPayload(
bytes memory encodedPayload
) public pure returns (SetWormholeAddressPayload memory sw) {
uint index = 0;
sw.newWormholeAddress = address(encodedPayload.toAddress(index));
index += 20;
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a SetTransactionFeePayload (action 8) with minimal validation
function parseSetTransactionFeePayload(
bytes memory encodedPayload
) public pure returns (SetTransactionFeePayload memory stf) {
uint index = 0;
uint64 val = encodedPayload.toUint64(index);
index += 8;
uint64 expo = encodedPayload.toUint64(index);
index += 8;
stf.newFee = uint256(val) * uint256(10) ** uint256(expo);
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a WithdrawFeePayload (action 9) with minimal validation
function parseWithdrawFeePayload(
bytes memory encodedPayload
) public pure returns (WithdrawFeePayload memory wf) {
uint index = 0;
wf.targetAddress = address(encodedPayload.toAddress(index));
index += 20;
uint64 val = encodedPayload.toUint64(index);
index += 8;
uint64 expo = encodedPayload.toUint64(index);
index += 8;
wf.fee = uint256(val) * uint256(10) ** uint256(expo);
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.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);
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "./PythStructs.sol";
import "./IPythEvents.sol";
/// @title Consume prices from the Pyth Network (https://pyth.network/).
/// @dev Please refer to the guidance at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how to consume prices safely.
/// @author Pyth Data Association
interface IPyth is IPythEvents {
/// @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 `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 Returns the required fee to update a TWAP price.
/// @param updateData Array of price update data.
/// @return feeAmount The required fee in Wei.
function getTwapUpdateFee(
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 will 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);
/// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published
/// within `minPublishTime` and `maxPublishTime,` but choose to store price updates if `storeUpdatesIfFresh`.
///
/// 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 may store the price updates on-chain, if they
/// are more recent than the current stored prices.
///
/// 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.
///
/// This method will eventually allow the caller to determine whether parsed price feeds should update
/// the stored values as well.
///
/// @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 minAllowedPublishTime minimum acceptable publishTime for the given `priceIds`.
/// @param maxAllowedPublishTime maximum acceptable publishTime for the given `priceIds`.
/// @param storeUpdatesIfFresh flag for the parse function to
/// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).
function parsePriceFeedUpdatesWithConfig(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minAllowedPublishTime,
uint64 maxAllowedPublishTime,
bool checkUniqueness,
bool checkUpdateDataIsMinimal,
bool storeUpdatesIfFresh
)
external
payable
returns (
PythStructs.PriceFeed[] memory priceFeeds,
uint64[] memory slots
);
/// @notice Parse time-weighted average price (TWAP) from two consecutive price updates for the given `priceIds`.
///
/// This method calculates TWAP between two data points by processing the difference in cumulative price values
/// divided by the time period. It requires exactly two updates that contain valid price information
/// for all the requested price IDs.
///
/// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
/// `getUpdateFee` with the updateData array.
///
/// @dev Reverts if:
/// - The transferred fee is not sufficient
/// - The updateData is invalid or malformed
/// - The updateData array does not contain exactly 2 updates
/// - There is no update for any of the given `priceIds`
/// - The time ordering between data points is invalid (start time must be before end time)
/// @param updateData Array containing exactly two price updates (start and end points for TWAP calculation)
/// @param priceIds Array of price ids to calculate TWAP for
/// @return twapPriceFeeds Array of TWAP price feeds corresponding to the given `priceIds` (with the same order)
function parseTwapPriceFeedUpdates(
bytes[] calldata updateData,
bytes32[] calldata priceIds
)
external
payable
returns (PythStructs.TwapPriceFeed[] memory twapPriceFeeds);
/// @notice Similar to `parsePriceFeedUpdates` but ensures the updates returned are
/// the first updates published in minPublishTime. That is, if there are multiple updates for a given timestamp,
/// this method will return the first update. This method may store the price updates on-chain, if they
/// are more recent than the current stored prices.
///
///
/// @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 and uniqueness condition.
/// @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 parsePriceFeedUpdatesUnique(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minPublishTime,
uint64 maxPublishTime
) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);
}// SPDX-License-Identifier: Unlicense /* * @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. */ pragma solidity >=0.8.0 <0.9.0; library UnsafeCalldataBytesLib { function slice( bytes calldata _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes calldata) { return _bytes[_start:_start + _length]; } function sliceFrom( bytes calldata _bytes, uint256 _start ) internal pure returns (bytes calldata) { return _bytes[_start:_bytes.length]; } function toAddress( bytes calldata _bytes, uint256 _start ) internal pure returns (address) { address tempAddress; assembly { tempAddress := shr(96, calldataload(add(_bytes.offset, _start))) } return tempAddress; } function toUint8( bytes calldata _bytes, uint256 _start ) internal pure returns (uint8) { uint8 tempUint; assembly { tempUint := shr(248, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint16( bytes calldata _bytes, uint256 _start ) internal pure returns (uint16) { uint16 tempUint; assembly { tempUint := shr(240, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint32( bytes calldata _bytes, uint256 _start ) internal pure returns (uint32) { uint32 tempUint; assembly { tempUint := shr(224, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint64( bytes calldata _bytes, uint256 _start ) internal pure returns (uint64) { uint64 tempUint; assembly { tempUint := shr(192, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint96( bytes calldata _bytes, uint256 _start ) internal pure returns (uint96) { uint96 tempUint; assembly { tempUint := shr(160, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint128( bytes calldata _bytes, uint256 _start ) internal pure returns (uint128) { uint128 tempUint; assembly { tempUint := shr(128, calldataload(add(_bytes.offset, _start))) } return tempUint; } function toUint256( bytes calldata _bytes, uint256 _start ) internal pure returns (uint256) { uint256 tempUint; assembly { tempUint := calldataload(add(_bytes.offset, _start)) } return tempUint; } function toBytes32( bytes calldata _bytes, uint256 _start ) internal pure returns (bytes32) { bytes32 tempBytes32; assembly { tempBytes32 := calldataload(add(_bytes.offset, _start)) } return tempBytes32; } }
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "./external/UnsafeCalldataBytesLib.sol";
/**
* @dev This library provides methods to construct and verify Merkle Tree proofs efficiently.
*
*/
library MerkleTree {
uint8 constant MERKLE_LEAF_PREFIX = 0;
uint8 constant MERKLE_NODE_PREFIX = 1;
uint8 constant MERKLE_EMPTY_LEAF_PREFIX = 2;
function hash(bytes memory input) internal pure returns (bytes20) {
return bytes20(keccak256(input));
}
function emptyLeafHash() internal pure returns (bytes20) {
return hash(abi.encodePacked(MERKLE_EMPTY_LEAF_PREFIX));
}
function leafHash(bytes memory data) internal pure returns (bytes20) {
return hash(abi.encodePacked(MERKLE_LEAF_PREFIX, data));
}
function nodeHash(
bytes20 childA,
bytes20 childB
) internal pure returns (bytes20) {
if (childA > childB) {
(childA, childB) = (childB, childA);
}
return hash(abi.encodePacked(MERKLE_NODE_PREFIX, childA, childB));
}
/// @notice Verify Merkle Tree proof for given leaf data based on data on memory.
/// @dev To optimize gas usage, this method doesn't take the proof as a bytes array
/// but rather takes the encoded proof and the offset of the proof in the
/// encoded proof array possibly containing multiple proofs. Also, the method
/// does not perform any check on the boundry of the `encodedProof` and the
/// `proofOffset` parameters. It is the caller's responsibility to ensure
/// that the `encodedProof` is long enough to contain the proof and the
/// `proofOffset` is not out of bound.
function isProofValid(
bytes calldata encodedProof,
uint proofOffset,
bytes20 root,
bytes calldata leafData
) internal pure returns (bool valid, uint endOffset) {
unchecked {
bytes20 currentDigest = MerkleTree.leafHash(leafData);
uint8 proofSize = UnsafeCalldataBytesLib.toUint8(
encodedProof,
proofOffset
);
proofOffset += 1;
for (uint i = 0; i < proofSize; i++) {
bytes20 siblingDigest = bytes20(
UnsafeCalldataBytesLib.toAddress(encodedProof, proofOffset)
);
proofOffset += 20;
currentDigest = MerkleTree.nodeHash(
currentDigest,
siblingDigest
);
}
valid = currentDigest == root;
endOffset = proofOffset;
}
}
/// @notice Construct Merkle Tree proofs for given list of messages.
/// @dev This function is only used for testing purposes and is not efficient
/// for production use-cases.
///
/// This method creates a merkle tree with leaf size of (2^depth) with the
/// messages as leafs (in the same given order) and returns the root digest
/// and the proofs for each message. If the number of messages is not a power
/// of 2, the tree is padded with empty messages.
function constructProofs(
bytes[] memory messages,
uint8 depth
) internal pure returns (bytes20 root, bytes[] memory proofs) {
require((1 << depth) >= messages.length, "depth too small");
bytes20[] memory tree = new bytes20[]((1 << (depth + 1)));
// The tree is structured as follows:
// 1
// 2 3
// 4 5 6 7
// ...
// In this structure the parent of node x is x//2 and the children
// of node x are x*2 and x*2 + 1. Also, the sibling of the node x
// is x^1. The root is at index 1 and index 0 is not used.
// Filling the leaf hashes
bytes20 cachedEmptyLeafHash = emptyLeafHash();
for (uint i = 0; i < (1 << depth); i++) {
if (i < messages.length) {
tree[(1 << depth) + i] = leafHash(messages[i]);
} else {
tree[(1 << depth) + i] = cachedEmptyLeafHash;
}
}
// Filling the node hashes from bottom to top
for (uint k = depth; k > 0; k--) {
uint level = k - 1;
uint levelNumNodes = (1 << level);
for (uint i = 0; i < levelNumNodes; i++) {
uint id = (1 << level) + i;
tree[id] = nodeHash(tree[id * 2], tree[id * 2 + 1]);
}
}
root = tree[1];
proofs = new bytes[](messages.length);
for (uint i = 0; i < messages.length; i++) {
// depth is the number of sibling nodes in the path from the leaf to the root
proofs[i] = abi.encodePacked(depth);
uint idx = (1 << depth) + i;
// This loop iterates through the leaf and its parents
// and keeps adding the sibling of the current node to the proof.
while (idx > 1) {
proofs[i] = abi.encodePacked(
proofs[i],
tree[idx ^ 1] // Sibling of this node
);
// Jump to parent
idx /= 2;
}
}
}
}// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
/// @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 the TWAP price feed with `id` has received a fresh update.
/// @param id The Pyth Price Feed ID.
/// @param startTime Start time of the TWAP.
/// @param endTime End time of the TWAP.
/// @param twapPrice Price of the TWAP.
/// @param twapConf Confidence interval of the TWAP.
/// @param downSlotsRatio Down slot ratio of the TWAP.
event TwapPriceFeedUpdate(
bytes32 indexed id,
uint64 startTime,
uint64 endTime,
int64 twapPrice,
uint64 twapConf,
uint32 downSlotsRatio
);
}// contracts/Structs.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
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/PythDeprecatedStructs.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
// 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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
*/
library StorageSlotUpgradeable {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
}{
"remappings": [
"@ensdomains/=node_modules/@ensdomains/",
"@openzeppelin/=node_modules/@openzeppelin/",
"@pythnetwork/=node_modules/@pythnetwork/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"@nomad-xyz/=node_modules/@nomad-xyz/",
"hardhat/=node_modules/hardhat/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InsufficientFee","type":"error"},{"inputs":[],"name":"InvalidArgument","type":"error"},{"inputs":[],"name":"InvalidGovernanceDataSource","type":"error"},{"inputs":[],"name":"InvalidGovernanceMessage","type":"error"},{"inputs":[],"name":"InvalidGovernanceTarget","type":"error"},{"inputs":[],"name":"InvalidTwapUpdateData","type":"error"},{"inputs":[],"name":"InvalidTwapUpdateDataSet","type":"error"},{"inputs":[],"name":"InvalidUpdateData","type":"error"},{"inputs":[],"name":"InvalidUpdateDataSource","type":"error"},{"inputs":[],"name":"InvalidWormholeAddressToSet","type":"error"},{"inputs":[],"name":"InvalidWormholeVaa","type":"error"},{"inputs":[],"name":"NoFreshUpdate","type":"error"},{"inputs":[],"name":"OldGovernanceMessage","type":"error"},{"inputs":[],"name":"PriceFeedNotFound","type":"error"},{"inputs":[],"name":"PriceFeedNotFoundWithinRange","type":"error"},{"inputs":[],"name":"StalePrice","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"newImplementation","type":"address"}],"name":"ContractUpgraded","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource[]","name":"oldDataSources","type":"tuple[]"},{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource[]","name":"newDataSources","type":"tuple[]"}],"name":"DataSourcesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"FeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"targetAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"FeeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource","name":"oldDataSource","type":"tuple"},{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource","name":"newDataSource","type":"tuple"},{"indexed":false,"internalType":"uint64","name":"initialSequence","type":"uint64"}],"name":"GovernanceDataSourceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"publishTime","type":"uint64"},{"indexed":false,"internalType":"int64","name":"price","type":"int64"},{"indexed":false,"internalType":"uint64","name":"conf","type":"uint64"}],"name":"PriceFeedUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"TransactionFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"startTime","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"endTime","type":"uint64"},{"indexed":false,"internalType":"int64","name":"twapPrice","type":"int64"},{"indexed":false,"internalType":"uint64","name":"twapConf","type":"uint64"},{"indexed":false,"internalType":"uint32","name":"downSlotsRatio","type":"uint32"}],"name":"TwapPriceFeedUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldValidPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValidPeriod","type":"uint256"}],"name":"ValidPeriodSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldWormholeAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newWormholeAddress","type":"address"}],"name":"WormholeAddressSet","type":"event"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVM","type":"bytes"}],"name":"executeGovernanceInstruction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getEmaPrice","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"uint256","name":"age","type":"uint256"}],"name":"getEmaPriceNoOlderThan","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getEmaPriceUnsafe","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getPrice","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"uint256","name":"age","type":"uint256"}],"name":"getPriceNoOlderThan","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getPriceUnsafe","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"}],"name":"getTwapUpdateFee","outputs":[{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"}],"name":"getUpdateFee","outputs":[{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"updateDataSize","type":"uint256"}],"name":"getUpdateFee","outputs":[{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getValidTimePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceDataSource","outputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceDataSourceIndex","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource","name":"ds","type":"tuple"}],"name":"hashDataSource","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"wormhole","type":"address"},{"internalType":"uint16[]","name":"dataSourceEmitterChainIds","type":"uint16[]"},{"internalType":"bytes32[]","name":"dataSourceEmitterAddresses","type":"bytes32[]"},{"internalType":"uint16","name":"governanceEmitterChainId","type":"uint16"},{"internalType":"bytes32","name":"governanceEmitterAddress","type":"bytes32"},{"internalType":"uint64","name":"governanceInitialSequence","type":"uint64"},{"internalType":"uint256","name":"validTimePeriodSeconds","type":"uint256"},{"internalType":"uint256","name":"singleUpdateFeeInWei","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"dataSourceChainId","type":"uint16"},{"internalType":"bytes32","name":"dataSourceEmitterAddress","type":"bytes32"}],"name":"isValidDataSource","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"governanceChainId","type":"uint16"},{"internalType":"bytes32","name":"governanceEmitterAddress","type":"bytes32"}],"name":"isValidGovernanceDataSource","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastExecutedGovernanceSequence","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"priceId","type":"bytes32"}],"name":"latestPriceInfoPublishTime","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseAuthorizeGovernanceDataSourceTransferPayload","outputs":[{"components":[{"internalType":"bytes","name":"claimVaa","type":"bytes"}],"internalType":"struct PythGovernanceInstructions.AuthorizeGovernanceDataSourceTransferPayload","name":"sgds","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedInstruction","type":"bytes"}],"name":"parseGovernanceInstruction","outputs":[{"components":[{"internalType":"enum PythGovernanceInstructions.GovernanceModule","name":"module","type":"uint8"},{"internalType":"enum PythGovernanceInstructions.GovernanceAction","name":"action","type":"uint8"},{"internalType":"uint16","name":"targetChainId","type":"uint16"},{"internalType":"bytes","name":"payload","type":"bytes"}],"internalType":"struct PythGovernanceInstructions.GovernanceInstruction","name":"gi","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"},{"internalType":"bytes32[]","name":"priceIds","type":"bytes32[]"},{"internalType":"uint64","name":"minPublishTime","type":"uint64"},{"internalType":"uint64","name":"maxPublishTime","type":"uint64"}],"name":"parsePriceFeedUpdates","outputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"emaPrice","type":"tuple"}],"internalType":"struct PythStructs.PriceFeed[]","name":"priceFeeds","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"},{"internalType":"bytes32[]","name":"priceIds","type":"bytes32[]"},{"internalType":"uint64","name":"minPublishTime","type":"uint64"},{"internalType":"uint64","name":"maxPublishTime","type":"uint64"}],"name":"parsePriceFeedUpdatesUnique","outputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"emaPrice","type":"tuple"}],"internalType":"struct PythStructs.PriceFeed[]","name":"priceFeeds","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"},{"internalType":"bytes32[]","name":"priceIds","type":"bytes32[]"},{"internalType":"uint64","name":"minAllowedPublishTime","type":"uint64"},{"internalType":"uint64","name":"maxAllowedPublishTime","type":"uint64"},{"internalType":"bool","name":"checkUniqueness","type":"bool"},{"internalType":"bool","name":"checkUpdateDataIsMinimal","type":"bool"},{"internalType":"bool","name":"storeUpdatesIfFresh","type":"bool"}],"name":"parsePriceFeedUpdatesWithConfig","outputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"emaPrice","type":"tuple"}],"internalType":"struct PythStructs.PriceFeed[]","name":"priceFeeds","type":"tuple[]"},{"internalType":"uint64[]","name":"slots","type":"uint64[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseRequestGovernanceDataSourceTransferPayload","outputs":[{"components":[{"internalType":"uint32","name":"governanceDataSourceIndex","type":"uint32"}],"internalType":"struct PythGovernanceInstructions.RequestGovernanceDataSourceTransferPayload","name":"sgdsClaim","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetDataSourcesPayload","outputs":[{"components":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource[]","name":"dataSources","type":"tuple[]"}],"internalType":"struct PythGovernanceInstructions.SetDataSourcesPayload","name":"sds","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetFeePayload","outputs":[{"components":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"internalType":"struct PythGovernanceInstructions.SetFeePayload","name":"sf","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetTransactionFeePayload","outputs":[{"components":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"internalType":"struct PythGovernanceInstructions.SetTransactionFeePayload","name":"stf","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetValidPeriodPayload","outputs":[{"components":[{"internalType":"uint256","name":"newValidPeriod","type":"uint256"}],"internalType":"struct PythGovernanceInstructions.SetValidPeriodPayload","name":"svp","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetWormholeAddressPayload","outputs":[{"components":[{"internalType":"address","name":"newWormholeAddress","type":"address"}],"internalType":"struct PythGovernanceInstructions.SetWormholeAddressPayload","name":"sw","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"},{"internalType":"bytes32[]","name":"priceIds","type":"bytes32[]"}],"name":"parseTwapPriceFeedUpdates","outputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"uint64","name":"startTime","type":"uint64"},{"internalType":"uint64","name":"endTime","type":"uint64"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"twap","type":"tuple"},{"internalType":"uint32","name":"downSlotsRatio","type":"uint32"}],"internalType":"struct PythStructs.TwapPriceFeed[]","name":"twapPriceFeeds","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseUpgradeContractPayload","outputs":[{"components":[{"internalType":"address","name":"newImplementation","type":"address"}],"internalType":"struct PythGovernanceInstructions.UpgradeContractPayload","name":"uc","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseWithdrawFeePayload","outputs":[{"components":[{"internalType":"address","name":"targetAddress","type":"address"},{"internalType":"uint256","name":"fee","type":"uint256"}],"internalType":"struct PythGovernanceInstructions.WithdrawFeePayload","name":"wf","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"priceFeedExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pythUpgradableMagic","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"queryPriceFeed","outputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"emaPrice","type":"tuple"}],"internalType":"struct PythStructs.PriceFeed","name":"priceFeed","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"singleUpdateFeeInWei","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transactionFeeInWei","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"}],"name":"updatePriceFeeds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"},{"internalType":"bytes32[]","name":"priceIds","type":"bytes32[]"},{"internalType":"uint64[]","name":"publishTimes","type":"uint64[]"}],"name":"updatePriceFeedsIfNecessary","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"validDataSources","outputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"validTimePeriodSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"wormhole","outputs":[{"internalType":"contract IWormhole","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a06040523060805234801561001457600080fd5b50600054610100900460ff16158080156100355750600054600160ff909116105b8061004f5750303b15801561004f575060005460ff166001145b6100b65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff1916600117905580156100d9576000805461ff0019166101001790555b801561011f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50608051615fb261015760003960008181610bc501528181610c05015281816110bf015281816110ff015261117b0152615fb26000f3fe6080604052600436106102e45760003560e01c80638881016f11610190578063b6ed701e116100dc578063d82d58a511610095578063e3795cc11161006f578063e3795cc11461099b578063eb942158146109b2578063ef9e5e28146109d2578063f2fde38b146109e557600080fd5b8063d82d58a51461092d578063e17efd4814610966578063e18910a31461098657600080fd5b8063b6ed701e14610898578063b9256d28146108b8578063c091ae7b146104b0578063caaf43f1146108cb578063cb718a9b146108f8578063d47eed451461090d57600080fd5b80639a8a059211610149578063aac4129211610123578063aac41292146106f8578063accca7f91461082d578063b5dcc91114610840578063b5ec02611461086057600080fd5b80639a8a0592146107c3578063a38d81c6146107eb578063a4ae35e01461080d57600080fd5b80638881016f146106f857806389a5bb4d146107305780638da5cb5b146107505780639474f45b1461076e57806396834ad31461078e578063978a800d146107ae57600080fd5b806352d1902d1161024f5780636b7f53ca11610208578063715018a6116101e2578063715018a61461064f5780637b72bcae1461066457806384acd1bb1461069957806387c5bd1b146106cb57600080fd5b80636b7f53ca146105d65780636c72f51b14610603578063711a2e281461062f57600080fd5b806352d1902d146104e357806354fd4d50146104f8578063586d3cf81461053457806358c67635146105525780635f674e35146105725780636054312d1461059257600080fd5b8063437209a7116102a1578063437209a7146103f35780634716e9c51461042357806348b6404d146104435780634c469d8c146104625780634d7a734e146104b05780634f1ef286146104d057600080fd5b8063146faf77146102e957806314dd317f1461030b57806331d98b3f1461033f5780633659cfe61461036c5780633a229d181461038c578063426234e4146103ad575b600080fd5b3480156102f557600080fd5b50610309610304366004614d9f565b610a05565b005b34801561031757600080fd5b5061032b610326366004614f75565b610b47565b604051905181526020015b60405180910390f35b34801561034b57600080fd5b5061035f61035a366004614fa9565b610ba1565b6040516103369190614ff7565b34801561037857600080fd5b50610309610387366004615005565b610bbb565b61039f61039a36600461502e565b610ca0565b60405161033692919061516f565b3480156103b957600080fd5b506040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015260405161033691906151d2565b3480156103ff57600080fd5b5061041361040e3660046151ed565b610fa9565b6040519015158152602001610336565b610436610431366004615219565b610ffc565b60405161033691906152b1565b34801561044f57600080fd5b5060ce545b604051908152602001610336565b34801561046e57600080fd5b5061049861047d366004614fa9565b600090815260d560205260409020546001600160401b031690565b6040516001600160401b039091168152602001610336565b3480156104bc57600080fd5b5061032b6104cb366004614f75565b61101d565b6103096104de3660046152c4565b6110b5565b3480156104ef57600080fd5b5061045461116e565b34801561050457600080fd5b50604080518082018252600d81526c312e342e352d616c7068612e3160981b602082015290516103369190615361565b34801561054057600080fd5b5060d2546001600160401b0316610498565b34801561055e57600080fd5b5061041361056d3660046151ed565b611221565b34801561057e57600080fd5b5061045461058d366004615374565b611244565b34801561059e57600080fd5b506105b26105ad366004614f75565b611387565b6040805182516001600160a01b031681526020928301519281019290925201610336565b3480156105e257600080fd5b506105f66105f1366004614f75565b611442565b60405161033691906153cb565b34801561060f57600080fd5b5060d45463ffffffff165b60405163ffffffff9091168152602001610336565b34801561063b57600080fd5b5061035f61064a36600461542c565b6115e4565b34801561065b57600080fd5b50610309611625565b34801561067057600080fd5b5061068461067f366004614f75565b611639565b604051905163ffffffff168152602001610336565b3480156106a557600080fd5b5060c9546001600160a01b03165b6040516001600160a01b039091168152602001610336565b3480156106d757600080fd5b506106eb6106e6366004614f75565b611667565b6040516103369190615499565b34801561070457600080fd5b50610718610713366004614f75565b6117af565b60405190516001600160a01b03168152602001610336565b34801561073c57600080fd5b5061045461074b3660046154b4565b6117e0565b34801561075c57600080fd5b506033546001600160a01b03166106b3565b34801561077a57600080fd5b5061035f610789366004614fa9565b611832565b34801561079a57600080fd5b5061035f6107a9366004614fa9565b6118aa565b3480156107ba57600080fd5b5060d654610454565b3480156107cf57600080fd5b506107d8611924565b60405161ffff9091168152602001610336565b3480156107f757600080fd5b5061080061199e565b604051610336919061550d565b34801561081957600080fd5b5061035f61082836600461542c565b611a11565b61043661083b366004615219565b611a22565b34801561084c57600080fd5b5061035f61085b366004614fa9565b611a37565b34801561086c57600080fd5b5061041361087b366004614fa9565b600090815260d560205260409020546001600160401b0316151590565b3480156108a457600080fd5b506103096108b3366004615520565b611a4b565b6103096108c6366004615592565b611d83565b3480156108d757600080fd5b506108eb6108e6366004614fa9565b611e5e565b6040516103369190615635565b34801561090457600080fd5b5060cf54610454565b34801561091957600080fd5b50610454610928366004615374565b611f25565b34801561093957600080fd5b50610959610948366004614f75565b604080516020810190915290815290565b6040516103369190615644565b34801561097257600080fd5b50610454610981366004614fa9565b61200d565b34801561099257600080fd5b50610454612041565b3480156109a757600080fd5b506397a6f30461061a565b6109c56109c036600461565f565b61204c565b60405161033691906156ce565b6103096109e0366004615374565b612357565b3480156109f157600080fd5b50610309610a00366004615005565b6123d4565b600054610100900460ff1615808015610a255750600054600160ff909116105b80610a3f5750303b158015610a3f575060005460ff166001145b610aa75760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610aca576000805461ff0019166101001790555b610ad261244a565b610ada612479565b610aec8b8b8b8b8b8b8b8b8b8b6124a0565b610af4611625565b8015610b3a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050505050565b6040805160208101909152600081526000610b628382612661565b6001600160401b03168252610b78600882615775565b905080835114610b9b576040516397363b3560e01b815260040160405180910390fd5b50919050565b610ba9614b7e565b610bb582610828612041565b92915050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610c035760405162461bcd60e51b8152600401610a9e90615788565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c356126be565b6001600160a01b031614610c5b5760405162461bcd60e51b8152600401610a9e906157d4565b610c64816126da565b610c9d8160005b6040519080825280601f01601f191660200182016040528015610c95576020820181803683370190505b5060006126e2565b50565b606080610cad8b8b611f25565b341015610ccc5760405162976f7560e21b815260040160405180910390fd5b6040805161010060208b02808301820190935260e082018b815260009383928e918e918291908601908490808284376000920191909152505050908252506001600160401b03808b16602083015289811660408301528815156060830152871515608083015260a0909101908b90811115610d4957610d49614e67565b604051908082528060200260200182016040528015610d8257816020015b610d6f614ba5565b815260200190600190039081610d675790505b5081526020018a6001600160401b03811115610da057610da0614e67565b604051908082528060200260200182016040528015610dc9578160200160208202803683370190505b50905290506000805b8c811015610e1357610e078e8e83818110610def57610def615820565b9050602002810190610e019190615836565b85612852565b90910190600101610dd2565b5060005b8a811015610efe5760008360a001518281518110610e3757610e37615820565b60200260200101519050868015610e4e5750805115155b15610ef557610ef58d8d84818110610e6857610e68615820565b905060200201356040518060c001604052808460200151606001516001600160401b0316815260200184602001516040015160030b815260200184602001516000015160070b81526020018460200151602001516001600160401b0316815260200184604001516000015160070b81526020018460400151602001516001600160401b0316815250612980565b50600101610e17565b50858015610f1557506001600160401b0381168a14155b15610f335760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b8a811015610f8a578260a001518181518110610f5457610f54615820565b6020026020010151600001516000801b03610f82576040516345805f5d60e01b815260040160405180910390fd5b600101610f36565b508160a001518260c00151935093505050995099975050505050505050565b6040805160f09390931b6001600160f01b0319166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b60606110118787878787876000806000610ca0565b50979650505050505050565b6040805160208101909152600081526000806110398482612661565b9050611046600883615775565b915060006110548584612661565b9050611061600884615775565b92506110776001600160401b038216600a61595b565b61108a906001600160401b038416615967565b8452845183146110ad576040516397363b3560e01b815260040160405180910390fd5b505050919050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036110fd5760405162461bcd60e51b8152600401610a9e90615788565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661112f6126be565b6001600160a01b0316146111555760405162461bcd60e51b8152600401610a9e906157d4565b61115e826126da565b61116a828260016126e2565b5050565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461120e5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610a9e565b50600080516020615f3683398151915290565b60d05460009061ffff848116911614801561123d575060d15482145b9392505050565b60008060048484838161125957611259615820565b905060200281019061126b9190615836565b90501180156112b0575063504e41556112a8858560008161128e5761128e615820565b90506020028101906112a09190615836565b503560e01c90565b63ffffffff16145b1561135d576000806112e5868660008181106112ce576112ce615820565b90506020028101906112e09190615836565b612ab1565b909250905060008180156112fb576112fb6153b5565b146113195760405163734fff6760e11b815260040160405180910390fd5b6113478686600081811061132f5761132f615820565b90506020028101906113419190615836565b84612b6a565b6113549060ff1684615775565b92505050611376565b60405163734fff6760e11b815260040160405180910390fd5b61137f81612ba1565b949350505050565b604080518082019091526000808252602082015260006113a78382612bb9565b6001600160a01b031682526113bd601482615775565b905060006113cb8483612661565b90506113d8600883615775565b915060006113e68584612661565b90506113f3600884615775565b92506114096001600160401b038216600a61595b565b61141c906001600160401b038416615967565b6020850152845183146110ad576040516397363b3560e01b815260040160405180910390fd5b61146e604080516080810190915280600081526020016000815260006020820152606060409091015290565b60008061147b8482612c1e565b905063ffffffff8116635054474d146114a7576040516397363b3560e01b815260040160405180910390fd5b6114b2600483615775565b915060006114c08584612c7b565b90508060ff1660038111156114d7576114d76153b5565b849060038111156114ea576114ea6153b5565b908160038111156114fd576114fd6153b5565b90525061150b600184615775565b9250600184516003811115611522576115226153b5565b14611540576040516363daeb7760e01b815260040160405180910390fd5b600061154c8685612c7b565b90508060ff166009811115611563576115636153b5565b85602001906009811115611579576115796153b5565b9081600981111561158c5761158c6153b5565b90525061159a600185615775565b93506115a68685612cd7565b61ffff1660408601526115ba600285615775565b93506115d5848588516115cd919061597e565b889190612d34565b60608601525092949350505050565b6115ec614b7e565b6115f583611832565b905081611606428360600151612e41565b1115610bb557604051630cd5fa0760e11b815260040160405180910390fd5b61162d612e66565b6116376000612ec0565b565b60408051602081019091526000815260006116548382612c1e565b63ffffffff168252610b78600482615775565b6040805160208101909152606081526000806116838482612c7b565b9050611690600183615775565b91508060ff166001600160401b038111156116ad576116ad614e67565b6040519080825280602002602001820160405280156116f257816020015b60408051808201909152600080825260208201528152602001906001900390816116cb5790505b50835260005b8160ff168110156117865761170d8584612cd7565b845180518390811061172157611721615820565b602090810291909101015161ffff909116905261173f600284615775565b925061174b8584612f12565b845180518390811061175f5761175f615820565b6020026020010151602001818152505060208361177c9190615775565b92506001016116f8565b50818451146117a8576040516397363b3560e01b815260040160405180910390fd5b5050919050565b60408051602081019091526000815260006117ca8382612bb9565b6001600160a01b03168252610b78601482615775565b60008160000151826020015160405160200161181592919060f09290921b6001600160f01b0319168252600282015260220190565b604051602081830303815290604052805190602001209050919050565b61183a614b7e565b600082815260d56020908152604080832080546001600160401b0380821660608801819052600160401b9283900460030b948801949094526001830154600781900b8852919091041692850192909252909103610b9b57604051630295d7cd60e31b815260040160405180910390fd5b6118b2614b7e565b600082815260d56020908152604080832080546001600160401b0380821660608801819052600160401b830460030b94880194909452600160601b820460070b8752600160a01b9091041692850192909252909103610b9b57604051630295d7cd60e31b815260040160405180910390fd5b600061193860c9546001600160a01b031690565b6001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa158015611975573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611999919061599c565b905090565b606060c9600301805480602002602001604051908101604052809291908181526020016000905b82821015611a085760008481526020908190206040805180820190915260028502909101805461ffff1682526001908101548284015290835290920191016119c5565b50505050905090565b611a19614b7e565b6115f5836118aa565b60606110118787878787876001600080610ca0565b611a3f614b7e565b610bb58261064a612041565b6000611a8c83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f7092505050565b90506000611a9d8260e00151611442565b9050611aa7611924565b61ffff16816040015161ffff1614158015611ac95750604081015161ffff1615155b15611ae7576040516363daeb7760e01b815260040160405180910390fd5b600081602001516009811115611aff57611aff6153b5565b03611b4757806040015161ffff16600003611b2d576040516363daeb7760e01b815260040160405180910390fd5b611b42611b3d82606001516117af565b6130a4565b611d7d565b600181602001516009811115611b5f57611b5f6153b5565b03611b8557611b42611b808260600151604080516020810190915290815290565b6130ad565b600281602001516009811115611b9d57611b9d6153b5565b03611bb757611b42611bb28260600151611667565b61336c565b600381602001516009811115611bcf57611bcf6153b5565b03611be957611b42611be4826060015161101d565b6134e1565b600481602001516009811115611c0157611c016153b5565b03611c1b57611b42611c168260600151610b47565b613533565b600581602001516009811115611c3357611c336153b5565b03611c51576040516397363b3560e01b815260040160405180910390fd5b600681602001516009811115611c6957611c696153b5565b03611ce357806040015161ffff16600003611c97576040516363daeb7760e01b815260040160405180910390fd5b611b42611ca782606001516117af565b85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061357092505050565b600781602001516009811115611cfb57611cfb6153b5565b14611d7d57600881602001516009811115611d1857611d186153b5565b03611d3257611b42611d2d826060015161101d565b613787565b600981602001516009811115611d4a57611d4a6153b5565b03611d6457611b42611d5f8260600151611387565b6137c4565b6040516397363b3560e01b815260040160405180910390fd5b50505050565b828114611da35760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b83811015611e3c57828282818110611dc057611dc0615820565b9050602002016020810190611dd591906159b9565b6001600160401b0316611e15868684818110611df357611df3615820565b90506020020135600090815260d560205260409020546001600160401b031690565b6001600160401b03161015611e3457611e2e8787612357565b50611e56565b600101611da6565b50604051636f162bfd60e11b815260040160405180910390fd5b505050505050565b611e66614ba5565b6000611e71836138d3565b80519091506001600160401b0316600003611e9f57604051630295d7cd60e31b815260040160405180910390fd5b91815260408083015160208084018051600793840b905260608087015182516001600160401b039182169085015283880180518451600391820b908901528951945194831694840194909452608089015187890180519190970b905260a0890151865190831695019490945292518451920b919094015293519051931692019190915290565b600080805b83811015612003576004858583818110611f4657611f46615820565b9050602002810190611f589190615836565b9050118015611f84575063504e4155611f7c86868481811061128e5761128e615820565b63ffffffff16145b1561135d57600080611fa18787858181106112ce576112ce615820565b90925090506000818015611fb757611fb76153b5565b14611fd55760405163734fff6760e11b815260040160405180910390fd5b611fea87878581811061132f5761132f615820565b611ff79060ff1685615775565b93505050600101611f2a565b5061137f81612ba1565b600061201860d65490565b8261202260ce5490565b61202d9060ff615967565b6120379190615967565b610bb59190615775565b600061199960cf5490565b60606002841461206f5760405163734fff6760e11b815260040160405180910390fd5b600061207b8686611244565b90508034101561209d5760405162976f7560e21b815260040160405180910390fd5b60608060006120cf898960008181106120b8576120b8615820565b90506020028101906120ca9190615836565b613957565b90945092506060915081905060006120f38b8b60018181106120b8576120b8615820565b8051875192965090945014915061211f905057604051630196224b60e41b815260040160405180910390fd5b60005b83518110156121855781818151811061213d5761213d615820565b602002602001015184828151811061215757612157615820565b60200260200101511461217d57604051630196224b60e41b815260040160405180910390fd5b600101612122565b50866001600160401b0381111561219e5761219e614e67565b6040519080825280602002602001820160405280156121d757816020015b6121c4614bd2565b8152602001906001900390816121bc5790505b50955060005b878110156122f55760008989838181106121f9576121f9615820565b9050602002013590506000600019905060005b8651811015612245578287828151811061222857612228615820565b60200260200101510361223d57809150612245565b60010161220c565b50600081126122eb57600081905061228f88828151811061226857612268615820565b602002602001015187838151811061228257612282615820565b6020026020010151613b1e565b6122cc838983815181106122a5576122a5615820565b60200260200101518884815181106122bf576122bf615820565b6020026020010151613c36565b8a85815181106122de576122de615820565b6020026020010181905250505b50506001016121dd565b5060005b878110156123495786818151811061231357612313615820565b6020026020010151600001516000801b03612341576040516345805f5d60e01b815260040160405180910390fd5b6001016122f9565b505050505050949350505050565b6000805b828110156123a65761238f84848381811061237857612378615820565b905060200281019061238a9190615836565b613d65565b61239c9060ff1683615775565b915060010161235b565b5060006123b282612ba1565b905080341015611d7d5760405162976f7560e21b815260040160405180910390fd5b6123dc612e66565b6001600160a01b0381166124415760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a9e565b610c9d81612ec0565b600054610100900460ff166124715760405162461bcd60e51b8152600401610a9e906159d6565b611637613e3d565b600054610100900460ff166116375760405162461bcd60e51b8152600401610a9e906159d6565b6124a98a613e6d565b8786146124c95760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b8881101561260c57600060405180604001604052808c8c858181106124f3576124f3615820565b90506020020160208101906125089190615a21565b61ffff1681526020018a8a8581811061252357612523615820565b90506020020135815250905061254181600001518260200151610fa9565b1561255f5760405163a9cb9e0d60e01b815260040160405180910390fd5b600160cd600061256e846117e0565b81526020808201929092526040016000908120805460ff19169315159390931790925560cc8054600181810183559190935283517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebe6002909402938401805461ffff191661ffff9092169190911790559201517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebf90910155016124cc565b506040805180820190915261ffff86168082526020820186905260d0805461ffff1916909117905560d185905561264284613e8f565b5061264c8260cf55565b6126558160ce55565b50505050505050505050565b600061266e826008615775565b835110156126b55760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b6044820152606401610a9e565b50016008015190565b600080516020615f36833981519152546001600160a01b031690565b610c9d612e66565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561271a5761271583613eb2565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612774575060408051601f3d908101601f1916820190925261277191810190615a3e565b60015b6127d75760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610a9e565b600080516020615f3683398151915281146128465760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610a9e565b50612715838383613f4e565b600060048311158061286c5750833560e01c63504e415514155b1561288a5760405163734fff6760e11b815260040160405180910390fd5b6000806128978686612ab1565b909250905060008180156128ad576128ad6153b5565b146128cb5760405163734fff6760e11b815260040160405180910390fd5b5060408051606081018252600080825260208201819052918101919091523660006128f7888886613f73565b6001600160401b0316604089015260ff90921660208801526001600160601b031990921686529195509250905060005b836020015160ff1681101561294d57612943848484888b6140b3565b9450600101612927565b5083811461296e5760405163734fff6760e11b815260040160405180910390fd5b50506020015160ff1695945050505050565b600082815260d5602052604090205481516001600160401b03918216911681101561271557600083815260d560209081526040918290208451815486840151878601516060808a01516001600160401b039586166001600160601b03199095168517600160401b63ffffffff9095168502176fffffffffffffffffffffffffffffffff60601b1916600160601b8785160267ffffffffffffffff60a01b191617600160a01b91871691820217875560808b01516001909701805460a08d01519888166fffffffffffffffffffffffffffffffff19909116179790961690930295909517909355855191825260079290920b938101939093529282019290925284917fd06a6b7f4918494b3719217d1802786c1f5112a6c1d88fe2cfec00b4584f6aec910160405180910390a2505050565b60046000833560e01c63504e41558114612ade5760405163734fff6760e11b815260040160405180910390fd5b60018084019386013560f81c908114612b0a5760405163734fff6760e11b815260040160405180910390fd5b50508184016001013560f890811c9092016002818101939186010135901c60ff168015612b3957612b396153b5565b60019290920191905081831015612b635760405163734fff6760e11b815260040160405180910390fd5b9250929050565b60008382013560f01c612b7e600284615775565b9250612b8e61ffff821684615775565b92508483013560f81c5b95945050505050565b6000612bac60d65490565b60ce546120379084615967565b6000612bc6826014615775565b83511015612c0e5760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b6044820152606401610a9e565b500160200151600160601b900490565b6000612c2b826004615775565b83511015612c725760405162461bcd60e51b8152602060048201526014602482015273746f55696e7433325f6f75744f66426f756e647360601b6044820152606401610a9e565b50016004015190565b6000612c88826001615775565b83511015612cce5760405162461bcd60e51b8152602060048201526013602482015272746f55696e74385f6f75744f66426f756e647360681b6044820152606401610a9e565b50016001015190565b6000612ce4826002615775565b83511015612d2b5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606401610a9e565b50016002015190565b606081612d4281601f615775565b1015612d815760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610a9e565b612d8b8284615775565b84511015612dcf5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610a9e565b606082158015612dee5760405191506000825260208201604052612e38565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612e27578051835260209283019201612e0f565b5050858452601f01601f1916604052505b50949350505050565b600081831115612e5c57612e55828461597e565b9050610bb5565b612e55838361597e565b6033546001600160a01b031633146116375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9e565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000612f1f826020615775565b83511015612f675760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b6044820152606401610a9e565b50016020015190565b612f78614c08565b600080612f8d60c9546001600160a01b031690565b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b8152600401612fb89190615361565b600060405180830381865afa158015612fd5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612ffd9190810190615ba3565b50915091508061302057604051632acbe91560e01b815260040160405180910390fd5b61303282606001518360800151611221565b61304f5760405163360f2d8760e01b815260040160405180910390fd5b60d2546001600160401b03166001600160401b03168260a001516001600160401b031611613090576040516388d1b84760e01b815260040160405180910390fd5b61309d8260a00151613e8f565b5092915050565b610c9d816143cd565b60006130e16040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b90506000806130f860c9546001600160a01b031690565b845160405163607ec5ef60e11b81526001600160a01b03929092169163c0fd8bde9161312691600401615361565b600060405180830381865afa158015613143573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261316b9190810190615ba3565b50915091508061318e57604051632acbe91560e01b815260040160405180910390fd5b600061319d8360e00151611442565b90506131a7611924565b61ffff16816040015161ffff16141580156131c95750604081015161ffff1615155b156131e7576040516363daeb7760e01b815260040160405180910390fd5b6005816020015160098111156131ff576131ff6153b5565b1461321d576040516397363b3560e01b815260040160405180910390fd5b600061322c8260600151611639565b805190915063ffffffff1661324660d45463ffffffff1690565b63ffffffff161061326a576040516388d1b84760e01b815260040160405180910390fd5b805160d4805463ffffffff191663ffffffff90921691909117905560408051808201909152606085015161ffff1680825260808601516020830181905260d0805461ffff191690921790915560d1556132c68560a00151613e8f565b7f6bce23ef3d34e51710fe4700b43ba5f1733a6215c883f384671a4ece3ea8aa208661331a6040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b60d25460408051845161ffff90811682526020958601518683015284511691810191909152929091015160608301526001600160401b0316608082015260a0015b60405180910390a150505050505050565b600061337661199e565b905060005b81518110156133e057600060c960040160006133af8585815181106133a2576133a2615820565b60200260200101516117e0565b81526020810191909152604001600020805460ff19169115159190911790556133d9600182615775565b905061337b565b506133ed60cc6000614c63565b60005b82515181101561349c578251805160cc91908390811061341257613412615820565b60209081029190910181015182546001808201855560009485528385208351600290930201805461ffff191661ffff90931692909217825591909201519181019190915584518051919260cd92909161347591869081106133a2576133a2615820565b81526020810191909152604001600020805460ff19169115159190911790556001016133f0565b507fd451e0fcb7c5b9e13de533604d158069dad159841c45f39f09d379bfc423080d816134c761199e565b6040516134d5929190615d0b565b60405180910390a15050565b60006134ec60ce5490565b825160ce5590507f74dbbbe280ef27b79a8a0c449d5ae2ba7a31849103241d0f98df70bbc9d03e378161351e60ce5490565b604080519283526020830191909152016134d5565b600061353e60cf5490565b825160cf5590507fcdb88a22f82ddd76115ab7c66cf08eb1e40afe80c9b31017eb2cbdb1570b33ae8161351e60cf5490565b600061358460c9546001600160a01b031690565b90506135938360000151613e6d565b6000806135a860c9546001600160a01b031690565b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b81526004016135d39190615361565b600060405180830381865afa1580156135f0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526136189190810190615ba3565b50915091508061363b576040516397363b3560e01b815260040160405180910390fd5b61364d82606001518360800151611221565b61366a576040516397363b3560e01b815260040160405180910390fd5b60d2546001600160401b03166001600160401b03168260a001516001600160401b0316146136ab576040516309e9f6c160e11b815260040160405180910390fd5b60006136ba8360e00151611442565b90506006816020015160098111156136d4576136d46153b5565b146136f2576040516309e9f6c160e11b815260040160405180910390fd5b600061370182606001516117af565b875181519192506001600160a01b03918216911614613733576040516309e9f6c160e11b815260040160405180910390fd5b7fd495c4e5b386d59bccca38a2277b5d70a0f5e47d7b6587a45a6f5aca221a31258561376760c9546001600160a01b031690565b604080516001600160a01b0393841681529290911660208301520161335b565b600061379260d65490565b825160d65590507f5ac11e113c4b7116e6d04c95bd9f5ec9109fc1199331c882f5a0b63c9b33ac2b8161351e60d65490565b47816020015111156137e85760405162976f7560e21b815260040160405180910390fd5b805160208201516040516000926001600160a01b031691908381818185875af1925050503d8060008114613838576040519150601f19603f3d011682016040523d82523d6000602084013e61383d565b606091505b505090508061388e5760405162461bcd60e51b815260206004820152601760248201527f4661696c656420746f20776974686472617720666565730000000000000000006044820152606401610a9e565b8151602080840151604080516001600160a01b039094168452918301527f78473f3f373f7673597f4f0fa5873cb4d375fea6d4339ad6b56dbd411513cb3f91016134d5565b6138db614c84565b50600090815260d56020908152604091829020825160c08101845281546001600160401b038082168352600160401b80830460030b95840195909552600160601b8204600790810b96840196909652600160a01b909104811660608301526001909201549384900b60808201529190920490911660a082015290565b600060608060008060008036600061396f8b8b612ab1565b965094506000868015613984576139846153b5565b146139a25760405163734fff6760e11b815260040160405180910390fd5b6139ad8b8b87613f73565b509398509196509450925090508985106139da5760405163734fff6760e11b815260040160405180910390fd5b8260ff166001600160401b038111156139f5576139f5614e67565b604051908082528060200260200182016040528015613a2e57816020015b613a1b614cb9565b815260200190600190039081613a135790505b5097508260ff166001600160401b03811115613a4c57613a4c614e67565b604051908082528060200260200182016040528015613a75578160200160208202803683370190505b50965060005b8360ff16811015613aed57613a8e614cb9565b6000613a9c8786868b6144bc565b8d51929a50909350915082908c9085908110613aba57613aba615820565b6020026020010181905250808a8481518110613ad857613ad8615820565b60209081029190910101525050600101613a7b565b50848114613b0e5760405163076ef4a560e21b815260040160405180910390fd5b8498505050505050509250925092565b81608001516001600160401b03168260a001516001600160401b031610613b585760405163076ef4a560e21b815260040160405180910390fd5b80608001516001600160401b03168160a001516001600160401b031610613b925760405163076ef4a560e21b815260040160405180910390fd5b8060c0015160030b8260c0015160030b14613bc057604051630196224b60e41b815260040160405180910390fd5b80606001516001600160401b031682606001516001600160401b03161115613bfb57604051630196224b60e41b815260040160405180910390fd5b80608001516001600160401b031682608001516001600160401b0316111561116a57604051630196224b60e41b815260040160405180910390fd5b613c3e614bd2565b8381526080808401516001600160401b0390811660208401529083015116604082015260608084015190830151600091613c7791615d30565b84518451919250600091613c8b9190615d4f565b9050600085602001518560200151613ca39190615d85565b90506000613cba6001600160401b03851684615dba565b90506000613cd16001600160401b03861684615df8565b60608088018051600786900b905280516001600160401b0380851660209092019190915260c08c0151825160039190910b60409182015260808c015192519290911691909201528981015190890151919250600091613d309190615d30565b9050600086613d4283620f4240615e26565b613d4c9190615e48565b63ffffffff166080890152505050505050509392505050565b6000806000613d748585612ab1565b90925090506000818015613d8a57613d8a6153b5565b14613da85760405163734fff6760e11b815260040160405180910390fd5b60008036600080613dba8a8a89613f73565b929c50939850919650909450909250905060005b8860ff16811015613e0f57613de1614c84565b600080613df08888888c614518565b929b5090945092509050613e048284612980565b505050600101613dce565b50848214613e305760405163734fff6760e11b815260040160405180910390fd5b5050505050505092915050565b600054610100900460ff16613e645760405162461bcd60e51b8152600401610a9e906159d6565b61163733612ec0565b60c980546001600160a01b0319166001600160a01b0392909216919091179055565b60d2805467ffffffffffffffff19166001600160401b0392909216919091179055565b6001600160a01b0381163b613f1f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610a9e565b600080516020615f3683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b613f5783614578565b600082511180613f645750805b1561271557611d7d83836145b8565b60008080368180613f888989898082036146a3565b600297509093509150823560f01c60606000613fae613fa987878c876146a3565b6146cd565b60e0015160048082015161ffff86169b909b019a9193509150634155575663ffffffff821614613ff15760405163734fff6760e11b815260040160405180910390fd5b8183016001015160009060ff16801561400c5761400c6153b5565b60019093019290506000818015614025576140256153b5565b146140435760405163734fff6760e11b815260040160405180910390fd5b828401600801519550600c909201916140678484602091010151600160601b900490565b60601b995060148301925083518311156140945760405163734fff6760e11b815260040160405180910390fd5b5050600189019c979b505050509482013560f81c965090945092919050565b60006140bd614c84565b6000806140d08960000151898989614518565b9296509094509250905060005b8551518110156141145782866000015182815181106140fe576140fe615820565b60200260200101510315614114576001016140dd565b8551518110801561414457508560a00151818151811061413657614136615820565b602090810291909101015151155b156143c057835160208701516001600160401b0391821691168110801590614179575086604001516001600160401b03168111155b80156141a65750866060015115806141a65750826001600160401b031687602001516001600160401b0316115b156143be57838760a0015183815181106141c2576141c2615820565b602090810291909101015152604085015160a08801518051849081106141ea576141ea615820565b602090810291909101810151015160079190910b9052606085015160a088015180518490811061421c5761421c615820565b602002602001015160200151602001906001600160401b031690816001600160401b03168152505084602001518760a00151838151811061425f5761425f615820565b6020026020010151602001516040019060030b908160030b81525050808760a00151838151811061429257614292615820565b602002602001015160200151606001818152505084608001518760a0015183815181106142c1576142c1615820565b6020026020010151604001516000019060070b908160070b815250508460a001518760a0015183815181106142f8576142f8615820565b602002602001015160400151602001906001600160401b031690816001600160401b03168152505084602001518760a00151838151811061433b5761433b615820565b6020026020010151604001516040019060030b908160030b81525050808760a00151838151811061436e5761436e615820565b60200260200101516040015160600181815250508a604001518760c00151838151811061439d5761439d615820565b60200260200101906001600160401b031690816001600160401b0316815250505b505b5050505095945050505050565b60006143d76126be565b82519091506143e7906000610c6b565b306001600160a01b031663e3795cc16040518163ffffffff1660e01b8152600401602060405180830381865afa158015614425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144499190615e76565b63ffffffff166397a6f30414614472576040516397363b3560e01b815260040160405180910390fd5b7f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a498161449c6126be565b604080516001600160a01b039384168152929091166020830152016134d5565b60006144c6614cb9565b6000366000806144d88989898d6147b7565b98509194509250905060018160018111156144f5576144f56153b5565b0361135d576145068383600161489e565b90955093505050509450945094915050565b6000614522614c84565b600080366000806145358a8a8a8e6147b7565b9950919450925090506000816001811115614552576145526153b5565b0361135d576145638383600161493b565b91975095509350505050945094509450949050565b61458181613eb2565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6146205760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610a9e565b600080846001600160a01b03168460405161463b9190615e91565b600060405180830381855af49150503d8060008114614676576040519150601f19603f3d011682016040523d82523d6000602084013e61467b565b606091505b5091509150612b988282604051806060016040528060278152602001615f5660279139614a14565b3660008584866146b38683615775565b926146c093929190615ead565b9150915094509492505050565b6146d5614c08565b60006146e960c9546001600160a01b031690565b6001600160a01b031663c0fd8bde85856040518363ffffffff1660e01b8152600401614716929190615ed7565b600060405180830381865afa158015614733573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261475b9190810190615ba3565b5090925090508061477f57604051632acbe91560e01b815260040160405180910390fd5b5061479281606001518260800151610fa9565b610bb55760405163e60dce7160e01b815260040160405180910390fd5b016008015190565b36600080808786013560f01c6147ce600288615775565b96506147e08989898461ffff166146a3565b90955093506147f361ffff821688615775565b965060006148058a8a8a8a8a8a614a2d565b93509050806148275760405163734fff6760e11b815260040160405180910390fd5b853560f81c600181111561483d5761483d6153b5565b93506000846001811115614853576148536153b5565b1415801561487357506001846001811115614870576148706153b5565b14155b156148915760405163734fff6760e11b815260040160405180910390fd5b5050945094509450949050565b6148a6614cb9565b818401602081810135608090811d84526030830135811c9184019190915260408083013560c090811c918501919091526048830135811c6060808601919091526050840135821c928501929092526058830135811c60a08501529082013560e01d9083015260649092019135838311156149335760405163734fff6760e11b815260040160405180910390fd5b935093915050565b614943614c84565b60208483018181013560c090811d6040858101919091526028830135821c6060860152603083013560e01d85850152603483013590911c84528051601f8701849004840281018401909152858152603c909401939035916000916149c39188908890819084018382808284376000920191909152508892506147af915050565b868501600881013560c090811d6080870152601090910135901c60a0850152601890940193905084841115614a0b5760405163734fff6760e11b815260040160405180910390fd5b93509350939050565b60608315614a2357508161123d565b61123d8383614ad5565b6000806000614a7185858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250614aff92505050565b600188019790915089013560f81c60005b8160ff16811015614ab45760148901988b01356001600160601b031916614aa98482614b32565b935050600101614a82565b50506001600160601b03199081169516949094149794965093945050505050565b815115614ae55781518083602001fd5b8060405162461bcd60e51b8152600401610a9e9190615361565b6000610bb5600083604051602001614b18929190615f06565b604051602081830303815290604052805160209091012090565b60006001600160601b03198083169084161115614b4d579091905b604051600160f81b60208201526001600160601b031980851660218301528316603582015261123d90604901614b18565b60408051608081018252600080825260208201819052918101829052606081019190915290565b60408051606081019091526000815260208101614bc0614b7e565b8152602001614bcd614b7e565b905290565b6040805160a0810182526000808252602082018190529181019190915260608101614bfb614b7e565b8152600060209091015290565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201819052610100820183905261012082015261014081019190915290565b5080546000825560020290600052602060002090810190610c9d9190614cf5565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b5b80821115614d1657805461ffff1916815560006001820155600201614cf6565b5090565b80356001600160a01b0381168114614d3157600080fd5b919050565b60008083601f840112614d4857600080fd5b5081356001600160401b03811115614d5f57600080fd5b6020830191508360208260051b8501011115612b6357600080fd5b61ffff81168114610c9d57600080fd5b6001600160401b0381168114610c9d57600080fd5b6000806000806000806000806000806101008b8d031215614dbf57600080fd5b614dc88b614d1a565b995060208b01356001600160401b03811115614de357600080fd5b614def8d828e01614d36565b909a5098505060408b01356001600160401b03811115614e0e57600080fd5b614e1a8d828e01614d36565b90985096505060608b0135614e2e81614d7a565b945060808b0135935060a08b0135614e4581614d8a565b999c989b50969995989497939650919460c08101359360e09091013592509050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715614e9f57614e9f614e67565b60405290565b60405161016081016001600160401b0381118282101715614e9f57614e9f614e67565b604051601f8201601f191681016001600160401b0381118282101715614ef057614ef0614e67565b604052919050565b60006001600160401b03821115614f1157614f11614e67565b50601f01601f191660200190565b600082601f830112614f3057600080fd5b8135614f43614f3e82614ef8565b614ec8565b818152846020838601011115614f5857600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215614f8757600080fd5b81356001600160401b03811115614f9d57600080fd5b61137f84828501614f1f565b600060208284031215614fbb57600080fd5b5035919050565b805160070b82526001600160401b036020820151166020830152604081015160030b6040830152606081015160608301525050565b60808101610bb58284614fc2565b60006020828403121561501757600080fd5b61123d82614d1a565b8015158114610c9d57600080fd5b600080600080600080600080600060e08a8c03121561504c57600080fd5b89356001600160401b0381111561506257600080fd5b61506e8c828d01614d36565b909a5098505060208a01356001600160401b0381111561508d57600080fd5b6150998c828d01614d36565b90985096505060408a01356150ad81614d8a565b945060608a01356150bd81614d8a565b935060808a01356150cd81615020565b925060a08a01356150dd81615020565b915060c08a01356150ed81615020565b809150509295985092959850929598565b8051825260208101516151146020840182614fc2565b50604081015161271560a0840182614fc2565b600081518084526020840193506020830160005b828110156151655761514e8683516150fe565b61012095909501946020919091019060010161513b565b5093949350505050565b6040815260006151826040830185615127565b828103602084015280845180835260208301915060208601925060005b818110156151c65783516001600160401b031683526020938401939092019160010161519f565b50909695505050505050565b815161ffff1681526020808301519082015260408101610bb5565b6000806040838503121561520057600080fd5b823561520b81614d7a565b946020939093013593505050565b6000806000806000806080878903121561523257600080fd5b86356001600160401b0381111561524857600080fd5b61525489828a01614d36565b90975095505060208701356001600160401b0381111561527357600080fd5b61527f89828a01614d36565b909550935050604087013561529381614d8a565b915060608701356152a381614d8a565b809150509295509295509295565b60208152600061123d6020830184615127565b600080604083850312156152d757600080fd5b6152e083614d1a565b915060208301356001600160401b038111156152fb57600080fd5b61530785828601614f1f565b9150509250929050565b60005b8381101561532c578181015183820152602001615314565b50506000910152565b6000815180845261534d816020860160208601615311565b601f01601f19169290920160200192915050565b60208152600061123d6020830184615335565b6000806020838503121561538757600080fd5b82356001600160401b0381111561539d57600080fd5b6153a985828601614d36565b90969095509350505050565b634e487b7160e01b600052602160045260246000fd5b6020815260008251600481106153e3576153e36153b5565b806020840152506020830151600a81106153ff576153ff6153b5565b8060408401525061ffff6040840151166060830152606083015160808084015261137f60a0840182615335565b6000806040838503121561543f57600080fd5b50508035926020909101359150565b600081518084526020840193506020830160005b8281101561516557615483868351805161ffff168252602090810151910152565b6040959095019460209190910190600101615462565b602081526000825160208084015261137f604084018261544e565b600060408284031280156154c757600080fd5b50604080519081016001600160401b03811182821017156154ea576154ea614e67565b60405282356154f881614d7a565b81526020928301359281019290925250919050565b60208152600061123d602083018461544e565b6000806020838503121561553357600080fd5b82356001600160401b0381111561554957600080fd5b8301601f8101851361555a57600080fd5b80356001600160401b0381111561557057600080fd5b85602082840101111561558257600080fd5b6020919091019590945092505050565b600080600080600080606087890312156155ab57600080fd5b86356001600160401b038111156155c157600080fd5b6155cd89828a01614d36565b90975095505060208701356001600160401b038111156155ec57600080fd5b6155f889828a01614d36565b90955093505060408701356001600160401b0381111561561757600080fd5b61562389828a01614d36565b979a9699509497509295939492505050565b6101208101610bb582846150fe565b602081526000825160208084015261137f6040840182615335565b6000806000806040858703121561567557600080fd5b84356001600160401b0381111561568b57600080fd5b61569787828801614d36565b90955093505060208501356001600160401b038111156156b657600080fd5b6156c287828801614d36565b95989497509550505050565b602080825282518282018190526000918401906040840190835b81811015615754578351805184526001600160401b0360208201511660208501526001600160401b036040820151166040850152606081015161572e6060860182614fc2565b506080015163ffffffff1660e084015260209390930192610100909201916001016156e8565b509095945050505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610bb557610bb561575f565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261584d57600080fd5b8301803591506001600160401b0382111561586757600080fd5b602001915036819003821315612b6357600080fd5b6001815b60018411156149335780850481111561589b5761589b61575f565b60018416156158a957908102905b60019390931c928002615880565b6000826158c657506001610bb5565b816158d357506000610bb5565b81600181146158e957600281146158f35761590f565b6001915050610bb5565b60ff8411156159045761590461575f565b50506001821b610bb5565b5060208310610133831016604e8410600b8410161715615932575081810a610bb5565b61593f600019848461587c565b80600019048211156159535761595361575f565b029392505050565b600061123d83836158b7565b8082028115828204841417610bb557610bb561575f565b81810381811115610bb557610bb561575f565b8051614d3181614d7a565b6000602082840312156159ae57600080fd5b815161123d81614d7a565b6000602082840312156159cb57600080fd5b813561123d81614d8a565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215615a3357600080fd5b813561123d81614d7a565b600060208284031215615a5057600080fd5b5051919050565b805160ff81168114614d3157600080fd5b805163ffffffff81168114614d3157600080fd5b8051614d3181614d8a565b600082601f830112615a9857600080fd5b8151602083016000615aac614f3e84614ef8565b9050828152858383011115615ac057600080fd5b612b98836020830184615311565b600082601f830112615adf57600080fd5b81516001600160401b03811115615af857615af8614e67565b615b0760208260051b01614ec8565b8082825260208201915060208360071b860101925085831115615b2957600080fd5b602085015b83811015615b8e5760808188031215615b4657600080fd5b615b4e614e7d565b8151815260208083015190820152615b6860408301615a57565b6040820152615b7960608301615a57565b60608201528352602090920191608001615b2e565b5095945050505050565b8051614d3181615020565b600080600060608486031215615bb857600080fd5b83516001600160401b03811115615bce57600080fd5b84016101608187031215615be157600080fd5b615be9614ea5565b615bf282615a57565b8152615c0060208301615a68565b6020820152615c1160408301615a68565b6040820152615c2260608301615991565b606082015260808281015190820152615c3d60a08301615a7c565b60a0820152615c4e60c08301615a57565b60c082015260e08201516001600160401b03811115615c6c57600080fd5b615c7888828501615a87565b60e083015250615c8b6101008301615a68565b6101008201526101208201516001600160401b03811115615cab57600080fd5b615cb788828501615ace565b6101208301525061014091820151918101919091529250615cda60208501615b98565b915060408401516001600160401b03811115615cf557600080fd5b615d0186828701615a87565b9150509250925092565b604081526000615d1e604083018561544e565b8281036020840152612b98818561544e565b6001600160401b038281168282160390811115610bb557610bb561575f565b600f82810b9082900b0360016001607f1b031981126f7fffffffffffffffffffffffffffffff82131715610bb557610bb561575f565b6001600160801b038281168282160390811115610bb557610bb561575f565b634e487b7160e01b600052601260045260246000fd5b600081600f0b83600f0b80615dd157615dd1615da4565b60016001607f1b0319821460001982141615615def57615def61575f565b90059392505050565b60006001600160801b03831680615e1157615e11615da4565b806001600160801b0384160491505092915050565b6001600160401b03818116838216029081169081811461309d5761309d61575f565b60006001600160401b03831680615e6157615e61615da4565b806001600160401b0384160491505092915050565b600060208284031215615e8857600080fd5b61123d82615a68565b60008251615ea3818460208701615311565b9190910192915050565b60008085851115615ebd57600080fd5b83861115615eca57600080fd5b5050820193919092039150565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60ff60f81b8360f81b16815260008251615f27816001850160208701615311565b91909101600101939250505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212207614ca7dd4837854d002383e05473e986de5f533c5b55d8daa58016d90e4b49c64736f6c634300081d0033
Deployed Bytecode
0x6080604052600436106102e45760003560e01c80638881016f11610190578063b6ed701e116100dc578063d82d58a511610095578063e3795cc11161006f578063e3795cc11461099b578063eb942158146109b2578063ef9e5e28146109d2578063f2fde38b146109e557600080fd5b8063d82d58a51461092d578063e17efd4814610966578063e18910a31461098657600080fd5b8063b6ed701e14610898578063b9256d28146108b8578063c091ae7b146104b0578063caaf43f1146108cb578063cb718a9b146108f8578063d47eed451461090d57600080fd5b80639a8a059211610149578063aac4129211610123578063aac41292146106f8578063accca7f91461082d578063b5dcc91114610840578063b5ec02611461086057600080fd5b80639a8a0592146107c3578063a38d81c6146107eb578063a4ae35e01461080d57600080fd5b80638881016f146106f857806389a5bb4d146107305780638da5cb5b146107505780639474f45b1461076e57806396834ad31461078e578063978a800d146107ae57600080fd5b806352d1902d1161024f5780636b7f53ca11610208578063715018a6116101e2578063715018a61461064f5780637b72bcae1461066457806384acd1bb1461069957806387c5bd1b146106cb57600080fd5b80636b7f53ca146105d65780636c72f51b14610603578063711a2e281461062f57600080fd5b806352d1902d146104e357806354fd4d50146104f8578063586d3cf81461053457806358c67635146105525780635f674e35146105725780636054312d1461059257600080fd5b8063437209a7116102a1578063437209a7146103f35780634716e9c51461042357806348b6404d146104435780634c469d8c146104625780634d7a734e146104b05780634f1ef286146104d057600080fd5b8063146faf77146102e957806314dd317f1461030b57806331d98b3f1461033f5780633659cfe61461036c5780633a229d181461038c578063426234e4146103ad575b600080fd5b3480156102f557600080fd5b50610309610304366004614d9f565b610a05565b005b34801561031757600080fd5b5061032b610326366004614f75565b610b47565b604051905181526020015b60405180910390f35b34801561034b57600080fd5b5061035f61035a366004614fa9565b610ba1565b6040516103369190614ff7565b34801561037857600080fd5b50610309610387366004615005565b610bbb565b61039f61039a36600461502e565b610ca0565b60405161033692919061516f565b3480156103b957600080fd5b506040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015260405161033691906151d2565b3480156103ff57600080fd5b5061041361040e3660046151ed565b610fa9565b6040519015158152602001610336565b610436610431366004615219565b610ffc565b60405161033691906152b1565b34801561044f57600080fd5b5060ce545b604051908152602001610336565b34801561046e57600080fd5b5061049861047d366004614fa9565b600090815260d560205260409020546001600160401b031690565b6040516001600160401b039091168152602001610336565b3480156104bc57600080fd5b5061032b6104cb366004614f75565b61101d565b6103096104de3660046152c4565b6110b5565b3480156104ef57600080fd5b5061045461116e565b34801561050457600080fd5b50604080518082018252600d81526c312e342e352d616c7068612e3160981b602082015290516103369190615361565b34801561054057600080fd5b5060d2546001600160401b0316610498565b34801561055e57600080fd5b5061041361056d3660046151ed565b611221565b34801561057e57600080fd5b5061045461058d366004615374565b611244565b34801561059e57600080fd5b506105b26105ad366004614f75565b611387565b6040805182516001600160a01b031681526020928301519281019290925201610336565b3480156105e257600080fd5b506105f66105f1366004614f75565b611442565b60405161033691906153cb565b34801561060f57600080fd5b5060d45463ffffffff165b60405163ffffffff9091168152602001610336565b34801561063b57600080fd5b5061035f61064a36600461542c565b6115e4565b34801561065b57600080fd5b50610309611625565b34801561067057600080fd5b5061068461067f366004614f75565b611639565b604051905163ffffffff168152602001610336565b3480156106a557600080fd5b5060c9546001600160a01b03165b6040516001600160a01b039091168152602001610336565b3480156106d757600080fd5b506106eb6106e6366004614f75565b611667565b6040516103369190615499565b34801561070457600080fd5b50610718610713366004614f75565b6117af565b60405190516001600160a01b03168152602001610336565b34801561073c57600080fd5b5061045461074b3660046154b4565b6117e0565b34801561075c57600080fd5b506033546001600160a01b03166106b3565b34801561077a57600080fd5b5061035f610789366004614fa9565b611832565b34801561079a57600080fd5b5061035f6107a9366004614fa9565b6118aa565b3480156107ba57600080fd5b5060d654610454565b3480156107cf57600080fd5b506107d8611924565b60405161ffff9091168152602001610336565b3480156107f757600080fd5b5061080061199e565b604051610336919061550d565b34801561081957600080fd5b5061035f61082836600461542c565b611a11565b61043661083b366004615219565b611a22565b34801561084c57600080fd5b5061035f61085b366004614fa9565b611a37565b34801561086c57600080fd5b5061041361087b366004614fa9565b600090815260d560205260409020546001600160401b0316151590565b3480156108a457600080fd5b506103096108b3366004615520565b611a4b565b6103096108c6366004615592565b611d83565b3480156108d757600080fd5b506108eb6108e6366004614fa9565b611e5e565b6040516103369190615635565b34801561090457600080fd5b5060cf54610454565b34801561091957600080fd5b50610454610928366004615374565b611f25565b34801561093957600080fd5b50610959610948366004614f75565b604080516020810190915290815290565b6040516103369190615644565b34801561097257600080fd5b50610454610981366004614fa9565b61200d565b34801561099257600080fd5b50610454612041565b3480156109a757600080fd5b506397a6f30461061a565b6109c56109c036600461565f565b61204c565b60405161033691906156ce565b6103096109e0366004615374565b612357565b3480156109f157600080fd5b50610309610a00366004615005565b6123d4565b600054610100900460ff1615808015610a255750600054600160ff909116105b80610a3f5750303b158015610a3f575060005460ff166001145b610aa75760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610aca576000805461ff0019166101001790555b610ad261244a565b610ada612479565b610aec8b8b8b8b8b8b8b8b8b8b6124a0565b610af4611625565b8015610b3a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050505050565b6040805160208101909152600081526000610b628382612661565b6001600160401b03168252610b78600882615775565b905080835114610b9b576040516397363b3560e01b815260040160405180910390fd5b50919050565b610ba9614b7e565b610bb582610828612041565b92915050565b6001600160a01b037f000000000000000000000000a2aa501b19aff244d90cc15a4cf739d2725b5729163003610c035760405162461bcd60e51b8152600401610a9e90615788565b7f000000000000000000000000a2aa501b19aff244d90cc15a4cf739d2725b57296001600160a01b0316610c356126be565b6001600160a01b031614610c5b5760405162461bcd60e51b8152600401610a9e906157d4565b610c64816126da565b610c9d8160005b6040519080825280601f01601f191660200182016040528015610c95576020820181803683370190505b5060006126e2565b50565b606080610cad8b8b611f25565b341015610ccc5760405162976f7560e21b815260040160405180910390fd5b6040805161010060208b02808301820190935260e082018b815260009383928e918e918291908601908490808284376000920191909152505050908252506001600160401b03808b16602083015289811660408301528815156060830152871515608083015260a0909101908b90811115610d4957610d49614e67565b604051908082528060200260200182016040528015610d8257816020015b610d6f614ba5565b815260200190600190039081610d675790505b5081526020018a6001600160401b03811115610da057610da0614e67565b604051908082528060200260200182016040528015610dc9578160200160208202803683370190505b50905290506000805b8c811015610e1357610e078e8e83818110610def57610def615820565b9050602002810190610e019190615836565b85612852565b90910190600101610dd2565b5060005b8a811015610efe5760008360a001518281518110610e3757610e37615820565b60200260200101519050868015610e4e5750805115155b15610ef557610ef58d8d84818110610e6857610e68615820565b905060200201356040518060c001604052808460200151606001516001600160401b0316815260200184602001516040015160030b815260200184602001516000015160070b81526020018460200151602001516001600160401b0316815260200184604001516000015160070b81526020018460400151602001516001600160401b0316815250612980565b50600101610e17565b50858015610f1557506001600160401b0381168a14155b15610f335760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b8a811015610f8a578260a001518181518110610f5457610f54615820565b6020026020010151600001516000801b03610f82576040516345805f5d60e01b815260040160405180910390fd5b600101610f36565b508160a001518260c00151935093505050995099975050505050505050565b6040805160f09390931b6001600160f01b0319166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b60606110118787878787876000806000610ca0565b50979650505050505050565b6040805160208101909152600081526000806110398482612661565b9050611046600883615775565b915060006110548584612661565b9050611061600884615775565b92506110776001600160401b038216600a61595b565b61108a906001600160401b038416615967565b8452845183146110ad576040516397363b3560e01b815260040160405180910390fd5b505050919050565b6001600160a01b037f000000000000000000000000a2aa501b19aff244d90cc15a4cf739d2725b57291630036110fd5760405162461bcd60e51b8152600401610a9e90615788565b7f000000000000000000000000a2aa501b19aff244d90cc15a4cf739d2725b57296001600160a01b031661112f6126be565b6001600160a01b0316146111555760405162461bcd60e51b8152600401610a9e906157d4565b61115e826126da565b61116a828260016126e2565b5050565b6000306001600160a01b037f000000000000000000000000a2aa501b19aff244d90cc15a4cf739d2725b5729161461120e5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610a9e565b50600080516020615f3683398151915290565b60d05460009061ffff848116911614801561123d575060d15482145b9392505050565b60008060048484838161125957611259615820565b905060200281019061126b9190615836565b90501180156112b0575063504e41556112a8858560008161128e5761128e615820565b90506020028101906112a09190615836565b503560e01c90565b63ffffffff16145b1561135d576000806112e5868660008181106112ce576112ce615820565b90506020028101906112e09190615836565b612ab1565b909250905060008180156112fb576112fb6153b5565b146113195760405163734fff6760e11b815260040160405180910390fd5b6113478686600081811061132f5761132f615820565b90506020028101906113419190615836565b84612b6a565b6113549060ff1684615775565b92505050611376565b60405163734fff6760e11b815260040160405180910390fd5b61137f81612ba1565b949350505050565b604080518082019091526000808252602082015260006113a78382612bb9565b6001600160a01b031682526113bd601482615775565b905060006113cb8483612661565b90506113d8600883615775565b915060006113e68584612661565b90506113f3600884615775565b92506114096001600160401b038216600a61595b565b61141c906001600160401b038416615967565b6020850152845183146110ad576040516397363b3560e01b815260040160405180910390fd5b61146e604080516080810190915280600081526020016000815260006020820152606060409091015290565b60008061147b8482612c1e565b905063ffffffff8116635054474d146114a7576040516397363b3560e01b815260040160405180910390fd5b6114b2600483615775565b915060006114c08584612c7b565b90508060ff1660038111156114d7576114d76153b5565b849060038111156114ea576114ea6153b5565b908160038111156114fd576114fd6153b5565b90525061150b600184615775565b9250600184516003811115611522576115226153b5565b14611540576040516363daeb7760e01b815260040160405180910390fd5b600061154c8685612c7b565b90508060ff166009811115611563576115636153b5565b85602001906009811115611579576115796153b5565b9081600981111561158c5761158c6153b5565b90525061159a600185615775565b93506115a68685612cd7565b61ffff1660408601526115ba600285615775565b93506115d5848588516115cd919061597e565b889190612d34565b60608601525092949350505050565b6115ec614b7e565b6115f583611832565b905081611606428360600151612e41565b1115610bb557604051630cd5fa0760e11b815260040160405180910390fd5b61162d612e66565b6116376000612ec0565b565b60408051602081019091526000815260006116548382612c1e565b63ffffffff168252610b78600482615775565b6040805160208101909152606081526000806116838482612c7b565b9050611690600183615775565b91508060ff166001600160401b038111156116ad576116ad614e67565b6040519080825280602002602001820160405280156116f257816020015b60408051808201909152600080825260208201528152602001906001900390816116cb5790505b50835260005b8160ff168110156117865761170d8584612cd7565b845180518390811061172157611721615820565b602090810291909101015161ffff909116905261173f600284615775565b925061174b8584612f12565b845180518390811061175f5761175f615820565b6020026020010151602001818152505060208361177c9190615775565b92506001016116f8565b50818451146117a8576040516397363b3560e01b815260040160405180910390fd5b5050919050565b60408051602081019091526000815260006117ca8382612bb9565b6001600160a01b03168252610b78601482615775565b60008160000151826020015160405160200161181592919060f09290921b6001600160f01b0319168252600282015260220190565b604051602081830303815290604052805190602001209050919050565b61183a614b7e565b600082815260d56020908152604080832080546001600160401b0380821660608801819052600160401b9283900460030b948801949094526001830154600781900b8852919091041692850192909252909103610b9b57604051630295d7cd60e31b815260040160405180910390fd5b6118b2614b7e565b600082815260d56020908152604080832080546001600160401b0380821660608801819052600160401b830460030b94880194909452600160601b820460070b8752600160a01b9091041692850192909252909103610b9b57604051630295d7cd60e31b815260040160405180910390fd5b600061193860c9546001600160a01b031690565b6001600160a01b0316639a8a05926040518163ffffffff1660e01b8152600401602060405180830381865afa158015611975573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611999919061599c565b905090565b606060c9600301805480602002602001604051908101604052809291908181526020016000905b82821015611a085760008481526020908190206040805180820190915260028502909101805461ffff1682526001908101548284015290835290920191016119c5565b50505050905090565b611a19614b7e565b6115f5836118aa565b60606110118787878787876001600080610ca0565b611a3f614b7e565b610bb58261064a612041565b6000611a8c83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f7092505050565b90506000611a9d8260e00151611442565b9050611aa7611924565b61ffff16816040015161ffff1614158015611ac95750604081015161ffff1615155b15611ae7576040516363daeb7760e01b815260040160405180910390fd5b600081602001516009811115611aff57611aff6153b5565b03611b4757806040015161ffff16600003611b2d576040516363daeb7760e01b815260040160405180910390fd5b611b42611b3d82606001516117af565b6130a4565b611d7d565b600181602001516009811115611b5f57611b5f6153b5565b03611b8557611b42611b808260600151604080516020810190915290815290565b6130ad565b600281602001516009811115611b9d57611b9d6153b5565b03611bb757611b42611bb28260600151611667565b61336c565b600381602001516009811115611bcf57611bcf6153b5565b03611be957611b42611be4826060015161101d565b6134e1565b600481602001516009811115611c0157611c016153b5565b03611c1b57611b42611c168260600151610b47565b613533565b600581602001516009811115611c3357611c336153b5565b03611c51576040516397363b3560e01b815260040160405180910390fd5b600681602001516009811115611c6957611c696153b5565b03611ce357806040015161ffff16600003611c97576040516363daeb7760e01b815260040160405180910390fd5b611b42611ca782606001516117af565b85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061357092505050565b600781602001516009811115611cfb57611cfb6153b5565b14611d7d57600881602001516009811115611d1857611d186153b5565b03611d3257611b42611d2d826060015161101d565b613787565b600981602001516009811115611d4a57611d4a6153b5565b03611d6457611b42611d5f8260600151611387565b6137c4565b6040516397363b3560e01b815260040160405180910390fd5b50505050565b828114611da35760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b83811015611e3c57828282818110611dc057611dc0615820565b9050602002016020810190611dd591906159b9565b6001600160401b0316611e15868684818110611df357611df3615820565b90506020020135600090815260d560205260409020546001600160401b031690565b6001600160401b03161015611e3457611e2e8787612357565b50611e56565b600101611da6565b50604051636f162bfd60e11b815260040160405180910390fd5b505050505050565b611e66614ba5565b6000611e71836138d3565b80519091506001600160401b0316600003611e9f57604051630295d7cd60e31b815260040160405180910390fd5b91815260408083015160208084018051600793840b905260608087015182516001600160401b039182169085015283880180518451600391820b908901528951945194831694840194909452608089015187890180519190970b905260a0890151865190831695019490945292518451920b919094015293519051931692019190915290565b600080805b83811015612003576004858583818110611f4657611f46615820565b9050602002810190611f589190615836565b9050118015611f84575063504e4155611f7c86868481811061128e5761128e615820565b63ffffffff16145b1561135d57600080611fa18787858181106112ce576112ce615820565b90925090506000818015611fb757611fb76153b5565b14611fd55760405163734fff6760e11b815260040160405180910390fd5b611fea87878581811061132f5761132f615820565b611ff79060ff1685615775565b93505050600101611f2a565b5061137f81612ba1565b600061201860d65490565b8261202260ce5490565b61202d9060ff615967565b6120379190615967565b610bb59190615775565b600061199960cf5490565b60606002841461206f5760405163734fff6760e11b815260040160405180910390fd5b600061207b8686611244565b90508034101561209d5760405162976f7560e21b815260040160405180910390fd5b60608060006120cf898960008181106120b8576120b8615820565b90506020028101906120ca9190615836565b613957565b90945092506060915081905060006120f38b8b60018181106120b8576120b8615820565b8051875192965090945014915061211f905057604051630196224b60e41b815260040160405180910390fd5b60005b83518110156121855781818151811061213d5761213d615820565b602002602001015184828151811061215757612157615820565b60200260200101511461217d57604051630196224b60e41b815260040160405180910390fd5b600101612122565b50866001600160401b0381111561219e5761219e614e67565b6040519080825280602002602001820160405280156121d757816020015b6121c4614bd2565b8152602001906001900390816121bc5790505b50955060005b878110156122f55760008989838181106121f9576121f9615820565b9050602002013590506000600019905060005b8651811015612245578287828151811061222857612228615820565b60200260200101510361223d57809150612245565b60010161220c565b50600081126122eb57600081905061228f88828151811061226857612268615820565b602002602001015187838151811061228257612282615820565b6020026020010151613b1e565b6122cc838983815181106122a5576122a5615820565b60200260200101518884815181106122bf576122bf615820565b6020026020010151613c36565b8a85815181106122de576122de615820565b6020026020010181905250505b50506001016121dd565b5060005b878110156123495786818151811061231357612313615820565b6020026020010151600001516000801b03612341576040516345805f5d60e01b815260040160405180910390fd5b6001016122f9565b505050505050949350505050565b6000805b828110156123a65761238f84848381811061237857612378615820565b905060200281019061238a9190615836565b613d65565b61239c9060ff1683615775565b915060010161235b565b5060006123b282612ba1565b905080341015611d7d5760405162976f7560e21b815260040160405180910390fd5b6123dc612e66565b6001600160a01b0381166124415760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610a9e565b610c9d81612ec0565b600054610100900460ff166124715760405162461bcd60e51b8152600401610a9e906159d6565b611637613e3d565b600054610100900460ff166116375760405162461bcd60e51b8152600401610a9e906159d6565b6124a98a613e6d565b8786146124c95760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b8881101561260c57600060405180604001604052808c8c858181106124f3576124f3615820565b90506020020160208101906125089190615a21565b61ffff1681526020018a8a8581811061252357612523615820565b90506020020135815250905061254181600001518260200151610fa9565b1561255f5760405163a9cb9e0d60e01b815260040160405180910390fd5b600160cd600061256e846117e0565b81526020808201929092526040016000908120805460ff19169315159390931790925560cc8054600181810183559190935283517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebe6002909402938401805461ffff191661ffff9092169190911790559201517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebf90910155016124cc565b506040805180820190915261ffff86168082526020820186905260d0805461ffff1916909117905560d185905561264284613e8f565b5061264c8260cf55565b6126558160ce55565b50505050505050505050565b600061266e826008615775565b835110156126b55760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b6044820152606401610a9e565b50016008015190565b600080516020615f36833981519152546001600160a01b031690565b610c9d612e66565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561271a5761271583613eb2565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612774575060408051601f3d908101601f1916820190925261277191810190615a3e565b60015b6127d75760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610a9e565b600080516020615f3683398151915281146128465760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610a9e565b50612715838383613f4e565b600060048311158061286c5750833560e01c63504e415514155b1561288a5760405163734fff6760e11b815260040160405180910390fd5b6000806128978686612ab1565b909250905060008180156128ad576128ad6153b5565b146128cb5760405163734fff6760e11b815260040160405180910390fd5b5060408051606081018252600080825260208201819052918101919091523660006128f7888886613f73565b6001600160401b0316604089015260ff90921660208801526001600160601b031990921686529195509250905060005b836020015160ff1681101561294d57612943848484888b6140b3565b9450600101612927565b5083811461296e5760405163734fff6760e11b815260040160405180910390fd5b50506020015160ff1695945050505050565b600082815260d5602052604090205481516001600160401b03918216911681101561271557600083815260d560209081526040918290208451815486840151878601516060808a01516001600160401b039586166001600160601b03199095168517600160401b63ffffffff9095168502176fffffffffffffffffffffffffffffffff60601b1916600160601b8785160267ffffffffffffffff60a01b191617600160a01b91871691820217875560808b01516001909701805460a08d01519888166fffffffffffffffffffffffffffffffff19909116179790961690930295909517909355855191825260079290920b938101939093529282019290925284917fd06a6b7f4918494b3719217d1802786c1f5112a6c1d88fe2cfec00b4584f6aec910160405180910390a2505050565b60046000833560e01c63504e41558114612ade5760405163734fff6760e11b815260040160405180910390fd5b60018084019386013560f81c908114612b0a5760405163734fff6760e11b815260040160405180910390fd5b50508184016001013560f890811c9092016002818101939186010135901c60ff168015612b3957612b396153b5565b60019290920191905081831015612b635760405163734fff6760e11b815260040160405180910390fd5b9250929050565b60008382013560f01c612b7e600284615775565b9250612b8e61ffff821684615775565b92508483013560f81c5b95945050505050565b6000612bac60d65490565b60ce546120379084615967565b6000612bc6826014615775565b83511015612c0e5760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b6044820152606401610a9e565b500160200151600160601b900490565b6000612c2b826004615775565b83511015612c725760405162461bcd60e51b8152602060048201526014602482015273746f55696e7433325f6f75744f66426f756e647360601b6044820152606401610a9e565b50016004015190565b6000612c88826001615775565b83511015612cce5760405162461bcd60e51b8152602060048201526013602482015272746f55696e74385f6f75744f66426f756e647360681b6044820152606401610a9e565b50016001015190565b6000612ce4826002615775565b83511015612d2b5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b6044820152606401610a9e565b50016002015190565b606081612d4281601f615775565b1015612d815760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610a9e565b612d8b8284615775565b84511015612dcf5760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610a9e565b606082158015612dee5760405191506000825260208201604052612e38565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612e27578051835260209283019201612e0f565b5050858452601f01601f1916604052505b50949350505050565b600081831115612e5c57612e55828461597e565b9050610bb5565b612e55838361597e565b6033546001600160a01b031633146116375760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a9e565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000612f1f826020615775565b83511015612f675760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b6044820152606401610a9e565b50016020015190565b612f78614c08565b600080612f8d60c9546001600160a01b031690565b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b8152600401612fb89190615361565b600060405180830381865afa158015612fd5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612ffd9190810190615ba3565b50915091508061302057604051632acbe91560e01b815260040160405180910390fd5b61303282606001518360800151611221565b61304f5760405163360f2d8760e01b815260040160405180910390fd5b60d2546001600160401b03166001600160401b03168260a001516001600160401b031611613090576040516388d1b84760e01b815260040160405180910390fd5b61309d8260a00151613e8f565b5092915050565b610c9d816143cd565b60006130e16040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b90506000806130f860c9546001600160a01b031690565b845160405163607ec5ef60e11b81526001600160a01b03929092169163c0fd8bde9161312691600401615361565b600060405180830381865afa158015613143573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261316b9190810190615ba3565b50915091508061318e57604051632acbe91560e01b815260040160405180910390fd5b600061319d8360e00151611442565b90506131a7611924565b61ffff16816040015161ffff16141580156131c95750604081015161ffff1615155b156131e7576040516363daeb7760e01b815260040160405180910390fd5b6005816020015160098111156131ff576131ff6153b5565b1461321d576040516397363b3560e01b815260040160405180910390fd5b600061322c8260600151611639565b805190915063ffffffff1661324660d45463ffffffff1690565b63ffffffff161061326a576040516388d1b84760e01b815260040160405180910390fd5b805160d4805463ffffffff191663ffffffff90921691909117905560408051808201909152606085015161ffff1680825260808601516020830181905260d0805461ffff191690921790915560d1556132c68560a00151613e8f565b7f6bce23ef3d34e51710fe4700b43ba5f1733a6215c883f384671a4ece3ea8aa208661331a6040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b60d25460408051845161ffff90811682526020958601518683015284511691810191909152929091015160608301526001600160401b0316608082015260a0015b60405180910390a150505050505050565b600061337661199e565b905060005b81518110156133e057600060c960040160006133af8585815181106133a2576133a2615820565b60200260200101516117e0565b81526020810191909152604001600020805460ff19169115159190911790556133d9600182615775565b905061337b565b506133ed60cc6000614c63565b60005b82515181101561349c578251805160cc91908390811061341257613412615820565b60209081029190910181015182546001808201855560009485528385208351600290930201805461ffff191661ffff90931692909217825591909201519181019190915584518051919260cd92909161347591869081106133a2576133a2615820565b81526020810191909152604001600020805460ff19169115159190911790556001016133f0565b507fd451e0fcb7c5b9e13de533604d158069dad159841c45f39f09d379bfc423080d816134c761199e565b6040516134d5929190615d0b565b60405180910390a15050565b60006134ec60ce5490565b825160ce5590507f74dbbbe280ef27b79a8a0c449d5ae2ba7a31849103241d0f98df70bbc9d03e378161351e60ce5490565b604080519283526020830191909152016134d5565b600061353e60cf5490565b825160cf5590507fcdb88a22f82ddd76115ab7c66cf08eb1e40afe80c9b31017eb2cbdb1570b33ae8161351e60cf5490565b600061358460c9546001600160a01b031690565b90506135938360000151613e6d565b6000806135a860c9546001600160a01b031690565b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b81526004016135d39190615361565b600060405180830381865afa1580156135f0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526136189190810190615ba3565b50915091508061363b576040516397363b3560e01b815260040160405180910390fd5b61364d82606001518360800151611221565b61366a576040516397363b3560e01b815260040160405180910390fd5b60d2546001600160401b03166001600160401b03168260a001516001600160401b0316146136ab576040516309e9f6c160e11b815260040160405180910390fd5b60006136ba8360e00151611442565b90506006816020015160098111156136d4576136d46153b5565b146136f2576040516309e9f6c160e11b815260040160405180910390fd5b600061370182606001516117af565b875181519192506001600160a01b03918216911614613733576040516309e9f6c160e11b815260040160405180910390fd5b7fd495c4e5b386d59bccca38a2277b5d70a0f5e47d7b6587a45a6f5aca221a31258561376760c9546001600160a01b031690565b604080516001600160a01b0393841681529290911660208301520161335b565b600061379260d65490565b825160d65590507f5ac11e113c4b7116e6d04c95bd9f5ec9109fc1199331c882f5a0b63c9b33ac2b8161351e60d65490565b47816020015111156137e85760405162976f7560e21b815260040160405180910390fd5b805160208201516040516000926001600160a01b031691908381818185875af1925050503d8060008114613838576040519150601f19603f3d011682016040523d82523d6000602084013e61383d565b606091505b505090508061388e5760405162461bcd60e51b815260206004820152601760248201527f4661696c656420746f20776974686472617720666565730000000000000000006044820152606401610a9e565b8151602080840151604080516001600160a01b039094168452918301527f78473f3f373f7673597f4f0fa5873cb4d375fea6d4339ad6b56dbd411513cb3f91016134d5565b6138db614c84565b50600090815260d56020908152604091829020825160c08101845281546001600160401b038082168352600160401b80830460030b95840195909552600160601b8204600790810b96840196909652600160a01b909104811660608301526001909201549384900b60808201529190920490911660a082015290565b600060608060008060008036600061396f8b8b612ab1565b965094506000868015613984576139846153b5565b146139a25760405163734fff6760e11b815260040160405180910390fd5b6139ad8b8b87613f73565b509398509196509450925090508985106139da5760405163734fff6760e11b815260040160405180910390fd5b8260ff166001600160401b038111156139f5576139f5614e67565b604051908082528060200260200182016040528015613a2e57816020015b613a1b614cb9565b815260200190600190039081613a135790505b5097508260ff166001600160401b03811115613a4c57613a4c614e67565b604051908082528060200260200182016040528015613a75578160200160208202803683370190505b50965060005b8360ff16811015613aed57613a8e614cb9565b6000613a9c8786868b6144bc565b8d51929a50909350915082908c9085908110613aba57613aba615820565b6020026020010181905250808a8481518110613ad857613ad8615820565b60209081029190910101525050600101613a7b565b50848114613b0e5760405163076ef4a560e21b815260040160405180910390fd5b8498505050505050509250925092565b81608001516001600160401b03168260a001516001600160401b031610613b585760405163076ef4a560e21b815260040160405180910390fd5b80608001516001600160401b03168160a001516001600160401b031610613b925760405163076ef4a560e21b815260040160405180910390fd5b8060c0015160030b8260c0015160030b14613bc057604051630196224b60e41b815260040160405180910390fd5b80606001516001600160401b031682606001516001600160401b03161115613bfb57604051630196224b60e41b815260040160405180910390fd5b80608001516001600160401b031682608001516001600160401b0316111561116a57604051630196224b60e41b815260040160405180910390fd5b613c3e614bd2565b8381526080808401516001600160401b0390811660208401529083015116604082015260608084015190830151600091613c7791615d30565b84518451919250600091613c8b9190615d4f565b9050600085602001518560200151613ca39190615d85565b90506000613cba6001600160401b03851684615dba565b90506000613cd16001600160401b03861684615df8565b60608088018051600786900b905280516001600160401b0380851660209092019190915260c08c0151825160039190910b60409182015260808c015192519290911691909201528981015190890151919250600091613d309190615d30565b9050600086613d4283620f4240615e26565b613d4c9190615e48565b63ffffffff166080890152505050505050509392505050565b6000806000613d748585612ab1565b90925090506000818015613d8a57613d8a6153b5565b14613da85760405163734fff6760e11b815260040160405180910390fd5b60008036600080613dba8a8a89613f73565b929c50939850919650909450909250905060005b8860ff16811015613e0f57613de1614c84565b600080613df08888888c614518565b929b5090945092509050613e048284612980565b505050600101613dce565b50848214613e305760405163734fff6760e11b815260040160405180910390fd5b5050505050505092915050565b600054610100900460ff16613e645760405162461bcd60e51b8152600401610a9e906159d6565b61163733612ec0565b60c980546001600160a01b0319166001600160a01b0392909216919091179055565b60d2805467ffffffffffffffff19166001600160401b0392909216919091179055565b6001600160a01b0381163b613f1f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610a9e565b600080516020615f3683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b613f5783614578565b600082511180613f645750805b1561271557611d7d83836145b8565b60008080368180613f888989898082036146a3565b600297509093509150823560f01c60606000613fae613fa987878c876146a3565b6146cd565b60e0015160048082015161ffff86169b909b019a9193509150634155575663ffffffff821614613ff15760405163734fff6760e11b815260040160405180910390fd5b8183016001015160009060ff16801561400c5761400c6153b5565b60019093019290506000818015614025576140256153b5565b146140435760405163734fff6760e11b815260040160405180910390fd5b828401600801519550600c909201916140678484602091010151600160601b900490565b60601b995060148301925083518311156140945760405163734fff6760e11b815260040160405180910390fd5b5050600189019c979b505050509482013560f81c965090945092919050565b60006140bd614c84565b6000806140d08960000151898989614518565b9296509094509250905060005b8551518110156141145782866000015182815181106140fe576140fe615820565b60200260200101510315614114576001016140dd565b8551518110801561414457508560a00151818151811061413657614136615820565b602090810291909101015151155b156143c057835160208701516001600160401b0391821691168110801590614179575086604001516001600160401b03168111155b80156141a65750866060015115806141a65750826001600160401b031687602001516001600160401b0316115b156143be57838760a0015183815181106141c2576141c2615820565b602090810291909101015152604085015160a08801518051849081106141ea576141ea615820565b602090810291909101810151015160079190910b9052606085015160a088015180518490811061421c5761421c615820565b602002602001015160200151602001906001600160401b031690816001600160401b03168152505084602001518760a00151838151811061425f5761425f615820565b6020026020010151602001516040019060030b908160030b81525050808760a00151838151811061429257614292615820565b602002602001015160200151606001818152505084608001518760a0015183815181106142c1576142c1615820565b6020026020010151604001516000019060070b908160070b815250508460a001518760a0015183815181106142f8576142f8615820565b602002602001015160400151602001906001600160401b031690816001600160401b03168152505084602001518760a00151838151811061433b5761433b615820565b6020026020010151604001516040019060030b908160030b81525050808760a00151838151811061436e5761436e615820565b60200260200101516040015160600181815250508a604001518760c00151838151811061439d5761439d615820565b60200260200101906001600160401b031690816001600160401b0316815250505b505b5050505095945050505050565b60006143d76126be565b82519091506143e7906000610c6b565b306001600160a01b031663e3795cc16040518163ffffffff1660e01b8152600401602060405180830381865afa158015614425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144499190615e76565b63ffffffff166397a6f30414614472576040516397363b3560e01b815260040160405180910390fd5b7f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a498161449c6126be565b604080516001600160a01b039384168152929091166020830152016134d5565b60006144c6614cb9565b6000366000806144d88989898d6147b7565b98509194509250905060018160018111156144f5576144f56153b5565b0361135d576145068383600161489e565b90955093505050509450945094915050565b6000614522614c84565b600080366000806145358a8a8a8e6147b7565b9950919450925090506000816001811115614552576145526153b5565b0361135d576145638383600161493b565b91975095509350505050945094509450949050565b61458181613eb2565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6146205760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610a9e565b600080846001600160a01b03168460405161463b9190615e91565b600060405180830381855af49150503d8060008114614676576040519150601f19603f3d011682016040523d82523d6000602084013e61467b565b606091505b5091509150612b988282604051806060016040528060278152602001615f5660279139614a14565b3660008584866146b38683615775565b926146c093929190615ead565b9150915094509492505050565b6146d5614c08565b60006146e960c9546001600160a01b031690565b6001600160a01b031663c0fd8bde85856040518363ffffffff1660e01b8152600401614716929190615ed7565b600060405180830381865afa158015614733573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261475b9190810190615ba3565b5090925090508061477f57604051632acbe91560e01b815260040160405180910390fd5b5061479281606001518260800151610fa9565b610bb55760405163e60dce7160e01b815260040160405180910390fd5b016008015190565b36600080808786013560f01c6147ce600288615775565b96506147e08989898461ffff166146a3565b90955093506147f361ffff821688615775565b965060006148058a8a8a8a8a8a614a2d565b93509050806148275760405163734fff6760e11b815260040160405180910390fd5b853560f81c600181111561483d5761483d6153b5565b93506000846001811115614853576148536153b5565b1415801561487357506001846001811115614870576148706153b5565b14155b156148915760405163734fff6760e11b815260040160405180910390fd5b5050945094509450949050565b6148a6614cb9565b818401602081810135608090811d84526030830135811c9184019190915260408083013560c090811c918501919091526048830135811c6060808601919091526050840135821c928501929092526058830135811c60a08501529082013560e01d9083015260649092019135838311156149335760405163734fff6760e11b815260040160405180910390fd5b935093915050565b614943614c84565b60208483018181013560c090811d6040858101919091526028830135821c6060860152603083013560e01d85850152603483013590911c84528051601f8701849004840281018401909152858152603c909401939035916000916149c39188908890819084018382808284376000920191909152508892506147af915050565b868501600881013560c090811d6080870152601090910135901c60a0850152601890940193905084841115614a0b5760405163734fff6760e11b815260040160405180910390fd5b93509350939050565b60608315614a2357508161123d565b61123d8383614ad5565b6000806000614a7185858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250614aff92505050565b600188019790915089013560f81c60005b8160ff16811015614ab45760148901988b01356001600160601b031916614aa98482614b32565b935050600101614a82565b50506001600160601b03199081169516949094149794965093945050505050565b815115614ae55781518083602001fd5b8060405162461bcd60e51b8152600401610a9e9190615361565b6000610bb5600083604051602001614b18929190615f06565b604051602081830303815290604052805160209091012090565b60006001600160601b03198083169084161115614b4d579091905b604051600160f81b60208201526001600160601b031980851660218301528316603582015261123d90604901614b18565b60408051608081018252600080825260208201819052918101829052606081019190915290565b60408051606081019091526000815260208101614bc0614b7e565b8152602001614bcd614b7e565b905290565b6040805160a0810182526000808252602082018190529181019190915260608101614bfb614b7e565b8152600060209091015290565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201819052610100820183905261012082015261014081019190915290565b5080546000825560020290600052602060002090810190610c9d9190614cf5565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b5b80821115614d1657805461ffff1916815560006001820155600201614cf6565b5090565b80356001600160a01b0381168114614d3157600080fd5b919050565b60008083601f840112614d4857600080fd5b5081356001600160401b03811115614d5f57600080fd5b6020830191508360208260051b8501011115612b6357600080fd5b61ffff81168114610c9d57600080fd5b6001600160401b0381168114610c9d57600080fd5b6000806000806000806000806000806101008b8d031215614dbf57600080fd5b614dc88b614d1a565b995060208b01356001600160401b03811115614de357600080fd5b614def8d828e01614d36565b909a5098505060408b01356001600160401b03811115614e0e57600080fd5b614e1a8d828e01614d36565b90985096505060608b0135614e2e81614d7a565b945060808b0135935060a08b0135614e4581614d8a565b999c989b50969995989497939650919460c08101359360e09091013592509050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715614e9f57614e9f614e67565b60405290565b60405161016081016001600160401b0381118282101715614e9f57614e9f614e67565b604051601f8201601f191681016001600160401b0381118282101715614ef057614ef0614e67565b604052919050565b60006001600160401b03821115614f1157614f11614e67565b50601f01601f191660200190565b600082601f830112614f3057600080fd5b8135614f43614f3e82614ef8565b614ec8565b818152846020838601011115614f5857600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215614f8757600080fd5b81356001600160401b03811115614f9d57600080fd5b61137f84828501614f1f565b600060208284031215614fbb57600080fd5b5035919050565b805160070b82526001600160401b036020820151166020830152604081015160030b6040830152606081015160608301525050565b60808101610bb58284614fc2565b60006020828403121561501757600080fd5b61123d82614d1a565b8015158114610c9d57600080fd5b600080600080600080600080600060e08a8c03121561504c57600080fd5b89356001600160401b0381111561506257600080fd5b61506e8c828d01614d36565b909a5098505060208a01356001600160401b0381111561508d57600080fd5b6150998c828d01614d36565b90985096505060408a01356150ad81614d8a565b945060608a01356150bd81614d8a565b935060808a01356150cd81615020565b925060a08a01356150dd81615020565b915060c08a01356150ed81615020565b809150509295985092959850929598565b8051825260208101516151146020840182614fc2565b50604081015161271560a0840182614fc2565b600081518084526020840193506020830160005b828110156151655761514e8683516150fe565b61012095909501946020919091019060010161513b565b5093949350505050565b6040815260006151826040830185615127565b828103602084015280845180835260208301915060208601925060005b818110156151c65783516001600160401b031683526020938401939092019160010161519f565b50909695505050505050565b815161ffff1681526020808301519082015260408101610bb5565b6000806040838503121561520057600080fd5b823561520b81614d7a565b946020939093013593505050565b6000806000806000806080878903121561523257600080fd5b86356001600160401b0381111561524857600080fd5b61525489828a01614d36565b90975095505060208701356001600160401b0381111561527357600080fd5b61527f89828a01614d36565b909550935050604087013561529381614d8a565b915060608701356152a381614d8a565b809150509295509295509295565b60208152600061123d6020830184615127565b600080604083850312156152d757600080fd5b6152e083614d1a565b915060208301356001600160401b038111156152fb57600080fd5b61530785828601614f1f565b9150509250929050565b60005b8381101561532c578181015183820152602001615314565b50506000910152565b6000815180845261534d816020860160208601615311565b601f01601f19169290920160200192915050565b60208152600061123d6020830184615335565b6000806020838503121561538757600080fd5b82356001600160401b0381111561539d57600080fd5b6153a985828601614d36565b90969095509350505050565b634e487b7160e01b600052602160045260246000fd5b6020815260008251600481106153e3576153e36153b5565b806020840152506020830151600a81106153ff576153ff6153b5565b8060408401525061ffff6040840151166060830152606083015160808084015261137f60a0840182615335565b6000806040838503121561543f57600080fd5b50508035926020909101359150565b600081518084526020840193506020830160005b8281101561516557615483868351805161ffff168252602090810151910152565b6040959095019460209190910190600101615462565b602081526000825160208084015261137f604084018261544e565b600060408284031280156154c757600080fd5b50604080519081016001600160401b03811182821017156154ea576154ea614e67565b60405282356154f881614d7a565b81526020928301359281019290925250919050565b60208152600061123d602083018461544e565b6000806020838503121561553357600080fd5b82356001600160401b0381111561554957600080fd5b8301601f8101851361555a57600080fd5b80356001600160401b0381111561557057600080fd5b85602082840101111561558257600080fd5b6020919091019590945092505050565b600080600080600080606087890312156155ab57600080fd5b86356001600160401b038111156155c157600080fd5b6155cd89828a01614d36565b90975095505060208701356001600160401b038111156155ec57600080fd5b6155f889828a01614d36565b90955093505060408701356001600160401b0381111561561757600080fd5b61562389828a01614d36565b979a9699509497509295939492505050565b6101208101610bb582846150fe565b602081526000825160208084015261137f6040840182615335565b6000806000806040858703121561567557600080fd5b84356001600160401b0381111561568b57600080fd5b61569787828801614d36565b90955093505060208501356001600160401b038111156156b657600080fd5b6156c287828801614d36565b95989497509550505050565b602080825282518282018190526000918401906040840190835b81811015615754578351805184526001600160401b0360208201511660208501526001600160401b036040820151166040850152606081015161572e6060860182614fc2565b506080015163ffffffff1660e084015260209390930192610100909201916001016156e8565b509095945050505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610bb557610bb561575f565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261584d57600080fd5b8301803591506001600160401b0382111561586757600080fd5b602001915036819003821315612b6357600080fd5b6001815b60018411156149335780850481111561589b5761589b61575f565b60018416156158a957908102905b60019390931c928002615880565b6000826158c657506001610bb5565b816158d357506000610bb5565b81600181146158e957600281146158f35761590f565b6001915050610bb5565b60ff8411156159045761590461575f565b50506001821b610bb5565b5060208310610133831016604e8410600b8410161715615932575081810a610bb5565b61593f600019848461587c565b80600019048211156159535761595361575f565b029392505050565b600061123d83836158b7565b8082028115828204841417610bb557610bb561575f565b81810381811115610bb557610bb561575f565b8051614d3181614d7a565b6000602082840312156159ae57600080fd5b815161123d81614d7a565b6000602082840312156159cb57600080fd5b813561123d81614d8a565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215615a3357600080fd5b813561123d81614d7a565b600060208284031215615a5057600080fd5b5051919050565b805160ff81168114614d3157600080fd5b805163ffffffff81168114614d3157600080fd5b8051614d3181614d8a565b600082601f830112615a9857600080fd5b8151602083016000615aac614f3e84614ef8565b9050828152858383011115615ac057600080fd5b612b98836020830184615311565b600082601f830112615adf57600080fd5b81516001600160401b03811115615af857615af8614e67565b615b0760208260051b01614ec8565b8082825260208201915060208360071b860101925085831115615b2957600080fd5b602085015b83811015615b8e5760808188031215615b4657600080fd5b615b4e614e7d565b8151815260208083015190820152615b6860408301615a57565b6040820152615b7960608301615a57565b60608201528352602090920191608001615b2e565b5095945050505050565b8051614d3181615020565b600080600060608486031215615bb857600080fd5b83516001600160401b03811115615bce57600080fd5b84016101608187031215615be157600080fd5b615be9614ea5565b615bf282615a57565b8152615c0060208301615a68565b6020820152615c1160408301615a68565b6040820152615c2260608301615991565b606082015260808281015190820152615c3d60a08301615a7c565b60a0820152615c4e60c08301615a57565b60c082015260e08201516001600160401b03811115615c6c57600080fd5b615c7888828501615a87565b60e083015250615c8b6101008301615a68565b6101008201526101208201516001600160401b03811115615cab57600080fd5b615cb788828501615ace565b6101208301525061014091820151918101919091529250615cda60208501615b98565b915060408401516001600160401b03811115615cf557600080fd5b615d0186828701615a87565b9150509250925092565b604081526000615d1e604083018561544e565b8281036020840152612b98818561544e565b6001600160401b038281168282160390811115610bb557610bb561575f565b600f82810b9082900b0360016001607f1b031981126f7fffffffffffffffffffffffffffffff82131715610bb557610bb561575f565b6001600160801b038281168282160390811115610bb557610bb561575f565b634e487b7160e01b600052601260045260246000fd5b600081600f0b83600f0b80615dd157615dd1615da4565b60016001607f1b0319821460001982141615615def57615def61575f565b90059392505050565b60006001600160801b03831680615e1157615e11615da4565b806001600160801b0384160491505092915050565b6001600160401b03818116838216029081169081811461309d5761309d61575f565b60006001600160401b03831680615e6157615e61615da4565b806001600160401b0384160491505092915050565b600060208284031215615e8857600080fd5b61123d82615a68565b60008251615ea3818460208701615311565b9190910192915050565b60008085851115615ebd57600080fd5b83861115615eca57600080fd5b5050820193919092039150565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60ff60f81b8360f81b16815260008251615f27816001850160208701615311565b91909101600101939250505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212207614ca7dd4837854d002383e05473e986de5f533c5b55d8daa58016d90e4b49c64736f6c634300081d0033
Deployed Bytecode Sourcemap
488:2163:13:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;614:796;;;;;;;;;;-1:-1:-1;614:796:13;;;;;:::i;:::-;;:::i;:::-;;6563:359:9;;;;;;;;;;-1:-1:-1;6563:359:9;;;;;:::i;:::-;;:::i;:::-;;;4479:13:35;;4461:32;;4449:2;4434:18;6563:359:9;;;;;;;;1032:176:30;;;;;;;;;;-1:-1:-1;1032:176:30;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;3317:197:21:-;;;;;;;;;;-1:-1:-1;3317:197:21;;;;;:::i;:::-;;:::i;11352:3014:4:-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;2060:171:7:-;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;2190:34:7;;;;;;;;2197:27;2190:34;;;;;;;;;;;2060:171;;;;;;:::i;897:408::-;;;;;;;;;;-1:-1:-1;897:408:7;;;;;:::i;:::-;;:::i;:::-;;;9723:14:35;;9716:22;9698:41;;9686:2;9671:18;897:408:7;9558:187:35;14372:521:4;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2237:110:7:-;;;;;;;;;;-1:-1:-1;2313:27:7;;2237:110;;;11280:25:35;;;11268:2;11253:18;2237:110:7;11134:177:35;530:163:7;;;;;;;;;;-1:-1:-1;530:163:7;;;;;:::i;:::-;618:6;643:31;;;:22;:31;;;;;:43;-1:-1:-1;;;;;643:43:7;;530:163;;;;-1:-1:-1;;;;;11478:31:35;;;11460:50;;11448:2;11433:18;530:163:7;11316:200:35;6013:466:9;;;;;;;;;;-1:-1:-1;6013:466:9;;;;;:::i;:::-;;:::i;3763:222:21:-;;;;;;:::i;:::-;;:::i;3006:131::-;;;;;;;;;;;;;:::i;24368:94:4:-;;;;;;;;;;-1:-1:-1;24433:22:4;;;;;;;;;;;-1:-1:-1;;;24433:22:4;;;;24368:94;;;;24433:22;24368:94;:::i;1751:132:7:-;;;;;;;;;;-1:-1:-1;1839:37:7;;-1:-1:-1;;;;;1839:37:7;1751:132;;1311:336;;;;;;;;;;-1:-1:-1;1311:336:7;;;;;:::i;:::-;;:::i;4104:1139:4:-;;;;;;;;;;-1:-1:-1;4104:1139:4;;;;;:::i;:::-;;:::i;8042:564:9:-;;;;;;;;;;-1:-1:-1;8042:564:9;;;;;:::i;:::-;;:::i;:::-;;;;13801:13:35;;-1:-1:-1;;;;;13797:39:35;13779:58;;13893:4;13881:17;;;13875:24;13853:20;;;13846:54;;;;13752:18;8042:564:9;13561:345:35;2681:1080:9;;;;;;;;;;-1:-1:-1;2681:1080:9;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2473:122:7:-;;;;;;;;;;-1:-1:-1;2556:32:7;;;;2473:122;;;14963:10:35;14951:23;;;14933:42;;14921:2;14906:18;2473:122:7;14789:192:35;2285:320:30;;;;;;;;;;-1:-1:-1;2285:320:30;;;;;:::i;:::-;;:::i;2071:101:16:-;;;;;;;;;;;;;:::i;4680:443:9:-;;;;;;;;;;-1:-1:-1;4680:443:9;;;;;:::i;:::-;;:::i;:::-;;;15625:13:35;;15640:10;15621:30;15603:49;;15591:2;15576:18;4680:443:9;15337:321:35;239:102:7;;;;;;;;;;-1:-1:-1;318:6:7;:15;-1:-1:-1;;;;;318:15:7;239:102;;;-1:-1:-1;;;;;15845:32:35;;;15827:51;;15815:2;15800:18;239:102:7;15663:221:35;5207:730:9;;;;;;;;;;-1:-1:-1;5207:730:9;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;3846:364::-;;;;;;;;;;-1:-1:-1;3846:364:9;;;;;:::i;:::-;;:::i;:::-;;;16985:13:35;;-1:-1:-1;;;;;16981:39:35;16963:58;;16951:2;16936:18;3846:364:9;16737:290:35;699:192:7;;;;;;;;;;-1:-1:-1;699:192:7;;;;;:::i;:::-;;:::i;1441:85:16:-;;;;;;;;;;-1:-1:-1;1513:6:16;;-1:-1:-1;;;;;1513:6:16;1441:85;;7044:429:4;;;;;;;;;;-1:-1:-1;7044:429:4;;;;;:::i;:::-;;:::i;6357:420::-;;;;;;;;;;-1:-1:-1;6357:420:4;;;;;:::i;:::-;;:::i;2601:108:7:-;;;;;;;;;;-1:-1:-1;2676:26:7;;2601:108;;1653:92;;;;;;;;;;;;;:::i;:::-;;;18101:6:35;18089:19;;;18071:38;;18059:2;18044:18;1653:92:7;17927:188:35;1889:165:7;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;1725:314:30:-;;;;;;;;;;-1:-1:-1;1725:314:30;;;;;:::i;:::-;;:::i;21523:526:4:-;;;;;;:::i;:::-;;:::i;1303:182:30:-;;;;;;;;;;-1:-1:-1;1303:182:30;;;;;:::i;:::-;;:::i;24108:134:4:-;;;;;;;;;;-1:-1:-1;24108:134:4;;;;;:::i;:::-;24175:4;643:31:7;;;:22;:31;;;;;:43;-1:-1:-1;;;;;643:43:7;24199:35:4;;;24108:134;1943:2288:8;;;;;;;;;;-1:-1:-1;1943:2288:8;;;;;:::i;:::-;;:::i;5349:741:4:-;;;;;;:::i;:::-;;:::i;23343:759::-;;;;;;;;;;-1:-1:-1;23343:759:4;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2353:114:7:-;;;;;;;;;;-1:-1:-1;2431:29:7;;2353:114;;3105:993:4;;;;;;;;;;-1:-1:-1;3105:993:4;;;;;:::i;:::-;;:::i;4317:256:9:-;;;;;;;;;;-1:-1:-1;4317:256:9;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;4536:30:9;;;-1:-1:-1;4317:256:9;;;;;;;;:::i;2704:395:4:-;;;;;;;;;;-1:-1:-1;2704:395:4;;;;;:::i;:::-;;:::i;24248:114::-;;;;;;;;;;;;;:::i;1853:94:13:-;;;;;;;;;;-1:-1:-1;1930:10:13;1853:94;;17087:3377:4;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2113:502::-;;;;;;:::i;:::-;;:::i;2321:198:16:-;;;;;;;;;;-1:-1:-1;2321:198:16;;;;;:::i;:::-;;:::i;614:796:13:-;3268:19:20;3291:13;;;;;;3290:14;;3336:34;;;;-1:-1:-1;3354:12:20;;3369:1;3354:12;;;;:16;3336:34;3335:108;;;-1:-1:-1;3415:4:20;1476:19:22;:23;;;3376:66:20;;-1:-1:-1;3425:12:20;;;;;:17;3376:66;3314:201;;;;-1:-1:-1;;;3314:201:20;;23680:2:35;3314:201:20;;;23662:21:35;23719:2;23699:18;;;23692:30;23758:34;23738:18;;;23731:62;-1:-1:-1;;;23809:18:35;;;23802:44;23863:19;;3314:201:20;;;;;;;;;3525:12;:16;;-1:-1:-1;;3525:16:20;3540:1;3525:16;;;3551:65;;;;3585:13;:20;;-1:-1:-1;;3585:20:20;;;;;3551:65;1000:16:13::1;:14;:16::i;:::-;1026:24;:22;:24::i;:::-;1061:312;1091:8;1113:25;;1152:26;;1192:24;1230;1268:25;1307:22;1343:20;1061:16;:312::i;:::-;1384:19;:17;:19::i;:::-;3640:14:20::0;3636:99;;;3686:5;3670:21;;-1:-1:-1;;3670:21:20;;;3710:14;;-1:-1:-1;24045:36:35;;3710:14:20;;24033:2:35;24018:18;3710:14:20;;;;;;;3636:99;3258:483;614:796:13;;;;;;;;;;:::o;6563:359:9:-;-1:-1:-1;;;;;;;;;;;;6707:10:9;6761:30;:14;6707:10;6761:23;:30::i;:::-;-1:-1:-1;;;;;6753:39:9;6732:60;;6802:10;6811:1;6802:10;;:::i;:::-;;;6852:5;6827:14;:21;:30;6823:92;;6878:37;;-1:-1:-1;;;6878:37:9;;;;;;;;;;;6823:92;6697:225;6563:359;;;:::o;1032:176:30:-;1107:30;;:::i;:::-;1156:45;1176:2;1180:20;:18;:20::i;1156:45::-;1149:52;1032:176;-1:-1:-1;;1032:176:30:o;3317:197:21:-;-1:-1:-1;;;;;1898:6:21;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:21;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:21;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:21;;1963:87;;;;-1:-1:-1;;;1963:87:21;;;;;;;:::i;:::-;3400:36:::1;3418:17;3400;:36::i;:::-;3446:61;3468:17:::0;3497:1:::1;3487:12;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;-1:-1:-1;3487:12:21::1;;3501:5;3446:21;:61::i;:::-;3317:197:::0;:::o;11352:3014:4:-;11713:41;11768:21;11830:24;11843:10;;11830:12;:24::i;:::-;11818:9;:36;11814:89;;;11875:28;;-1:-1:-1;;;11875:28:4;;;;;;;;;;;11814:89;12052:460;;;;;;;;;;;;;;;;;;;;;11984:65;;12052:460;;12119:8;;;;;;12052:460;;;;12119:8;;12052:460;12119:8;12052:460;;;;;;;;;-1:-1:-1;;;12052:460:4;;;-1:-1:-1;;;;;;12052:460:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12427:8;;12399:44;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;12052:460:4;;;;12481:8;-1:-1:-1;;;;;12468:29:4;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;12468:29:4;-1:-1:-1;12052:460:4;;11984:528;-1:-1:-1;12584:30:4;;12801:215;12818:21;;;12801:215;;;12891:110;12941:10;;12952:1;12941:13;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;12976:7;12891:28;:110::i;:::-;12864:137;;;;12841:3;;12801:215;;;;13035:6;13030:730;13047:19;;;13030:730;;;13091:31;13125:7;:18;;;13144:1;13125:21;;;;;;;;:::i;:::-;;;;;;;13091:55;;13168:19;:33;;;;-1:-1:-1;13191:5:4;;:10;;13168:33;13164:582;;;13225:502;13279:8;;13288:1;13279:11;;;;;;;:::i;:::-;;;;;;;13316:389;;;;;;;;13396:2;:8;;;:20;;;-1:-1:-1;;;;;13316:389:4;;;;;13453:2;:8;;;:13;;;13316:389;;;;;;13503:2;:8;;;:14;;;13316:389;;;;;;13553:2;:8;;;:13;;;-1:-1:-1;;;;;13316:389:4;;;;;13606:2;:11;;;:17;;;13316:389;;;;;;13662:2;:11;;;:16;;;-1:-1:-1;;;;;13316:389:4;;;;13225:28;:502::i;:::-;-1:-1:-1;13068:3:4;;13030:730;;;;13891:24;:82;;;;-1:-1:-1;;;;;;13931:42:4;;;;;13891:82;13874:170;;;14005:28;;-1:-1:-1;;;14005:28:4;;;;;;;;;;;13874:170;14103:6;14098:183;14115:19;;;14098:183;;;14159:7;:18;;;14178:1;14159:21;;;;;;;;:::i;:::-;;;;;;;:24;;;14187:1;14159:29;;;14155:116;;14215:41;;-1:-1:-1;;;14215:41:4;;;;;;;;;;;14155:116;14136:3;;14098:183;;;;14325:7;:18;;;14345:7;:13;;;14317:42;;;;;;11352:3014;;;;;;;;;;;;:::o;897:408:7:-;1135:131;;;26031:3:35;26009:16;;;;-1:-1:-1;;;;;;26005:38:35;1135:131:7;;;;25993:51:35;;;;26060:11;;;;26053:27;;;;1135:131:7;;;;;;;;;;26096:12:35;;;;1135:131:7;;1104:180;;;;;;;;;-1:-1:-1;1062:236:7;;;:24;:236;;;;;;;;;897:408::o;14372:521:4:-;14612:41;14686:200;14731:10;;14755:8;;14777:14;14805;14833:5;14852;14871;14686:31;:200::i;:::-;-1:-1:-1;14669:217:4;14372:521;-1:-1:-1;;;;;;;14372:521:4:o;6013:466:9:-;-1:-1:-1;;;;;;;;;;;;6140:10:9;;6178:30;:14;6140:10;6178:23;:30::i;:::-;6165:43;-1:-1:-1;6218:10:9;6227:1;6218:10;;:::i;:::-;;-1:-1:-1;6239:11:9;6253:30;:14;6218:10;6253:23;:30::i;:::-;6239:44;-1:-1:-1;6293:10:9;6302:1;6293:10;;:::i;:::-;;-1:-1:-1;6341:28:9;-1:-1:-1;;;;;6356:13:9;;6349:2;6341:28;:::i;:::-;6326:43;;-1:-1:-1;;;;;6326:12:9;;:43;:::i;:::-;6314:55;;6384:21;;:30;;6380:92;;6435:37;;-1:-1:-1;;;6435:37:9;;;;;;;;;;;6380:92;6130:349;;;6013:466;;;:::o;3763:222:21:-;-1:-1:-1;;;;;1898:6:21;1881:23;1889:4;1881:23;1873:80;;;;-1:-1:-1;;;1873:80:21;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:21;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:21;;1963:87;;;;-1:-1:-1;;;1963:87:21;;;;;;;:::i;:::-;3880:36:::1;3898:17;3880;:36::i;:::-;3926:52;3948:17;3967:4;3973;3926:21;:52::i;:::-;3763:222:::0;;:::o;3006:131::-;3084:7;2324:4;-1:-1:-1;;;;;2333:6:21;2316:23;;2308:92;;;;-1:-1:-1;;;2308:92:21;;27917:2:35;2308:92:21;;;27899:21:35;27956:2;27936:18;;;27929:30;27995:34;27975:18;;;27968:62;28066:26;28046:18;;;28039:54;28110:19;;2308:92:21;27715:420:35;2308:92:21;-1:-1:-1;;;;;;;;;;;;3006:131:21;:::o;1311:336:7:-;1486:27;:35;1451:4;;1486:56;;;;:35;;:56;:154;;;;-1:-1:-1;1558:42:7;;:82;;1486:154;1467:173;1311:336;-1:-1:-1;;;1311:336:7:o;4104:1139:4:-;4203:14;;4585:1;4562:10;;4203:14;4562:13;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:20;;:24;:122;;;;-1:-1:-1;595:10:5;4602:49:4;4634:10;;4645:1;4634:13;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;-1:-1:-1;1954:40:3;1949:3;1945:50;;1764:273;4602:49:4;:82;;;4562:122;4545:646;;;4727:11;4756:21;4794:53;4833:10;;4844:1;4833:13;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;4794:38;:53::i;:::-;4709:138;;-1:-1:-1;4709:138:4;-1:-1:-1;4879:25:4;4865:10;:39;;;;;;:::i;:::-;;4861:115;;4931:30;;-1:-1:-1;;;4931:30:4;;;;;;;;;;;4861:115;5008:104;5061:10;;5072:1;5061:13;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;5092:6;5008:35;:104::i;:::-;4989:123;;;;;;:::i;:::-;;;4695:428;;4545:646;;;5150:30;;-1:-1:-1;;;5150:30:4;;;;;;;;;;;4545:646;5208:28;5220:15;5208:11;:28::i;:::-;5201:35;4104:1139;-1:-1:-1;;;;4104:1139:4:o;8042:564:9:-;-1:-1:-1;;;;;;;;;;;;;;;;;8179:10:9;8231:31;:14;8179:10;8231:24;:31::i;:::-;-1:-1:-1;;;;;8204:59:9;;;8273:11;8282:2;8273:11;;:::i;:::-;;-1:-1:-1;8295:10:9;8308:30;:14;8273:11;8308:23;:30::i;:::-;8295:43;-1:-1:-1;8348:10:9;8357:1;8348:10;;:::i;:::-;;-1:-1:-1;8369:11:9;8383:30;:14;8348:10;8383:23;:30::i;:::-;8369:44;-1:-1:-1;8423:10:9;8432:1;8423:10;;:::i;:::-;;-1:-1:-1;8468:28:9;-1:-1:-1;;;;;8483:13:9;;8476:2;8468:28;:::i;:::-;8453:43;;-1:-1:-1;;;;;8453:12:9;;:43;:::i;:::-;8444:6;;;:52;8511:21;;:30;;8507:92;;8562:37;;-1:-1:-1;;;8562:37:9;;;;;;;;;;;2681:1080;2785:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2785:31:9;2828:10;;2868:34;:18;2828:10;2868:27;:34::i;:::-;2853:49;-1:-1:-1;2917:14:9;;;535:10;2917:14;2913:64;;2940:37;;-1:-1:-1;;;2940:37:9;;;;;;;;;;;2913:64;2988:10;2997:1;2988:10;;:::i;:::-;;-1:-1:-1;3009:15:9;3027:33;:18;2988:10;3027:26;:33::i;:::-;3009:51;;3099:9;3082:27;;;;;;;;;;:::i;:::-;3070:2;;:39;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;3119:10:9;3128:1;3119:10;;:::i;:::-;;-1:-1:-1;823:23:9;3144:9;;:19;;;;;;;;:::i;:::-;;3140:68;;3172:36;;-1:-1:-1;;;3172:36:9;;;;;;;;;;;3140:68;3219:18;3240:33;:18;3267:5;3240:26;:33::i;:::-;3219:54;;3312:12;3295:30;;;;;;;;;;:::i;:::-;3283:2;:9;;:42;;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;3335:10:9;3344:1;3335:10;;:::i;:::-;;-1:-1:-1;3375:34:9;:18;3335:10;3375:27;:34::i;:::-;3356:53;;:16;;;:53;3419:10;3428:1;3419:10;;:::i;:::-;;;3654:100;3692:5;3739;3711:18;:25;:33;;;;:::i;:::-;3654:18;;:100;:24;:100::i;:::-;3641:10;;;:113;-1:-1:-1;3641:2:9;;2681:1080;-1:-1:-1;;;;2681:1080:9:o;2285:320:30:-;2399:30;;:::i;:::-;2449:21;2467:2;2449:17;:21::i;:::-;2441:29;;2528:3;2485:40;2490:15;2507:5;:17;;;2485:4;:40::i;:::-;:46;2481:94;;;2552:23;;-1:-1:-1;;;2552:23:30;;;;;;;;;;;2071:101:16;1334:13;:11;:13::i;:::-;2135:30:::1;2162:1;2135:18;:30::i;:::-;2071:101::o:0;4680:443:9:-;-1:-1:-1;;;;;;;;;;;;4900:10:9;4963:30;:14;4900:10;4963:23;:30::i;:::-;4925:68;;;;5003:10;5012:1;5003:10;;:::i;5207:730::-;-1:-1:-1;;;;;;;;;;;;5351:10:9;;5402:29;:14;5351:10;5402:22;:29::i;:::-;5376:55;-1:-1:-1;5441:10:9;5450:1;5441:10;;:::i;:::-;;;5530:17;5480:77;;-1:-1:-1;;;;;5480:77:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;5480:77:9;;;;;;;;;;;;;;;-1:-1:-1;5462:95:9;;:15;5568:260;5589:17;5585:21;;:1;:21;5568:260;;;5656:30;:14;5680:5;5656:23;:30::i;:::-;5627:15;;:18;;5643:1;;5627:18;;;;;;:::i;:::-;;;;;;;;;;;:59;;;;;;5700:10;5709:1;5700:10;;:::i;:::-;;-1:-1:-1;5761:31:9;:14;5700:10;5761:24;:31::i;:::-;5725:15;;:18;;5741:1;;5725:18;;;;;;:::i;:::-;;;;;;;:33;;:67;;;;;5815:2;5806:11;;;;;:::i;:::-;;-1:-1:-1;5608:3:9;;5568:260;;;;5867:5;5842:14;:21;:30;5838:92;;5893:37;;-1:-1:-1;;;5893:37:9;;;;;;;;;;;5838:92;5341:596;;5207:730;;;:::o;3846:364::-;-1:-1:-1;;;;;;;;;;;;3991:10:9;4047:31;:14;3991:10;4047:24;:31::i;:::-;-1:-1:-1;;;;;4016:63:9;;;4089:11;4098:2;4089:11;;:::i;699:192:7:-;800:7;853:2;:10;;;865:2;:17;;;836:47;;;;;;;;26031:3:35;26009:16;;;;-1:-1:-1;;;;;;26005:38:35;25993:51;;26069:1;26060:11;;26053:27;26105:2;26096:12;;25838:276;836:47:7;;;;;;;;;;;;;826:58;;;;;;819:65;;699:192;;;:::o;7044:429:4:-;7127:30;;:::i;:::-;7169:42;7214:26;;;:22;:26;;;;;;;;7270:16;;-1:-1:-1;;;;;7270:16:4;;;7250:17;;;:36;;;-1:-1:-1;;;7309:9:4;;;;;;7296:10;;;:22;;;;7270:16;7342:13;;;;;;;7328:27;;7378:12;;;;;7365:10;;;:25;;;;7214:26;;7405:22;7401:65;;7436:30;;-1:-1:-1;;;7436:30:4;;;;;;;;;;;6357:420;6437:30;;:::i;:::-;6479:42;6524:26;;;:22;:26;;;;;;;;6580:16;;-1:-1:-1;;;;;6580:16:4;;;6560:17;;;:36;;;-1:-1:-1;;;6619:9:4;;;;6606:10;;;:22;;;;-1:-1:-1;;;6652:10:4;;;;6638:24;;-1:-1:-1;;;6685:9:4;;;;6672:10;;;:22;;;;6524:26;;6709:22;6705:65;;6740:30;;-1:-1:-1;;;6740:30:4;;;;;;;;;;;1653:92:7;1693:6;1718:10;318:6;:15;-1:-1:-1;;;;;318:15:7;;239:102;1718:10;-1:-1:-1;;;;;1718:18:7;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1711:27;;1653:92;:::o;1889:165::-;1962:39;2024:6;:23;;2017:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1889:165;:::o;1725:314:30:-;1836:30;;:::i;:::-;1886:18;1901:2;1886:14;:18::i;21523:526:4:-;21769:41;21843:199;21888:10;;21912:8;;21934:14;21962;21990:4;22008:5;22027;21843:31;:199::i;1303:182:30:-;1381:30;;:::i;:::-;1430:48;1453:2;1457:20;:18;:20::i;1943:2288:8:-;2024:22;2049:29;2068:9;;2049:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2049:18:8;;-1:-1:-1;;;2049:29:8:i;:::-;2024:54;;2089:31;2123:60;2163:2;:10;;;2123:26;:60::i;:::-;2089:94;;2218:9;:7;:9::i;:::-;2198:29;;:2;:16;;;:29;;;;:54;;;;-1:-1:-1;2231:16:8;;;;:21;;;;2198:54;2194:115;;;2273:36;;-1:-1:-1;;;2273:36:8;;;;;;;;;;;2194:115;2337:32;2324:2;:9;;;:45;;;;;;;;:::i;:::-;;2320:1905;;2389:2;:16;;;:21;;2409:1;2389:21;2385:86;;2435:36;;-1:-1:-1;;;2435:36:8;;;;;;;;;;;2385:86;2485:56;2501:39;2529:2;:10;;;2501:27;:39::i;:::-;2485:15;:56::i;:::-;2320:1905;;;2588:54;2575:2;:9;;;:67;;;;;;;;:::i;:::-;;2558:1667;;2667:130;2722:61;2772:2;:10;;;-1:-1:-1;;;;;;;;;4536:30:9;;;-1:-1:-1;4317:256:9;2722:61:8;2667:37;:130::i;2558:1667::-;2831:31;2818:2;:9;;;:44;;;;;;;;:::i;:::-;;2814:1411;;2878:54;2893:38;2920:2;:10;;;2893:26;:38::i;:::-;2878:14;:54::i;2814:1411::-;2966:23;2953:2;:9;;;:36;;;;;;;;:::i;:::-;;2949:1276;;3005:38;3012:30;3031:2;:10;;;3012:18;:30::i;:::-;3005:6;:38::i;2949:1276::-;3077:31;3064:2;:9;;;:44;;;;;;;;:::i;:::-;;3060:1165;;3124:54;3139:38;3166:2;:10;;;3139:26;:38::i;:::-;3124:14;:54::i;3060:1165::-;3225:52;3212:2;:9;;;:65;;;;;;;;:::i;:::-;;3195:1030;;3426:37;;-1:-1:-1;;;3426:37:8;;;;;;;;;;;3195:1030;3497:35;3484:2;:9;;;:48;;;;;;;;:::i;:::-;;3480:745;;3552:2;:16;;;:21;;3572:1;3552:21;3548:86;;3598:36;;-1:-1:-1;;;3598:36:8;;;;;;;;;;;3548:86;3648:119;3684:42;3715:2;:10;;;3684:30;:42::i;:::-;3744:9;;3648:119;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3648:18:8;;-1:-1:-1;;;3648:119:8:i;3480:745::-;3801:30;3788:2;:9;;;:43;;;;;;;;:::i;:::-;3784:441;;;3903:34;3890:2;:9;;;:47;;;;;;;;:::i;:::-;;3886:339;;3953:60;3971:41;4001:2;:10;;;3971:29;:41::i;:::-;3953:17;:60::i;3886:339::-;4047:28;4034:2;:9;;;:41;;;;;;;;:::i;:::-;;4030:195;;4091:48;4103:35;4127:2;:10;;;4103:23;:35::i;:::-;4091:11;:48::i;4030:195::-;4177:37;;-1:-1:-1;;;4177:37:8;;;;;;;;;;;4030:195;2014:2217;;1943:2288;;:::o;5349:741:4:-;5546:38;;;5542:91;;5605:28;;-1:-1:-1;;;5605:28:4;;;;;;;;;;;5542:91;5649:6;5644:396;5661:19;;;5644:396;;;5868:12;;5881:1;5868:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;5826:57:4;:39;5853:8;;5862:1;5853:11;;;;;;;:::i;:::-;;;;;;;618:6:7;643:31;;;:22;:31;;;;;:43;-1:-1:-1;;;;;643:43:7;;530:163;5826:39:4;-1:-1:-1;;;;;5826:57:4;;5822:148;;;5903:28;5920:10;;5903:16;:28::i;:::-;5949:7;;;5822:148;6012:3;;5644:396;;;;6057:26;;-1:-1:-1;;;6057:26:4;;;;;;;;;;;5349:741;;;;;;;:::o;23343:759::-;23423:38;;:::i;:::-;23531:41;23575:19;23591:2;23575:15;:19::i;:::-;23608:16;;23531:63;;-1:-1:-1;;;;;;23608:21:4;:16;:21;23604:64;;23638:30;;-1:-1:-1;;;23638:30:4;;;;;;;;;;;23604:64;23679:17;;;23730:10;;;;;23706:15;;;;;;:34;;;;;;23773:9;;;;;23750:15;;-1:-1:-1;;;;;23750:32:4;;;:20;;;:32;23815:9;;;;;23792:15;;:32;;;;:20;;;:32;23869:16;;23834:15;;23864:22;;;23834:27;;;:52;;;;23924:13;;;;23897:18;;;;;:40;;;;;;23973:12;;;;23947:18;;:38;;;:23;;:38;;;;24021:9;;23995:18;;:35;;:23;;;;:35;24078:16;;24040:18;;24073:22;;24040:30;;:55;;;;23679:9;23343:759::o;3105:993::-;3200:14;;;3260:787;3277:21;;;3260:787;;;3363:1;3340:10;;3351:1;3340:13;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:20;;:24;:130;;;;-1:-1:-1;595:10:5;3384:49:4;3416:10;;3427:1;3416:13;;;;;;;:::i;3384:49::-;:86;;;3340:130;3319:718;;;3525:11;3558:21;3600:53;3639:10;;3650:1;3639:13;;;;;;;:::i;3600:53::-;3503:150;;-1:-1:-1;3503:150:4;-1:-1:-1;3689:25:4;3675:10;:39;;;;;;:::i;:::-;;3671:123;;3745:30;;-1:-1:-1;;;3745:30:4;;;;;;;;;;;3671:123;3830:116;3887:10;;3898:1;3887:13;;;;;;;:::i;3830:116::-;3811:135;;;;;;:::i;:::-;;;3485:476;;3300:3;;3260:787;;;;4063:28;4075:15;4063:11;:28::i;2704:395::-;2782:14;3071:21;2676:26:7;;;2601:108;3071:21:4;3042:14;3005:22;2313:27:7;;;2237:110;3005:22:4;2987:40;;:3;:40;:::i;:::-;:69;;;;:::i;:::-;:105;;;;:::i;24248:114::-;24308:4;24331:24;2431:29:7;;;2353:114;17087:3377:4;17269:49;17453:1;17432:22;;17428:90;;17477:30;;-1:-1:-1;;;17477:30:4;;;;;;;;;;;17428:90;17528:16;17547:28;17564:10;;17547:16;:28::i;:::-;17528:47;;17601:11;17589:9;:23;17585:64;;;17621:28;;-1:-1:-1;;;17621:28:4;;;;;;;;;;;17585:64;17697:54;17761:30;17815:16;17959:36;17981:10;;17992:1;17981:13;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;17959:21;:36::i;:::-;17845:150;;-1:-1:-1;17845:150:4;-1:-1:-1;18051:52:4;;-1:-1:-1;18051:52:4;;-1:-1:-1;18165:14:4;18239:66;18278:10;;18289:1;18278:13;;;;;;;:::i;18239:66::-;18441:18;;18417:20;;18193:112;;-1:-1:-1;18193:112:4;;-1:-1:-1;18417:42:4;;-1:-1:-1;18413:117:4;;-1:-1:-1;18413:117:4;18482:37;;-1:-1:-1;;;18482:37:4;;;;;;;;;;;18413:117;18720:6;18715:189;18736:13;:20;18732:1;:24;18715:189;;;18801:11;18813:1;18801:14;;;;;;;;:::i;:::-;;;;;;;18781:13;18795:1;18781:16;;;;;;;;:::i;:::-;;;;;;;:34;18777:117;;18842:37;;-1:-1:-1;;;18842:37:4;;;;;;;;;;;18777:117;18758:3;;18715:189;;;-1:-1:-1;19002:8:4;-1:-1:-1;;;;;18970:48:4;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;18953:65;;19114:6;19109:1107;19126:19;;;19109:1107;;;19166:24;19193:8;;19202:1;19193:11;;;;;;;:::i;:::-;;;;;;;19166:38;;19218:12;-1:-1:-1;;19218:17:4;;19419:6;19414:207;19435:13;:20;19431:1;:24;19414:207;;;19504:16;19484:13;19498:1;19484:16;;;;;;;;:::i;:::-;;;;;;;:36;19480:127;;19559:1;19544:17;;19583:5;;19480:127;19457:3;;19414:207;;;;19691:1;19679:8;:13;19675:531;;19712:8;19728;19712:25;;19807:129;19850:19;19870:3;19850:24;;;;;;;;:::i;:::-;;;;;;;19896:17;19914:3;19896:22;;;;;;;;:::i;:::-;;;;;;;19807:21;:129::i;:::-;20032:159;20067:16;20105:19;20125:3;20105:24;;;;;;;;:::i;:::-;;;;;;;20151:17;20169:3;20151:22;;;;;;;;:::i;:::-;;;;;;;20032:13;:159::i;:::-;20012:14;20027:1;20012:17;;;;;;;;:::i;:::-;;;;;;:179;;;;19694:512;19675:531;-1:-1:-1;;19147:3:4;;19109:1107;;;;20284:6;20279:179;20296:19;;;20279:179;;;20340:14;20355:1;20340:17;;;;;;;;:::i;:::-;;;;;;;:20;;;20364:1;20340:25;;;20336:112;;20392:41;;-1:-1:-1;;;20392:41:4;;;;;;;;;;;20336:112;20317:3;;20279:179;;;;17324:3140;;;;;17087:3377;;;;;;:::o;2113:502::-;2216:20;2255:6;2250:228;2267:21;;;2250:228;;;2325:82;2380:10;;2391:1;2380:13;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;2325:37;:82::i;:::-;2306:101;;;;;;:::i;:::-;;-1:-1:-1;2450:3:4;;2250:228;;;;2487:16;2506:28;2518:15;2506:11;:28::i;:::-;2487:47;;2560:11;2548:9;:23;2544:64;;;2580:28;;-1:-1:-1;;;2580:28:4;;;;;;;;;;;2321:198:16;1334:13;:11;:13::i;:::-;-1:-1:-1;;;;;2409:22:16;::::1;2401:73;;;::::0;-1:-1:-1;;;2401:73:16;;29120:2:35;2401:73:16::1;::::0;::::1;29102:21:35::0;29159:2;29139:18;;;29132:30;29198:34;29178:18;;;29171:62;-1:-1:-1;;;29249:18:35;;;29242:36;29295:19;;2401:73:16::1;28918:402:35::0;2401:73:16::1;2484:28;2503:8;2484:18;:28::i;1003:95::-:0;5363:13:20;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:20;;;;;;;:::i;:::-;1065:26:16::1;:24;:26::i;1042:67:21:-:0;5363:13:20;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:20;;;;;;;:::i;514:1593:4:-;891:21;903:8;891:11;:21::i;:::-;940:81;;;923:144;;1039:28;;-1:-1:-1;;;1039:28:4;;;;;;;;;;;923:144;1083:6;1078:538;1095:36;;;1078:538;;;1152:40;1195:166;;;;;;;;1264:25;;1290:1;1264:28;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;1195:166;;;;;;1314:26;;1341:1;1314:29;;;;;;;:::i;:::-;;;;;;;1195:166;;;1152:209;;1380:60;1410:2;:10;;;1422:2;:17;;;1380:29;:60::i;:::-;1376:117;;;1465:28;;-1:-1:-1;;;1465:28:4;;;;;;;;;;;1376:117;1555:4;1508:24;:44;1533:18;1548:2;1533:14;:18::i;:::-;1508:44;;;;;;;;;;;;-1:-1:-1;1508:44:4;;;:51;;-1:-1:-1;;1508:51:4;;;;;;;;;;;1573:23;:32;;-1:-1:-1;1573:32:4;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1573:32:4;;;;;;;;;;;;;;;;;;;1133:3;1078:538;;;-1:-1:-1;1683:99:4;;;;;;;;;;;;;;;;;;;;;1194:27:11;:43;;-1:-1:-1;;1194:43:11;;;;;;;;;;1849:102:4;1912:25;1849:45;:102::i;:::-;1626:336;1972:61;2010:22;1008:29:11;:54;925:144;1972:61:4;2043:57;2079:20;879:27:11;:33;817:102;2043:57:4;514:1593;;;;;;;;;;:::o;13973:327:1:-;14073:6;14116:10;:6;14125:1;14116:10;:::i;:::-;14099:6;:13;:27;;14091:60;;;;-1:-1:-1;;;14091:60:1;;30189:2:35;14091:60:1;;;30171:21:35;30228:2;30208:18;;;30201:30;-1:-1:-1;;;30247:18:35;;;30240:50;30307:18;;14091:60:1;29987:344:35;14091:60:1;-1:-1:-1;14228:29:1;14244:3;14228:29;14222:36;;13973:327::o;1563:151:18:-;-1:-1:-1;;;;;;;;;;;1642:65:18;-1:-1:-1;;;;;1642:65:18;;1563:151::o;1781:66:13:-;1334:13:16;:11;:13::i;2938:974:18:-;951:66;3384:59;;;3380:526;;;3459:37;3478:17;3459:18;:37::i;:::-;2938:974;;;:::o;3380:526::-;3560:17;-1:-1:-1;;;;;3531:61:18;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3531:63:18;;;;;;;;-1:-1:-1;;3531:63:18;;;;;;;;;;;;:::i;:::-;;;3527:302;;3758:56;;-1:-1:-1;;;3758:56:18;;30773:2:35;3758:56:18;;;30755:21:35;30812:2;30792:18;;;30785:30;30851:34;30831:18;;;30824:62;-1:-1:-1;;;30902:18:35;;;30895:44;30956:19;;3758:56:18;30571:410:35;3527:302:18;-1:-1:-1;;;;;;;;;;;3644:28:18;;3636:82;;;;-1:-1:-1;;;3636:82:18;;31188:2:35;3636:82:18;;;31170:21:35;31227:2;31207:18;;;31200:30;31266:34;31246:18;;;31239:62;-1:-1:-1;;;31317:18:35;;;31310:39;31366:19;;3636:82:18;30986:405:35;3636:82:18;3595:138;3842:53;3860:17;3879:4;3885:9;3842:17;:53::i;9595:1751:4:-;9766:17;9886:1;9859:28;;;;:129;;-1:-1:-1;1954:40:3;;1949:3;1945:50;595:10:5;9903:85:4;;9859:129;9842:219;;;10020:30;;-1:-1:-1;;;10020:30:4;;;;;;;;;;;9842:219;10071:11;10106:21;10164:86;10220:16;;10164:38;:86::i;:::-;10141:109;;-1:-1:-1;10141:109:4;-1:-1:-1;10283:25:4;10269:10;:39;;;;;;:::i;:::-;;10265:115;;10335:30;;-1:-1:-1;;;10335:30:4;;;;;;;;;;;10265:115;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;10489:22:4;;10670:144;10768:16;;10798:6;10670:84;:144::i;:::-;-1:-1:-1;;;;;10521:293:4;10642:15;;;10521:293;;;;;10586:21;;;10521:293;-1:-1:-1;;;;;;10521:293:4;;;;;;;-1:-1:-1;10521:293:4;-1:-1:-1;10521:293:4;-1:-1:-1;10555:17:4;10880:223;10901:10;:21;;;10897:25;;:1;:25;10880:223;;;10952:140;10994:10;11022:7;;11047:6;11071:7;10952:24;:140::i;:::-;10943:149;-1:-1:-1;10924:3:4;;10880:223;;;-1:-1:-1;11147:24:4;;;11143:92;;11194:30;;-1:-1:-1;;;11194:30:4;;;;;;;;;;;11143:92;-1:-1:-1;;11318:21:4;;;11311:28;;;9595:1751;-1:-1:-1;;;;;9595:1751:4:o;319:492:11:-;458:24;485:31;;;:22;:31;;;;;:43;542:16;;-1:-1:-1;;;;;485:43:11;;;;542:36;;-1:-1:-1;538:267:11;;;594:31;;;;:22;:31;;;;;;;;;:38;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;594:38:11;;;-1:-1:-1;;;;;;594:38:11;;;;;-1:-1:-1;;;594:38:11;;;;;;;-1:-1:-1;;;;594:38:11;-1:-1:-1;;;594:38:11;;;;-1:-1:-1;;;;594:38:11;;-1:-1:-1;;;594:38:11;;;;;;;;;;;;;-1:-1:-1;594:38:11;;;;;;;;;;;;-1:-1:-1;;594:38:11;;;;;;;;;;;;;;;;;;651:143;;31590:50:35;;;31687:1;31676:21;;;;31656:18;;;31649:49;;;;31714:18;;;31707:59;;;;594:31:11;;651:143;;31563:18:35;651:143:11;;;;;;;448:363;319:492;;:::o;1558:2361:5:-;1949:1;1677:11;1954:40:3;;1949:3;1945:50;595:10:5;1973:26;;1969:89;;2028:30;;-1:-1:-1;;;2028:30:5;;;;;;;;;;;1969:89;2242:1;2232:11;;;;1409:26:3;;1396:40;1391:3;1387:50;;2266:29:5;;2262:92;;2324:30;;-1:-1:-1;;;2324:30:5;;;;;;;;;;;2262:92;-1:-1:-1;;1409:26:3;;;2538:1:5;1409:26:3;1396:40;1391:3;1387:50;;;3600:28:5;;;;;;;;1409:26:3;;;;1396:40;1387:50;;3670:99:5;;;;;;;;:::i;:::-;3794:1;3784:11;;;;;3657:112;-1:-1:-1;3814:33:5;;;3810:92;;;3872:30;;-1:-1:-1;;;3872:30:5;;;;;;;;;;;3810:92;1558:2361;;;;;:::o;6973:460::-;7113:16;1688:26:3;;;1675:40;1670:3;1666:50;7267:11:5;7277:1;1688:26:3;7267:11:5;:::i;:::-;;-1:-1:-1;7288:21:5;;;;7267:11;7288:21;:::i;:::-;;-1:-1:-1;1409:26:3;;;1396:40;1391:3;1387:50;7332:94:5;7319:107;6973:460;-1:-1:-1;;;;;6973:460:5:o;22055:199:4:-;22134:16;22226:21;2676:26:7;;;2601:108;22226:21:4;2313:27:7;;22182:40:4;;:15;:40;:::i;12550:422:1:-;12651:7;12695:11;:6;12704:2;12695:11;:::i;:::-;12678:6;:13;:28;;12670:62;;;;-1:-1:-1;;;12670:62:1;;31979:2:35;12670:62:1;;;31961:21:35;32018:2;31998:18;;;31991:30;-1:-1:-1;;;32037:18:35;;;32030:51;32098:18;;12670:62:1;31777:345:35;12670:62:1;-1:-1:-1;12837:30:1;12853:4;12837:30;12831:37;-1:-1:-1;;;12810:117:1;;;12550:422::o;13640:327::-;13740:6;13783:10;:6;13792:1;13783:10;:::i;:::-;13766:6;:13;:27;;13758:60;;;;-1:-1:-1;;;13758:60:1;;32329:2:35;13758:60:1;;;32311:21:35;32368:2;32348:18;;;32341:30;-1:-1:-1;;;32387:18:35;;;32380:50;32447:18;;13758:60:1;32127:344:35;13758:60:1;-1:-1:-1;13895:29:1;13911:3;13895:29;13889:36;;13640:327::o;12978:323::-;13077:5;13119:10;:6;13128:1;13119:10;:::i;:::-;13102:6;:13;:27;;13094:59;;;;-1:-1:-1;;;13094:59:1;;32678:2:35;13094:59:1;;;32660:21:35;32717:2;32697:18;;;32690:30;-1:-1:-1;;;32736:18:35;;;32729:49;32795:18;;13094:59:1;32476:343:35;13094:59:1;-1:-1:-1;13229:29:1;13245:3;13229:29;13223:36;;12978:323::o;13307:327::-;13407:6;13450:10;:6;13459:1;13450:10;:::i;:::-;13433:6;:13;:27;;13425:60;;;;-1:-1:-1;;;13425:60:1;;33026:2:35;13425:60:1;;;33008:21:35;33065:2;33045:18;;;33038:30;-1:-1:-1;;;33084:18:35;;;33077:50;33144:18;;13425:60:1;32824:344:35;13425:60:1;-1:-1:-1;13562:29:1;13578:3;13562:29;13556:36;;13307:327::o;9558:2986::-;9680:12;9728:7;9712:12;9728:7;9722:2;9712:12;:::i;:::-;:23;;9704:50;;;;-1:-1:-1;;;9704:50:1;;33375:2:35;9704:50:1;;;33357:21:35;33414:2;33394:18;;;33387:30;-1:-1:-1;;;33433:18:35;;;33426:44;33487:18;;9704:50:1;33173:338:35;9704:50:1;9789:16;9798:7;9789:6;:16;:::i;:::-;9772:6;:13;:33;;9764:63;;;;-1:-1:-1;;;9764:63:1;;33718:2:35;9764:63:1;;;33700:21:35;33757:2;33737:18;;;33730:30;-1:-1:-1;;;33776:18:35;;;33769:47;33833:18;;9764:63:1;33516:341:35;9764:63:1;9838:22;9901:15;;9929:2177;;;;12247:4;12241:11;12228:24;;12433:1;12422:9;12415:20;12481:4;12470:9;12466:20;12460:4;12453:34;9894:2607;;9929:2177;10111:4;10105:11;10092:24;;10770:2;10761:7;10757:16;11193:9;11186:17;11180:4;11176:28;11144:9;11133;11129:25;11104:118;11258:7;11254:2;11250:16;11641:6;11578:9;11571:17;11565:4;11561:28;11521:9;11513:6;11509:22;11476:139;11447:222;11284:577;11695:3;11691:2;11688:11;11284:577;;;11833:9;;11822:21;;11736:4;11728:13;;;;11768;11284:577;;;-1:-1:-1;;11879:26:1;;;12087:2;12070:11;-1:-1:-1;;12066:25:1;12060:4;12053:39;-1:-1:-1;9894:2607:1;-1:-1:-1;12528:9:1;9558:2986;-1:-1:-1;;;;9558:2986:1:o;2611:166:30:-;2664:4;2688:1;2684;:5;2680:91;;;2712:5;2716:1;2712;:5;:::i;:::-;2705:12;;;;2680:91;2755:5;2759:1;2755;:5;:::i;1599:130:16:-;1513:6;;-1:-1:-1;;;;;1513:6:16;929:10:23;1662:23:16;1654:68;;;;-1:-1:-1;;;1654:68:16;;34064:2:35;1654:68:16;;;34046:21:35;;;34083:18;;;34076:30;34142:34;34122:18;;;34115:62;34194:18;;1654:68:16;33862:356:35;2673:187:16;2765:6;;;-1:-1:-1;;;;;2781:17:16;;;-1:-1:-1;;;;;;2781:17:16;;;;;;;2813:40;;2765:6;;;2781:17;2765:6;;2813:40;;2746:16;;2813:40;2736:124;2673:187;:::o;15318:342:1:-;15419:7;15463:11;:6;15472:2;15463:11;:::i;:::-;15446:6;:13;:28;;15438:62;;;;-1:-1:-1;;;15438:62:1;;34425:2:35;15438:62:1;;;34407:21:35;34464:2;34444:18;;;34437:30;-1:-1:-1;;;34483:18:35;;;34476:51;34544:18;;15438:62:1;34223:345:35;15438:62:1;-1:-1:-1;15584:30:1;15600:4;15584:30;15578:37;;15318:342::o;1309:628:8:-;1393:28;;:::i;:::-;1434:22;1458:10;1474;318:6:7;:15;-1:-1:-1;;;;;318:15:7;;239:102;1474:10:8;-1:-1:-1;;;;;1474:27:8;;1515:9;1474:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1474:60:8;;;;;;;;;;;;:::i;:::-;1433:101;;;;;1550:5;1545:50;;1564:31;;-1:-1:-1;;;1564:31:8;;;;;;;;;;;1545:50;1611:65;1639:2;:17;;;1658:2;:17;;;1611:27;:65::i;:::-;1606:131;;1697:40;;-1:-1:-1;;;1697:40:8;;;;;;;;;;;1606:131;1839:37:7;;-1:-1:-1;;;;;1839:37:7;-1:-1:-1;;;;;1752:47:8;:2;:11;;;-1:-1:-1;;;;;1752:47:8;;1748:105;;1820:33;;-1:-1:-1;;;1820:33:8;;;;;;;;;;;1748:105;1864:46;1898:2;:11;;;1864:33;:46::i;:::-;-1:-1:-1;1928:2:8;1309:628;-1:-1:-1;;1309:628:8:o;4237:270::-;4466:34;4492:7;4466:25;:34::i;4774:2238::-;4915:72;4990:22;-1:-1:-1;;;;;;;;;;;;;;;;;2190:34:7;;;;;;;;2197:27;2190:34;;;;;;;;;;;;2060:171;4990:22:8;4915:97;;5370:22;5394:10;5410;318:6:7;:15;-1:-1:-1;;;;;318:15:7;;239:102;5410:10:8;5451:16;;5410:67;;-1:-1:-1;;;5410:67:8;;-1:-1:-1;;;;;5410:27:8;;;;;;;:67;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;5410:67:8;;;;;;;;;;;;:::i;:::-;5369:108;;;;;5492:5;5487:50;;5506:31;;-1:-1:-1;;;5506:31:8;;;;;;;;;;;5487:50;5548:31;5582:60;5622:2;:10;;;5582:26;:60::i;:::-;5548:94;;5676:9;:7;:9::i;:::-;5656:29;;:2;:16;;;:29;;;;:54;;;;-1:-1:-1;5689:16:8;;;;:21;;;;5656:54;5652:115;;;5731:36;;-1:-1:-1;;;5731:36:8;;;;;;;;;;;5652:115;5795:52;5782:2;:9;;;:65;;;;;;;;:::i;:::-;;5778:127;;5868:37;;-1:-1:-1;;;5868:37:8;;;;;;;;;;;5778:127;5916:74;5993:89;6058:2;:10;;;5993:47;:89::i;:::-;6264:38;;5916:166;;-1:-1:-1;6221:81:8;;:27;2556:32:7;;;;;2473:122;6221:27:8;:81;;;6204:149;;6320:33;;-1:-1:-1;;;6320:33:8;;;;;;;;;;;6204:149;6393:38;;1464:32:11;:43;;-1:-1:-1;;1464:43:11;;;;;;;;;;;6511:114:8;;;;;;;;;6559:17;;;;6511:114;;;;;6594:17;;;;6511:114;;;;;;1194:27:11;:43;;-1:-1:-1;;1194:43:11;;;;;;;;;6792:46:8;6826:2;:11;;;6792:33;:46::i;:::-;6854:151;6891:22;6927;-1:-1:-1;;;;;;;;;;;;;;;;;2190:34:7;;;;;;;;2197:27;2190:34;;;;;;;;;;;;2060:171;6927:22:8;1839:37:7;;6854:151:8;;;8839:12:35;;8853:6;8835:25;;;8823:38;;8910:4;8899:16;;;8893:23;8877:14;;;8870:47;8839:12;;8835:25;39370:18;;;8823:38;;;;8899:16;;;;8893:23;8877:14;;;8870:47;-1:-1:-1;;;;;1839:37:7;39420:3:35;39405:19;;39398:60;39264:3;39249:19;6854:151:8;;;;;;;;4905:2107;;;;;;4774:2238;:::o;7018:691::-;7099:66;7168:18;:16;:18::i;:::-;7099:87;;7202:6;7197:144;7218:14;:21;7214:1;:25;7197:144;;;7325:5;7263:6;:24;;:59;7288:33;7303:14;7318:1;7303:17;;;;;;;;:::i;:::-;;;;;;;7288:14;:33::i;:::-;7263:59;;;;;;;;;;;-1:-1:-1;7263:59:8;:67;;-1:-1:-1;;7263:67:8;;;;;;;;;;7241:6;-1:-1:-1;7241:6:8;;:::i;:::-;;;7197:144;;;-1:-1:-1;7351:30:8;7358:23;;7351:30;:::i;:::-;7396:6;7391:246;7412:19;;:26;7408:30;;7391:246;;;7488:19;;:22;;7459:23;;7488:19;7508:1;;7488:22;;;;;;:::i;:::-;;;;;;;;;;;;7459:52;;;;;;;;-1:-1:-1;7459:52:8;;;;;;;;;;;;;;;-1:-1:-1;;7459:52:8;;;;;;;;;;;;;;;;;;;;;;;7582:19;;:22;;7459:52;;7525:24;;-1:-1:-1;;7567:38:8;;7602:1;;7582:22;;;;;;:::i;7567:38::-;7525:94;;;;;;;;;;;-1:-1:-1;7525:94:8;:101;;-1:-1:-1;;7525:101:8;;;;;;;;;;-1:-1:-1;7440:3:8;7391:246;;;;7652:50;7667:14;7683:18;:16;:18::i;:::-;7652:50;;;;;;;:::i;:::-;;;;;;;;7089:620;7018:691;:::o;7715:211::-;7780:11;7794:22;2313:27:7;;;2237:110;7794:22:8;7850:14;;879:27:11;:33;7780:36:8;-1:-1:-1;7881:38:8;7888:6;7896:22;2313:27:7;;;2237:110;7896:22:8;7881:38;;;40245:25:35;;;40301:2;40286:18;;40279:34;;;;40218:18;7881:38:8;40071:248:35;7932:265:8;8013:19;8035:24;2431:29:7;;;2353:114;8035:24:8;8095:22;;1008:29:11;:54;8013:46:8;-1:-1:-1;8134:56:8;8149:14;8165:24;2431:29:7;;;2353:114;8203:1737:8;8338:26;8375:10;318:6:7;:15;-1:-1:-1;;;;;318:15:7;;239:102;8375:10:8;8338:48;;8396:39;8408:7;:26;;;8396:11;:39::i;:::-;8620:22;8644:10;8660;318:6:7;:15;-1:-1:-1;;;;;318:15:7;;239:102;8660:10:8;-1:-1:-1;;;;;8660:27:8;;8701:9;8660:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8660:60:8;;;;;;;;;;;;:::i;:::-;8619:101;;;;;8736:5;8731:56;;8750:37;;-1:-1:-1;;;8750:37:8;;;;;;;;;;;8731:56;8803:65;8831:2;:17;;;8850:2;:17;;;8803:27;:65::i;:::-;8798:128;;8889:37;;-1:-1:-1;;;8889:37:8;;;;;;;;;;;8798:128;1839:37:7;;-1:-1:-1;;;;;1839:37:7;-1:-1:-1;;;;;8941:47:8;:2;:11;;;-1:-1:-1;;;;;8941:47:8;;8937:112;;9009:40;;-1:-1:-1;;;9009:40:8;;;;;;;;;;;8937:112;9060:31;9094:60;9134:2;:10;;;9094:26;:60::i;:::-;9060:94;-1:-1:-1;9182:35:8;9169:2;:9;;;:48;;;;;;;;:::i;:::-;;9165:113;;9238:40;;-1:-1:-1;;;9238:40:8;;;;;;;;;;;9165:113;9623:55;9681:42;9712:2;:10;;;9681:30;:42::i;:::-;9771:26;;9738:29;;9623:100;;-1:-1:-1;;;;;;9738:59:8;;;;;;9734:124;;9818:40;;-1:-1:-1;;;9818:40:8;;;;;;;;;;;9734:124;9874:59;9893:18;9921:10;318:6:7;:15;-1:-1:-1;;;;;318:15:7;;239:102;9921:10:8;9874:59;;;-1:-1:-1;;;;;40516:32:35;;;40498:51;;40585:32;;;;40580:2;40565:18;;40558:60;40471:18;9874:59:8;40324:300:35;9946:255:8;10047:11;10061:21;2676:26:7;;;2601:108;10061:21:8;10115:14;;1581:26:11;:32;10047:35:8;-1:-1:-1;10146:48:8;10164:6;10172:21;2676:26:7;;;2601:108;10207:367:8;10300:21;10286:7;:11;;;:35;10282:88;;;10342:28;;-1:-1:-1;;;10342:28:8;;;;;;;;;;;10282:88;10400:21;;10434:11;;;;10400:50;;10382:12;;-1:-1:-1;;;;;10400:26:8;;10434:11;10382:12;10400:50;10382:12;10400:50;10434:11;10400:26;:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10381:69;;;10468:7;10460:43;;;;-1:-1:-1;;;10460:43:8;;41041:2:35;10460:43:8;;;41023:21:35;41080:2;41060:18;;;41053:30;41119:25;41099:18;;;41092:53;41162:18;;10460:43:8;40839:347:35;10460:43:8;10532:21;;10555:11;;;;;10519:48;;;-1:-1:-1;;;;;41383:32:35;;;41365:51;;41432:18;;;41425:34;10519:48:8;;41338:18:35;10519:48:8;41191:274:35;347:177:7;426:41;;:::i;:::-;-1:-1:-1;486:31:7;;;;:22;:31;;;;;;;;;479:38;;;;;;;;;-1:-1:-1;;;;;479:38:7;;;;;-1:-1:-1;;;479:38:7;;;;;;;;;;;;-1:-1:-1;;;479:38:7;;;;;;;;;;;;;-1:-1:-1;;;479:38:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;347:177::o;14899:2182:4:-;15283:14;15311:49;15374:25;15424:21;15455:11;15476:14;15500:16;15526:22;;15639:72;15691:10;;15639:38;:72::i;:::-;15616:95;-1:-1:-1;15616:95:4;-1:-1:-1;15740:25:4;15726:10;:39;;;;;;:::i;:::-;;15722:107;;15788:30;;-1:-1:-1;;;15788:30:4;;;;;;;;;;;15722:107;15967:138;16065:10;;16089:6;15967:84;:138::i;:::-;-1:-1:-1;15839:266:4;;-1:-1:-1;15839:266:4;;-1:-1:-1;15839:266:4;-1:-1:-1;15839:266:4;-1:-1:-1;15839:266:4;-1:-1:-1;16191:27:4;;;16187:95;;16241:30;;-1:-1:-1;;;16241:30:4;;;;;;;;;;;16187:95;16420:10;16388:43;;-1:-1:-1;;;;;16388:43:4;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;16371:60;;16466:10;16452:25;;-1:-1:-1;;;;;16452:25:4;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16452:25:4;;16441:36;;16555:6;16550:391;16571:10;16567:14;;:1;:14;16550:391;;;16602:46;;:::i;:::-;16662:15;16788:60;16824:6;16832:7;;16841:6;16788:35;:60::i;:::-;16862:17;;16691:157;;-1:-1:-1;16691:157:4;;-1:-1:-1;16691:157:4;-1:-1:-1;16691:157:4;;16862:14;;16877:1;;16862:17;;;;;;:::i;:::-;;;;;;:33;;;;16923:7;16909:8;16918:1;16909:11;;;;;;;;:::i;:::-;;;;;;;;;;:21;-1:-1:-1;;16583:3:4;;16550:391;;;-1:-1:-1;16955:24:4;;;16951:96;;17002:34;;-1:-1:-1;;;17002:34:4;;;;;;;;;;;16951:96;17068:6;17056:18;;15414:1667;;;;;;14899:2182;;;;;:::o;20470:1047::-;20766:18;:30;;;-1:-1:-1;;;;;20728:68:4;:18;:34;;;-1:-1:-1;;;;;20728:68:4;;20711:162;;20828:34;;-1:-1:-1;;;20828:34:4;;;;;;;;;;;20711:162;20922:16;:28;;;-1:-1:-1;;;;;20886:64:4;:16;:32;;;-1:-1:-1;;;;;20886:64:4;;20882:136;;20973:34;;-1:-1:-1;;;20973:34:4;;;;;;;;;;;20882:136;21129:16;:21;;;21102:48;;:18;:23;;;:48;;;21098:123;;21173:37;;-1:-1:-1;;;21173:37:4;;;;;;;;;;;21098:123;21267:16;:28;;;-1:-1:-1;;;;;21234:61:4;:18;:30;;;-1:-1:-1;;;;;21234:61:4;;21230:136;;;21318:37;;-1:-1:-1;;;21318:37:4;;;;;;;;;;;21230:136;21412:16;:28;;;-1:-1:-1;;;;;21379:61:4;:18;:30;;;-1:-1:-1;;;;;21379:61:4;;21375:136;;;21463:37;;-1:-1:-1;;;21463:37:4;;;;;;;;;;;24857:2301;25053:46;;:::i;:::-;25111:26;;;25173:30;;;;;-1:-1:-1;;;;;25147:56:4;;;:23;;;:56;25237:28;;;;25213:52;:21;;;:52;-1:-1:-1;25431:30:4;;;;25388:28;;;;25111:16;;25388:73;;;:::i;:::-;25537:34;;25490:32;;25370:91;;-1:-1:-1;25471:16:4;;25490:81;;25537:34;25490:81;:::i;:::-;25471:100;;25581:16;25646:18;:33;;;25600:16;:31;;;:79;;;;:::i;:::-;25581:98;-1:-1:-1;25863:16:4;25882:37;-1:-1:-1;;;;;25901:17:4;;25882:9;:37;:::i;:::-;25863:56;-1:-1:-1;25929:16:4;25948:28;-1:-1:-1;;;;;25959:17:4;;25948:8;:28;:::i;:::-;26420:18;;;;;;:43;;;;;;26473:18;;-1:-1:-1;;;;;26473:42:4;;;:23;;;;:42;;;;26551:23;;;;26525:18;;:49;;;;;-1:-1:-1;26525:23:4;;;:49;-1:-1:-1;26617:28:4;;;26584:18;;:61;;;;:30;;;;:61;26874:31;;;;26830:29;;;;25929:47;;-1:-1:-1;26420:24:4;;26830:75;;26874:31;26830:75;:::i;:::-;26806:99;-1:-1:-1;26915:21:4;26970:8;26940:26;26806:99;26957:9;26940:26;:::i;:::-;26939:39;;;;:::i;:::-;27067:53;;:28;;;:53;-1:-1:-1;;;;;;;24857:2301:4;;;;;:::o;14191:1376:5:-;14304:16;14346:18;14378:21;14412:57;14451:17;;14412:38;:57::i;:::-;14332:137;;-1:-1:-1;14332:137:5;-1:-1:-1;14498:25:5;14484:10;:39;;;;;;:::i;:::-;;14480:107;;14546:30;;-1:-1:-1;;;14546:30:5;;;;;;;;;;;14480:107;14597:11;14618:14;14642:22;;14674:11;14811:152;14909:17;;14940:13;14811:84;:152::i;:::-;14695:268;;-1:-1:-1;14695:268:5;;-1:-1:-1;14695:268:5;;-1:-1:-1;14695:268:5;;-1:-1:-1;14695:268:5;;-1:-1:-1;14695:268:5;-1:-1:-1;15003:6:5;14998:476;15019:10;15015:14;;:1;:14;14998:476;;;15054:46;;:::i;:::-;15118:15;15151:22;15337:56;15369:6;15377:7;;15386:6;15337:31;:56::i;:::-;15191:202;;-1:-1:-1;15191:202:5;;-1:-1:-1;15191:202:5;-1:-1:-1;15191:202:5;-1:-1:-1;15411:48:5;15191:202;;15411:28;:48::i;:::-;-1:-1:-1;;;15031:3:5;;14998:476;;;-1:-1:-1;15497:24:5;;;15493:67;;15530:30;;-1:-1:-1;;;15530:30:5;;;;;;;;;;;15493:67;14322:1245;;;;;;;14191:1376;;;;:::o;1104:111:16:-;5363:13:20;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:20;;;;;;;:::i;:::-;1176:32:16::1;929:10:23::0;1176:18:16::1;:32::i;225:88:11:-:0;277:6;:29;;-1:-1:-1;;;;;;277:29:11;-1:-1:-1;;;;;277:29:11;;;;;;;;;;225:88::o;1250:134::-;1329:37;:48;;-1:-1:-1;;1329:48:11;-1:-1:-1;;;;;1329:48:11;;;;;;;;;;1250:134::o;1805:281:18:-;-1:-1:-1;;;;;1476:19:22;;;1878:106:18;;;;-1:-1:-1;;;1878:106:18;;43519:2:35;1878:106:18;;;43501:21:35;43558:2;43538:18;;;43531:30;43597:34;43577:18;;;43570:62;-1:-1:-1;;;43648:18:35;;;43641:43;43701:19;;1878:106:18;43317:409:35;1878:106:18;-1:-1:-1;;;;;;;;;;;1994:85:18;;-1:-1:-1;;;;;;1994:85:18;-1:-1:-1;;;;;1994:85:18;;;;;;;;;;1805:281::o;2478:288::-;2616:29;2627:17;2616:10;:29::i;:::-;2673:1;2659:4;:11;:15;:28;;;;2678:9;2659:28;2655:105;;;2703:46;2725:17;2744:4;2703:21;:46::i;3925:3042:5:-;4155:11;;;4238:22;4155:11;;4344:166;4390:17;;4425:13;4456:40;;;4344:28;:166::i;:::-;4688:1;;-1:-1:-1;4334:176:5;;-1:-1:-1;4334:176:5;-1:-1:-1;1675:40:3;;1670:3;1666:50;4722:27:5;4533:1;4814:236;4860:168;4334:176;;4688:1;1666:50:3;4860:28:5;:168::i;:::-;4814:20;:236::i;:::-;5314:10;;;13637:3:2;13621:29;;;13615:36;5072:21:5;;;;;;;;5314:10;;-1:-1:-1;13637:3:2;-1:-1:-1;709:10:5;5629:35;;;;5625:102;;5697:30;;-1:-1:-1;;;5697:30:5;;;;;;;;;;;5625:102;13095:29:2;;;13111:3;13095:29;13089:36;5750:21:5;;5774:111;;;;;;;;:::i;:::-;5907:15;;;;;5750:135;-1:-1:-1;5963:25:5;5949:10;:39;;;;;;:::i;:::-;;5945:106;;6021:30;;-1:-1:-1;;;6021:30:5;;;;;;;;;;;5945:106;13884:29:2;;;13900:3;13884:29;13878:36;6074:131:5;-1:-1:-1;6411:18:5;;;;;6494:55;6519:14;6411:18;12788:4:2;12772:30;;;12766:37;-1:-1:-1;;;12745:117:2;;;12557:350;6494:55:5;6461:110;;6452:119;;6610:2;6593:19;;;;6734:14;:21;6718:13;:37;6714:104;;;6788:30;;-1:-1:-1;;;6788:30:5;;;;;;;;;;;6714:104;-1:-1:-1;;6949:1:5;6939:11;;;3925:3042;;-1:-1:-1;;;;1409:26:3;;;1396:40;1391:3;1387:50;;-1:-1:-1;1409:26:3;;-1:-1:-1;3925:3042:5;;;-1:-1:-1;3925:3042:5:o;7620:1904:4:-;7857:14;7883:46;;:::i;:::-;7939:15;7964:22;8106:67;8138:10;:17;;;8157:7;;8166:6;8106:31;:67::i;:::-;7997:176;;-1:-1:-1;7997:176:4;;-1:-1:-1;7997:176:4;-1:-1:-1;7997:176:4;-1:-1:-1;8184:6:4;8204:139;8215:16;;:23;8211:27;;8204:139;;;8286:7;8263;:16;;;8280:1;8263:19;;;;;;;;:::i;:::-;;;;;;;:30;8259:74;8313:5;8259:74;8240:3;;8204:139;;;8430:16;;:23;8426:27;;:60;;;;;8457:7;:18;;;8476:1;8457:21;;;;;;;;:::i;:::-;;;;;;;;;;;:24;:29;8426:60;8422:1096;;;8526:21;;8598:29;;;;-1:-1:-1;;;;;8521:27:4;;;;8583:44;;;;;;:108;;;8662:7;:29;;;-1:-1:-1;;;;;8647:44:4;:11;:44;;8583:108;:225;;;;;8713:7;:23;;;8712:24;:95;;;;8792:15;-1:-1:-1;;;;;8760:47:4;:7;:29;;;-1:-1:-1;;;;;8760:47:4;;8712:95;8562:946;;;8868:7;8841;:18;;;8860:1;8841:21;;;;;;;;:::i;:::-;;;;;;;;;;;:34;8929:15;;;;8893:18;;;;:21;;8912:1;;8893:21;;;;;;:::i;:::-;;;;;;;;;;;;:27;;:51;;;;;;;8997:14;;;;8962:18;;;;:21;;8981:1;;8962:21;;;;;;:::i;:::-;;;;;;;:27;;;:32;;:49;-1:-1:-1;;;;;8962:49:4;;;-1:-1:-1;;;;;8962:49:4;;;;;9064:9;:14;;;9029:7;:18;;;9048:1;9029:21;;;;;;;;:::i;:::-;;;;;;;:27;;;:32;;:49;;;;;;;;;;;9138:11;9096:7;:18;;;9115:1;9096:21;;;;;;;;:::i;:::-;;;;;;;:27;;;:39;;:53;;;;;9206:9;:18;;;9167:7;:18;;;9186:1;9167:21;;;;;;;;:::i;:::-;;;;;;;:30;;;:36;;:57;;;;;;;;;;;9280:9;:17;;;9242:7;:18;;;9261:1;9242:21;;;;;;;;:::i;:::-;;;;;;;:30;;;:35;;:55;-1:-1:-1;;;;;9242:55:4;;;-1:-1:-1;;;;;9242:55:4;;;;;9353:9;:14;;;9315:7;:18;;;9334:1;9315:21;;;;;;;;:::i;:::-;;;;;;;:30;;;:35;;:52;;;;;;;;;;;9430:11;9385:7;:18;;;9404:1;9385:21;;;;;;;;:::i;:::-;;;;;;;:30;;;:42;;:56;;;;;9478:10;:15;;;9459:7;:13;;;9473:1;9459:16;;;;;;;;:::i;:::-;;;;;;:34;-1:-1:-1;;;;;9459:34:4;;;-1:-1:-1;;;;;9459:34:4;;;;;8562:946;8488:1030;8422:1096;7873:1651;;;;7620:1904;;;;;;;:::o;2005:644:13:-;2121:25;2149:20;:18;:20::i;:::-;2201:25;;2121:48;;-1:-1:-1;2179:69:13;;2201:25;2228:12;;2179:69;2471:4;-1:-1:-1;;;;;2471:24:13;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:40;;2501:10;2471:40;2467:102;;2532:37;;-1:-1:-1;;;2532:37:13;;;;;;;;;;;2467:102;2585:57;2602:17;2621:20;:18;:20::i;:::-;2585:57;;;-1:-1:-1;;;;;40516:32:35;;;40498:51;;40585:32;;;;40580:2;40565:18;;40558:60;40471:18;2585:57:13;40324:300:35;8331:836:5;8519:14;8547:46;;:::i;:::-;8607:15;8647:29;;8686:23;8808:57;8841:7;;8850:6;8858;8808:32;:57::i;:::-;8719:146;-1:-1:-1;8719:146:5;;-1:-1:-1;8719:146:5;-1:-1:-1;8719:146:5;-1:-1:-1;8895:25:5;8880:11;:40;;;;;;;;:::i;:::-;;8876:231;;8963:90;9006:14;;9038:1;8963:25;:90::i;:::-;8936:117;;-1:-1:-1;8936:117:5;-1:-1:-1;9118:42:5;;;8331:836;;;;;;;;:::o;7439:886::-;7623:14;7651:46;;:::i;:::-;7711:15;7740:22;7787:29;;7826:23;7948:57;7981:7;;7990:6;7998;7948:32;:57::i;:::-;7859:146;-1:-1:-1;7859:146:5;;-1:-1:-1;7859:146:5;-1:-1:-1;7859:146:5;-1:-1:-1;8035:21:5;8020:11;:36;;;;;;;;:::i;:::-;;8016:236;;8112:86;8151:14;;8183:1;8112:21;:86::i;:::-;8072:126;;-1:-1:-1;8072:126:5;-1:-1:-1;8072:126:5;-1:-1:-1;8263:55:5;;;7439:886;;;;;;;;;:::o;2192:152:18:-;2258:37;2277:17;2258:18;:37::i;:::-;2310:27;;-1:-1:-1;;;;;2310:27:18;;;;;;;;2192:152;:::o;7088:455::-;7171:12;-1:-1:-1;;;;;1476:19:22;;;7195:88:18;;;;-1:-1:-1;;;7195:88:18;;44144:2:35;7195:88:18;;;44126:21:35;44183:2;44163:18;;;44156:30;44222:34;44202:18;;;44195:62;-1:-1:-1;;;44273:18:35;;;44266:36;44319:19;;7195:88:18;43942:402:35;7195:88:18;7354:12;7368:23;7395:6;-1:-1:-1;;;;;7395:19:18;7415:4;7395:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7353:67;;;;7437:99;7473:7;7482:10;7437:99;;;;;;;;;;;;;;;;;:35;:99::i;541:195:3:-;665:14;;698:6;705;698;712:16;721:7;705:6;712:16;:::i;:::-;698:31;;;;;;;:::i;:::-;691:38;;;;541:195;;;;;;;:::o;1124:428:5:-;1217:22;;:::i;:::-;1265:10;1305;318:6:7;:15;-1:-1:-1;;;;;318:15:7;;239:102;1305:10:5;-1:-1:-1;;;;;1305:27:5;;1333:9;;1305:38;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1305:38:5;;;;;;;;;;;;:::i;:::-;-1:-1:-1;1289:54:5;;-1:-1:-1;1289:54:5;-1:-1:-1;1289:54:5;1357:50;;1376:31;;-1:-1:-1;;;1376:31:5;;;;;;;;;;;1357:50;1251:167;1433:55;1451:2;:17;;;1470:2;:17;;;1433;:55::i;:::-;1428:117;;1509:36;;-1:-1:-1;;;1509:36:5;;;;;;;;;;;13699:257:2;13884:29;13900:3;13884:29;13878:36;;13699:257::o;9173:1177:5:-;9357:29;;;;1688:26:3;;;1675:40;1670:3;1666:50;9555:11:5;9565:1;1688:26:3;9555:11:5;:::i;:::-;;;9594:104;9636:7;;9657:6;9677:11;9594:104;;:28;:104::i;:::-;9577:121;;-1:-1:-1;9577:121:5;-1:-1:-1;9708:21:5;;;;;;:::i;:::-;;;9740:10;9781:122;9818:7;;9839:6;9859;9879:14;;9781:23;:122::i;:::-;9760:143;-1:-1:-1;9760:143:5;-1:-1:-1;9760:143:5;9913:74;;9946:30;;-1:-1:-1;;;9946:30:5;;;;;;;;;;;9913:74;1396:40:3;;1391:3;1387:50;10011:84:5;;;;;;;;:::i;:::-;9997:98;-1:-1:-1;10137:21:5;10122:11;:36;;;;;;;;:::i;:::-;;;:92;;;;-1:-1:-1;10189:25:5;10174:11;:40;;;;;;;;:::i;:::-;;;10122:92;10105:182;;;10246:30;;-1:-1:-1;;;10246:30:5;;;;;;;;;;;10105:182;10296:47;;9173:1177;;;;;;;;;:::o;12407:1778::-;12573:46;;:::i;:::-;3358:26:3;;;12839:2:5;2807:26:3;;;2794:40;2789:3;12856:132:5;;;;;13002:12;2807:26:3;;2794:40;2785:50;;13029:28:5;;;:139;;;;13182:12;2246:26:3;;;2233:40;2228:3;2224:50;;;13209:26:5;;;:136;;;;13359:11;2246:26:3;;2233:40;2224:50;;13385:25:5;;;;:135;;;;13534:11;2246:26:3;;2233:40;2224:50;;13560:25:5;;;:135;;;;13709:11;2246:26:3;;2233:40;2224:50;;13735:29:5;;;:139;1967:26:3;;;1954:40;1949:3;13914:119:5;:18;;;:119;14047:11;;;;;3345:40:3;14077:36:5;;;14073:95;;;14138:30;;-1:-1:-1;;;14138:30:5;;;;;;;;;;;14073:95;12407:1778;;;;;;:::o;10356:2045::-;10514:46;;:::i;:::-;10812:2;3358:26:3;;;2246;;;2233:40;2228:3;10829:112:5;;;:15;;;;:112;;;;10955:11;2246:26:3;;2233:40;2224:50;;10981:14:5;;;:120;11115:11;1967:26:3;;1954:40;1949:3;11141:111:5;:14;;;:111;11266:11;2246:26:3;;2233:40;2224:50;;;11608:127:5;;11886:49;;;;;;;;;;;;;;;;;;;;11749:11;;;;;3345:40:3;;;10574:15:5;;11886:49;;3358:26:3;;11886:49:5;;;;;;3358:26:3;11886:49:5;;3358:26:3;11886:49:5;;;;;;;;;-1:-1:-1;11928:6:5;;-1:-1:-1;11886:23:5;;-1:-1:-1;;11886:49:5:i;:::-;2246:26:3;;;11959:1:5;2246:26:3;;2233:40;2228:3;11975:115:5;;;:18;;;:115;12104:11;2246:26:3;;;2233:40;2224:50;;12130:17:5;;;:123;12267:11;;;;;11868:67;-1:-1:-1;12297:32:5;;;12293:91;;;12354:30;;-1:-1:-1;;;12354:30:5;;;;;;;;;;;12293:91;10356:2045;;;;;;;:::o;7438:295:22:-;7584:12;7612:7;7608:119;;;-1:-1:-1;7642:10:22;7635:17;;7608:119;7683:33;7691:10;7703:12;7683:7;:33::i;1676:939:0:-;1845:10;1857:14;1907:21;1931:29;1951:8;;1931:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1931:19:0;;-1:-1:-1;;;1931:29:0:i;:::-;2125:1;2110:16;;;1907:53;;-1:-1:-1;1409:26:3;;1396:40;1391:3;1387:50;1975:15:0;2141:377;2162:9;2158:13;;:1;:13;2141:377;;;2359:2;2344:17;;;1130:26:3;;1117:40;-1:-1:-1;;;;;;2220:106:0;2396:107;2437:13;2220:106;2396:19;:107::i;:::-;2380:123;-1:-1:-1;;2173:3:0;;2141:377;;;-1:-1:-1;;;;;;;;2540:21:0;;;;;;;;;;2587:11;;-1:-1:-1;1676:939:0;;-1:-1:-1;;;;;1676:939:0:o;7739:540:22:-;7898:17;;:21;7894:379;;8126:10;8120:17;8182:15;8169:10;8165:2;8161:19;8154:44;7894:379;8249:12;8242:20;;-1:-1:-1;;;8242:20:22;;;;;;;;:::i;635:141:0:-;695:7;721:48;279:1;763:4;726:42;;;;;;;;;:::i;:::-;;;;;;;;;;;;;470:16;;;;;;;;379:115;782:276;877:7;-1:-1:-1;;;;;;900:15:0;;;;;;;896:81;;;951:6;;959;896:81;998:52;;-1:-1:-1;;;998:52:0;;;45941:49:35;-1:-1:-1;;;;;;46019:44:35;;;46006:11;;;45999:65;46094:44;;46080:12;;;46073:66;993:58:0;;46155:12:35;;998:52:0;45760:413:35;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:173:35:-;82:20;;-1:-1:-1;;;;;131:31:35;;121:42;;111:70;;177:1;174;167:12;111:70;14:173;;;:::o;192:366::-;254:8;264:6;318:3;311:4;303:6;299:17;295:27;285:55;;336:1;333;326:12;285:55;-1:-1:-1;359:20:35;;-1:-1:-1;;;;;391:30:35;;388:50;;;434:1;431;424:12;388:50;471:4;463:6;459:17;447:29;;531:3;524:4;514:6;511:1;507:14;499:6;495:27;491:38;488:47;485:67;;;548:1;545;538:12;563:117;648:6;641:5;637:18;630:5;627:29;617:57;;670:1;667;660:12;685:129;-1:-1:-1;;;;;763:5:35;759:30;752:5;749:41;739:69;;804:1;801;794:12;819:1476;992:6;1000;1008;1016;1024;1032;1040;1048;1056;1064;1117:3;1105:9;1096:7;1092:23;1088:33;1085:53;;;1134:1;1131;1124:12;1085:53;1157:29;1176:9;1157:29;:::i;:::-;1147:39;;1237:2;1226:9;1222:18;1209:32;-1:-1:-1;;;;;1256:6:35;1253:30;1250:50;;;1296:1;1293;1286:12;1250:50;1335:69;1396:7;1387:6;1376:9;1372:22;1335:69;:::i;:::-;1423:8;;-1:-1:-1;1309:95:35;-1:-1:-1;;1511:2:35;1496:18;;1483:32;-1:-1:-1;;;;;1527:32:35;;1524:52;;;1572:1;1569;1562:12;1524:52;1611:71;1674:7;1663:8;1652:9;1648:24;1611:71;:::i;:::-;1701:8;;-1:-1:-1;1585:97:35;-1:-1:-1;;1786:2:35;1771:18;;1758:32;1799:30;1758:32;1799:30;:::i;:::-;1848:5;-1:-1:-1;1926:3:35;1911:19;;1898:33;;-1:-1:-1;2009:3:35;1994:19;;1981:33;2023:32;1981:33;2023:32;:::i;:::-;819:1476;;;;-1:-1:-1;819:1476:35;;;;;;;;-1:-1:-1;819:1476:35;;2154:3;2139:19;;2126:33;;2258:3;2243:19;;;2230:33;;-1:-1:-1;819:1476:35;-1:-1:-1;819:1476:35:o;2300:127::-;2361:10;2356:3;2352:20;2349:1;2342:31;2392:4;2389:1;2382:15;2416:4;2413:1;2406:15;2432:253;2504:2;2498:9;2546:4;2534:17;;-1:-1:-1;;;;;2566:34:35;;2602:22;;;2563:62;2560:88;;;2628:18;;:::i;:::-;2664:2;2657:22;2432:253;:::o;2690:255::-;2762:2;2756:9;2804:6;2792:19;;-1:-1:-1;;;;;2826:34:35;;2862:22;;;2823:62;2820:88;;;2888:18;;:::i;2950:275::-;3021:2;3015:9;3086:2;3067:13;;-1:-1:-1;;3063:27:35;3051:40;;-1:-1:-1;;;;;3106:34:35;;3142:22;;;3103:62;3100:88;;;3168:18;;:::i;:::-;3204:2;3197:22;2950:275;;-1:-1:-1;2950:275:35:o;3230:186::-;3278:4;-1:-1:-1;;;;;3303:6:35;3300:30;3297:56;;;3333:18;;:::i;:::-;-1:-1:-1;3399:2:35;3378:15;-1:-1:-1;;3374:29:35;3405:4;3370:40;;3230:186::o;3421:486::-;3463:5;3516:3;3509:4;3501:6;3497:17;3493:27;3483:55;;3534:1;3531;3524:12;3483:55;3574:6;3561:20;3605:52;3621:35;3649:6;3621:35;:::i;:::-;3605:52;:::i;:::-;3682:6;3673:7;3666:23;3736:3;3729:4;3720:6;3712;3708:19;3704:30;3701:39;3698:59;;;3753:1;3750;3743:12;3698:59;3818:6;3811:4;3803:6;3799:17;3792:4;3783:7;3779:18;3766:59;3874:1;3845:20;;;3867:4;3841:31;3834:42;;;;3849:7;3421:486;-1:-1:-1;;;3421:486:35:o;3912:320::-;3980:6;4033:2;4021:9;4012:7;4008:23;4004:32;4001:52;;;4049:1;4046;4039:12;4001:52;4089:9;4076:23;-1:-1:-1;;;;;4114:6:35;4111:30;4108:50;;;4154:1;4151;4144:12;4108:50;4177:49;4218:7;4209:6;4198:9;4194:22;4177:49;:::i;4504:226::-;4563:6;4616:2;4604:9;4595:7;4591:23;4587:32;4584:52;;;4632:1;4629;4622:12;4584:52;-1:-1:-1;4677:23:35;;4504:226;-1:-1:-1;4504:226:35:o;4735:313::-;4826:5;4820:12;4817:1;4806:27;4801:3;4794:40;-1:-1:-1;;;;;4887:4:35;4880:5;4876:16;4870:23;4866:48;4859:4;4854:3;4850:14;4843:72;4978:4;4971:5;4967:16;4961:23;4958:1;4947:38;4940:4;4935:3;4931:14;4924:62;5035:4;5028:5;5024:16;5018:23;5011:4;5006:3;5002:14;4995:47;;;4735:313::o;5053:241::-;5233:3;5218:19;;5246:42;5222:9;5270:6;5246:42;:::i;5299:186::-;5358:6;5411:2;5399:9;5390:7;5386:23;5382:32;5379:52;;;5427:1;5424;5417:12;5379:52;5450:29;5469:9;5450:29;:::i;5490:118::-;5576:5;5569:13;5562:21;5555:5;5552:32;5542:60;;5598:1;5595;5588:12;5613:1479;5780:6;5788;5796;5804;5812;5820;5828;5836;5844;5897:3;5885:9;5876:7;5872:23;5868:33;5865:53;;;5914:1;5911;5904:12;5865:53;5954:9;5941:23;-1:-1:-1;;;;;5979:6:35;5976:30;5973:50;;;6019:1;6016;6009:12;5973:50;6058:69;6119:7;6110:6;6099:9;6095:22;6058:69;:::i;:::-;6146:8;;-1:-1:-1;6032:95:35;-1:-1:-1;;6234:2:35;6219:18;;6206:32;-1:-1:-1;;;;;6250:32:35;;6247:52;;;6295:1;6292;6285:12;6247:52;6334:71;6397:7;6386:8;6375:9;6371:24;6334:71;:::i;:::-;6424:8;;-1:-1:-1;6308:97:35;-1:-1:-1;;6509:2:35;6494:18;;6481:32;6522:30;6481:32;6522:30;:::i;:::-;6571:5;-1:-1:-1;6628:2:35;6613:18;;6600:32;6641;6600;6641;:::i;:::-;6692:7;-1:-1:-1;6751:3:35;6736:19;;6723:33;6765:30;6723:33;6765:30;:::i;:::-;6814:7;-1:-1:-1;6873:3:35;6858:19;;6845:33;6887:30;6845:33;6887:30;:::i;:::-;6936:7;-1:-1:-1;7016:3:35;7001:19;;6988:33;7030:30;6988:33;7030:30;:::i;:::-;7079:7;7069:17;;;5613:1479;;;;;;;;;;;:::o;7097:326::-;7178:5;7172:12;7167:3;7160:25;7231:4;7224:5;7220:16;7214:23;7246:53;7293:4;7288:3;7284:14;7270:12;7246:53;:::i;:::-;;7347:4;7340:5;7336:16;7330:23;7362:55;7411:4;7406:3;7402:14;7386;7362:55;:::i;7428:452::-;7490:3;7528:5;7522:12;7555:6;7550:3;7543:19;7587:4;7582:3;7578:14;7571:21;;7626:4;7619:5;7615:16;7649:1;7659:196;7673:6;7670:1;7667:13;7659:196;;;7722:47;7765:3;7756:6;7750:13;7722:47;:::i;:::-;7798:6;7789:16;;;;;7840:4;7828:17;;;;;7695:1;7688:9;7659:196;;;-1:-1:-1;7871:3:35;;7428:452;-1:-1:-1;;;;7428:452:35:o;7885:869::-;8194:2;8183:9;8176:21;8157:4;8220:65;8281:2;8270:9;8266:18;8258:6;8220:65;:::i;:::-;8333:9;8325:6;8321:22;8316:2;8305:9;8301:18;8294:50;8364:6;8399;8393:13;8430:6;8422;8415:22;8465:2;8457:6;8453:15;8446:22;;8503:2;8495:6;8491:15;8477:29;;8524:1;8534:194;8548:6;8545:1;8542:13;8534:194;;;8613:13;;-1:-1:-1;;;;;8609:38:35;8597:51;;8677:2;8703:15;;;;8668:12;;;;8570:1;8563:9;8534:194;;;-1:-1:-1;8745:3:35;;7885:869;-1:-1:-1;;;;;;7885:869:35:o;8928:255::-;8839:12;;8853:6;8835:25;8823:38;;8910:4;8899:16;;;8893:23;8877:14;;;8870:47;9118:2;9103:18;;9130:47;8759:164;9188:365;9255:6;9263;9316:2;9304:9;9295:7;9291:23;9287:32;9284:52;;;9332:1;9329;9322:12;9284:52;9371:9;9358:23;9390:30;9414:5;9390:30;:::i;:::-;9439:5;9517:2;9502:18;;;;9489:32;;-1:-1:-1;;;9188:365:35:o;9750:1050::-;9899:6;9907;9915;9923;9931;9939;9992:3;9980:9;9971:7;9967:23;9963:33;9960:53;;;10009:1;10006;9999:12;9960:53;10049:9;10036:23;-1:-1:-1;;;;;10074:6:35;10071:30;10068:50;;;10114:1;10111;10104:12;10068:50;10153:69;10214:7;10205:6;10194:9;10190:22;10153:69;:::i;:::-;10241:8;;-1:-1:-1;10127:95:35;-1:-1:-1;;10329:2:35;10314:18;;10301:32;-1:-1:-1;;;;;10345:32:35;;10342:52;;;10390:1;10387;10380:12;10342:52;10429:71;10492:7;10481:8;10470:9;10466:24;10429:71;:::i;:::-;10519:8;;-1:-1:-1;10403:97:35;-1:-1:-1;;10604:2:35;10589:18;;10576:32;10617:30;10576:32;10617:30;:::i;:::-;10666:5;-1:-1:-1;10723:2:35;10708:18;;10695:32;10736;10695;10736;:::i;:::-;10787:7;10777:17;;;9750:1050;;;;;;;;:::o;10805:324::-;11038:2;11027:9;11020:21;11001:4;11058:65;11119:2;11108:9;11104:18;11096:6;11058:65;:::i;11772:394::-;11849:6;11857;11910:2;11898:9;11889:7;11885:23;11881:32;11878:52;;;11926:1;11923;11916:12;11878:52;11949:29;11968:9;11949:29;:::i;:::-;11939:39;;12029:2;12018:9;12014:18;12001:32;-1:-1:-1;;;;;12048:6:35;12045:30;12042:50;;;12088:1;12085;12078:12;12042:50;12111:49;12152:7;12143:6;12132:9;12128:22;12111:49;:::i;:::-;12101:59;;;11772:394;;;;;:::o;12353:250::-;12438:1;12448:113;12462:6;12459:1;12456:13;12448:113;;;12538:11;;;12532:18;12519:11;;;12512:39;12484:2;12477:10;12448:113;;;-1:-1:-1;;12595:1:35;12577:16;;12570:27;12353:250::o;12608:271::-;12650:3;12688:5;12682:12;12715:6;12710:3;12703:19;12731:76;12800:6;12793:4;12788:3;12784:14;12777:4;12770:5;12766:16;12731:76;:::i;:::-;12861:2;12840:15;-1:-1:-1;;12836:29:35;12827:39;;;;12868:4;12823:50;;12608:271;-1:-1:-1;;12608:271:35:o;12884:220::-;13033:2;13022:9;13015:21;12996:4;13053:45;13094:2;13083:9;13079:18;13071:6;13053:45;:::i;13109:447::-;13206:6;13214;13267:2;13255:9;13246:7;13242:23;13238:32;13235:52;;;13283:1;13280;13273:12;13235:52;13323:9;13310:23;-1:-1:-1;;;;;13348:6:35;13345:30;13342:50;;;13388:1;13385;13378:12;13342:50;13427:69;13488:7;13479:6;13468:9;13464:22;13427:69;:::i;:::-;13515:8;;13401:95;;-1:-1:-1;13109:447:35;-1:-1:-1;;;;13109:447:35:o;13911:127::-;13972:10;13967:3;13963:20;13960:1;13953:31;14003:4;14000:1;13993:15;14027:4;14024:1;14017:15;14043:741;14250:2;14239:9;14232:21;14213:4;14278:6;14272:13;14311:1;14307:2;14304:9;14294:43;;14317:18;;:::i;:::-;14373:2;14368;14357:9;14353:18;14346:30;;14423:2;14415:6;14411:15;14405:22;14463:2;14449:12;14446:20;14436:54;;14470:18;;:::i;:::-;14526:12;14521:2;14510:9;14506:18;14499:40;;14603:6;14597:2;14589:6;14585:15;14579:22;14575:35;14570:2;14559:9;14555:18;14548:63;14660:2;14652:6;14648:15;14642:22;14702:4;14695;14684:9;14680:20;14673:34;14724:54;14773:3;14762:9;14758:19;14742:14;14724:54;:::i;14986:346::-;15054:6;15062;15115:2;15103:9;15094:7;15090:23;15086:32;15083:52;;;15131:1;15128;15121:12;15083:52;-1:-1:-1;;15176:23:35;;;15296:2;15281:18;;;15268:32;;-1:-1:-1;14986:346:35:o;15889:452::-;15952:3;15990:5;15984:12;16017:6;16012:3;16005:19;16049:4;16044:3;16040:14;16033:21;;16088:4;16081:5;16077:16;16111:1;16121:195;16135:6;16132:1;16129:13;16121:195;;;16184:48;16228:3;16219:6;16213:13;8839:12;;8853:6;8835:25;8823:38;;8910:4;8899:16;;;8893:23;8877:14;;8870:47;8759:164;16184:48;16261:4;16252:14;;;;;16301:4;16289:17;;;;;16157:1;16150:9;16121:195;;16346:386;16553:2;16542:9;16535:21;16516:4;16591:6;16585:13;16634:2;16629;16618:9;16614:18;16607:30;16654:72;16722:2;16711:9;16707:18;16693:12;16654:72;:::i;17032:682::-;17119:6;17179:2;17167:9;17158:7;17154:23;17150:32;17194:2;17191:22;;;17209:1;17206;17199:12;17191:22;-1:-1:-1;17278:2:35;17272:9;;;17308:15;;-1:-1:-1;;;;;17338:34:35;;17374:22;;;17335:62;17332:88;;;17400:18;;:::i;:::-;17436:2;17429:22;17473:23;;17505:30;17473:23;17505:30;:::i;:::-;17544:21;;17638:2;17623:18;;;17610:32;17658:15;;;17651:32;;;;-1:-1:-1;17551:6:35;17032:682;-1:-1:-1;17032:682:35:o;18120:327::-;18355:2;18344:9;18337:21;18318:4;18375:66;18437:2;18426:9;18422:18;18414:6;18375:66;:::i;18753:586::-;18823:6;18831;18884:2;18872:9;18863:7;18859:23;18855:32;18852:52;;;18900:1;18897;18890:12;18852:52;18940:9;18927:23;-1:-1:-1;;;;;18965:6:35;18962:30;18959:50;;;19005:1;19002;18995:12;18959:50;19028:22;;19081:4;19073:13;;19069:27;-1:-1:-1;19059:55:35;;19110:1;19107;19100:12;19059:55;19150:2;19137:16;-1:-1:-1;;;;;19168:6:35;19165:30;19162:50;;;19208:1;19205;19198:12;19162:50;19253:7;19248:2;19239:6;19235:2;19231:15;19227:24;19224:37;19221:57;;;19274:1;19271;19264:12;19221:57;19305:2;19297:11;;;;;19327:6;;-1:-1:-1;18753:586:35;-1:-1:-1;;;18753:586:35:o;19344:1106::-;19512:6;19520;19528;19536;19544;19552;19605:2;19593:9;19584:7;19580:23;19576:32;19573:52;;;19621:1;19618;19611:12;19573:52;19661:9;19648:23;-1:-1:-1;;;;;19686:6:35;19683:30;19680:50;;;19726:1;19723;19716:12;19680:50;19765:69;19826:7;19817:6;19806:9;19802:22;19765:69;:::i;:::-;19853:8;;-1:-1:-1;19739:95:35;-1:-1:-1;;19941:2:35;19926:18;;19913:32;-1:-1:-1;;;;;19957:32:35;;19954:52;;;20002:1;19999;19992:12;19954:52;20041:71;20104:7;20093:8;20082:9;20078:24;20041:71;:::i;:::-;20131:8;;-1:-1:-1;20015:97:35;-1:-1:-1;;20219:2:35;20204:18;;20191:32;-1:-1:-1;;;;;20235:32:35;;20232:52;;;20280:1;20277;20270:12;20232:52;20319:71;20382:7;20371:8;20360:9;20356:24;20319:71;:::i;:::-;19344:1106;;;;-1:-1:-1;19344:1106:35;;-1:-1:-1;19344:1106:35;;20409:8;;19344:1106;-1:-1:-1;;;19344:1106:35:o;20728:253::-;20916:3;20901:19;;20929:46;20905:9;20957:6;20929:46;:::i;20986:411::-;21239:2;21228:9;21221:21;21202:4;21277:6;21271:13;21320:2;21315;21304:9;21300:18;21293:30;21340:51;21387:2;21376:9;21372:18;21358:12;21340:51;:::i;21633:777::-;21766:6;21774;21782;21790;21843:2;21831:9;21822:7;21818:23;21814:32;21811:52;;;21859:1;21856;21849:12;21811:52;21899:9;21886:23;-1:-1:-1;;;;;21924:6:35;21921:30;21918:50;;;21964:1;21961;21954:12;21918:50;22003:69;22064:7;22055:6;22044:9;22040:22;22003:69;:::i;:::-;22091:8;;-1:-1:-1;21977:95:35;-1:-1:-1;;22179:2:35;22164:18;;22151:32;-1:-1:-1;;;;;22195:32:35;;22192:52;;;22240:1;22237;22230:12;22192:52;22279:71;22342:7;22331:8;22320:9;22316:24;22279:71;:::i;:::-;21633:777;;;;-1:-1:-1;22369:8:35;-1:-1:-1;;;;21633:777:35:o;22415:1058::-;22667:2;22679:21;;;22749:13;;22652:18;;;22771:22;;;22619:4;;22850:15;;;22824:2;22809:18;;;22619:4;22893:554;22907:6;22904:1;22901:13;22893:554;;;22972:6;22966:13;23010:2;23004:9;22999:3;22992:22;-1:-1:-1;;;;;23066:2:35;23062;23058:11;23052:18;23048:43;23043:2;23038:3;23034:12;23027:65;-1:-1:-1;;;;;23144:2:35;23140;23136:11;23130:18;23126:43;23121:2;23116:3;23112:12;23105:65;23217:4;23213:2;23209:13;23203:20;23236:53;23283:4;23278:3;23274:14;23260:12;23236:53;:::i;:::-;-1:-1:-1;23343:4:35;23335:13;23329:20;23351:10;23325:37;23318:4;23309:14;;23302:61;23434:2;23422:15;;;;;23392:6;23383:16;;;;22929:1;22922:9;22893:554;;;-1:-1:-1;23464:3:35;;22415:1058;-1:-1:-1;;;;;22415:1058:35:o;24092:127::-;24153:10;24148:3;24144:20;24141:1;24134:31;24184:4;24181:1;24174:15;24208:4;24205:1;24198:15;24224:125;24289:9;;;24310:10;;;24307:36;;;24323:18;;:::i;24354:408::-;24556:2;24538:21;;;24595:2;24575:18;;;24568:30;24634:34;24629:2;24614:18;;24607:62;-1:-1:-1;;;24700:2:35;24685:18;;24678:42;24752:3;24737:19;;24354:408::o;24767:::-;24969:2;24951:21;;;25008:2;24988:18;;;24981:30;25047:34;25042:2;25027:18;;25020:62;-1:-1:-1;;;25113:2:35;25098:18;;25091:42;25165:3;25150:19;;24767:408::o;25180:127::-;25241:10;25236:3;25232:20;25229:1;25222:31;25272:4;25269:1;25262:15;25296:4;25293:1;25286:15;25312:521;25389:4;25395:6;25455:11;25442:25;25549:2;25545:7;25534:8;25518:14;25514:29;25510:43;25490:18;25486:68;25476:96;;25568:1;25565;25558:12;25476:96;25595:33;;25647:20;;;-1:-1:-1;;;;;;25679:30:35;;25676:50;;;25722:1;25719;25712:12;25676:50;25755:4;25743:17;;-1:-1:-1;25786:14:35;25782:27;;;25772:38;;25769:58;;;25823:1;25820;25813:12;26119:375;26207:1;26225:5;26239:249;26260:1;26250:8;26247:15;26239:249;;;26310:4;26305:3;26301:14;26295:4;26292:24;26289:50;;;26319:18;;:::i;:::-;26369:1;26359:8;26355:16;26352:49;;;26383:16;;;;26352:49;26466:1;26462:16;;;;;26422:15;;26239:249;;26499:902;26548:5;26578:8;26568:80;;-1:-1:-1;26619:1:35;26633:5;;26568:80;26667:4;26657:76;;-1:-1:-1;26704:1:35;26718:5;;26657:76;26749:4;26767:1;26762:59;;;;26835:1;26830:174;;;;26742:262;;26762:59;26792:1;26783:10;;26806:5;;;26830:174;26867:3;26857:8;26854:17;26851:43;;;26874:18;;:::i;:::-;-1:-1:-1;;26930:1:35;26916:16;;26989:5;;26742:262;;27088:2;27078:8;27075:16;27069:3;27063:4;27060:13;27056:36;27050:2;27040:8;27037:16;27032:2;27026:4;27023:12;27019:35;27016:77;27013:203;;;-1:-1:-1;27125:19:35;;;27201:5;;27013:203;27248:42;-1:-1:-1;;27273:8:35;27267:4;27248:42;:::i;:::-;27326:6;27322:1;27318:6;27314:19;27305:7;27302:32;27299:58;;;27337:18;;:::i;:::-;27375:20;;26499:902;-1:-1:-1;;;26499:902:35:o;27406:131::-;27466:5;27495:36;27522:8;27516:4;27495:36;:::i;27542:168::-;27615:9;;;27646;;27663:15;;;27657:22;;27643:37;27633:71;;27684:18;;:::i;28140:128::-;28207:9;;;28228:11;;;28225:37;;;28242:18;;:::i;28273:136::-;28351:13;;28373:30;28351:13;28373:30;:::i;28414:249::-;28483:6;28536:2;28524:9;28515:7;28511:23;28507:32;28504:52;;;28552:1;28549;28542:12;28504:52;28584:9;28578:16;28603:30;28627:5;28603:30;:::i;28668:245::-;28726:6;28779:2;28767:9;28758:7;28754:23;28750:32;28747:52;;;28795:1;28792;28785:12;28747:52;28834:9;28821:23;28853:30;28877:5;28853:30;:::i;29325:407::-;29527:2;29509:21;;;29566:2;29546:18;;;29539:30;29605:34;29600:2;29585:18;;29578:62;-1:-1:-1;;;29671:2:35;29656:18;;29649:41;29722:3;29707:19;;29325:407::o;29737:245::-;29795:6;29848:2;29836:9;29827:7;29823:23;29819:32;29816:52;;;29864:1;29861;29854:12;29816:52;29903:9;29890:23;29922:30;29946:5;29922:30;:::i;30336:230::-;30406:6;30459:2;30447:9;30438:7;30434:23;30430:32;30427:52;;;30475:1;30472;30465:12;30427:52;-1:-1:-1;30520:16:35;;30336:230;-1:-1:-1;30336:230:35:o;34796:160::-;34873:13;;34926:4;34915:16;;34905:27;;34895:55;;34946:1;34943;34936:12;34961:167;35039:13;;35092:10;35081:22;;35071:33;;35061:61;;35118:1;35115;35108:12;35133:136;35211:13;;35233:30;35211:13;35233:30;:::i;35274:491::-;35327:5;35380:3;35373:4;35365:6;35361:17;35357:27;35347:55;;35398:1;35395;35388:12;35347:55;35431:6;35425:13;35470:4;35462:6;35458:17;35499:1;35520:52;35536:35;35564:6;35536:35;:::i;35520:52::-;35509:63;;35597:6;35588:7;35581:23;35637:3;35628:6;35623:3;35619:16;35616:25;35613:45;;;35654:1;35651;35644:12;35613:45;35667:67;35727:6;35720:4;35711:7;35707:18;35702:3;35667:67;:::i;35770:1192::-;35844:5;35897:3;35890:4;35882:6;35878:17;35874:27;35864:55;;35915:1;35912;35905:12;35864:55;35948:6;35942:13;-1:-1:-1;;;;;35970:6:35;35967:30;35964:56;;;36000:18;;:::i;:::-;36040:42;36076:4;36067:6;36064:1;36060:14;36056:25;36040:42;:::i;:::-;36106:3;36130:6;36125:3;36118:19;36162:4;36157:3;36153:14;36146:21;;36223:4;36213:6;36210:1;36206:14;36198:6;36194:27;36190:38;36176:52;;36251:3;36243:6;36240:15;36237:35;;;36268:1;36265;36258:12;36237:35;36304:4;36296:6;36292:17;36318:613;36334:6;36329:3;36326:15;36318:613;;;36412:4;36406:3;36401;36397:13;36393:24;36390:44;;;36430:1;36427;36420:12;36390:44;36460:22;;:::i;:::-;36535:10;;36558:22;;36648:4;36639:14;;;36633:21;36674:16;;;36667:33;36736:41;36773:2;36764:12;;36736:41;:::i;:::-;36731:2;36724:5;36720:14;36713:65;36814:41;36851:2;36846:3;36842:12;36814:41;:::i;:::-;36809:2;36798:14;;36791:65;36869:18;;36916:4;36907:14;;;;36360:4;36351:14;36318:613;;;-1:-1:-1;36949:7:35;35770:1192;-1:-1:-1;;;;;35770:1192:35:o;36967:132::-;37043:13;;37065:28;37043:13;37065:28;:::i;37104:1855::-;37219:6;37227;37235;37288:2;37276:9;37267:7;37263:23;37259:32;37256:52;;;37304:1;37301;37294:12;37256:52;37337:9;37331:16;-1:-1:-1;;;;;37362:6:35;37359:30;37356:50;;;37402:1;37399;37392:12;37356:50;37425:22;;37481:6;37463:16;;;37459:29;37456:49;;;37501:1;37498;37491:12;37456:49;37527:22;;:::i;:::-;37572:31;37600:2;37572:31;:::i;:::-;37565:5;37558:46;37636:41;37673:2;37669;37665:11;37636:41;:::i;:::-;37631:2;37624:5;37620:14;37613:65;37710:41;37747:2;37743;37739:11;37710:41;:::i;:::-;37705:2;37698:5;37694:14;37687:65;37784:41;37821:2;37817;37813:11;37784:41;:::i;:::-;37779:2;37768:14;;37761:65;37885:3;37877:12;;;37871:19;37906:15;;;37899:32;37964:42;38001:3;37993:12;;37964:42;:::i;:::-;37958:3;37951:5;37947:15;37940:67;38040:41;38076:3;38072:2;38068:12;38040:41;:::i;:::-;38034:3;38027:5;38023:15;38016:66;38121:3;38117:2;38113:12;38107:19;-1:-1:-1;;;;;38141:8:35;38138:32;38135:52;;;38183:1;38180;38173:12;38135:52;38220:55;38267:7;38256:8;38252:2;38248:17;38220:55;:::i;:::-;38214:3;38207:5;38203:15;38196:80;;38309:42;38346:3;38342:2;38338:12;38309:42;:::i;:::-;38303:3;38296:5;38292:15;38285:67;38391:3;38387:2;38383:12;38377:19;-1:-1:-1;;;;;38411:8:35;38408:32;38405:52;;;38453:1;38450;38443:12;38405:52;38490:76;38558:7;38547:8;38543:2;38539:17;38490:76;:::i;:::-;38484:3;38473:15;;38466:101;-1:-1:-1;38626:3:35;38618:12;;;38612:19;38647:15;;;38640:32;;;;38477:5;-1:-1:-1;38715:46:35;38757:2;38742:18;;38715:46;:::i;:::-;38705:56;;38807:2;38796:9;38792:18;38786:25;-1:-1:-1;;;;;38826:8:35;38823:32;38820:52;;;38868:1;38865;38858:12;38820:52;38891:62;38945:7;38934:8;38923:9;38919:24;38891:62;:::i;:::-;38881:72;;;37104:1855;;;;;:::o;39469:597::-;39838:2;39827:9;39820:21;39801:4;39864:66;39926:2;39915:9;39911:18;39903:6;39864:66;:::i;:::-;39978:9;39970:6;39966:22;39961:2;39950:9;39946:18;39939:50;40006:54;40053:6;40045;40006:54;:::i;41470:194::-;-1:-1:-1;;;;;41568:26:35;;;41540;;;41536:59;;41607:28;;41604:54;;;41638:18;;:::i;41669:249::-;41769:2;41758:17;;;41739;;;;41735:41;-1:-1:-1;;;;;;41791:50:35;;41853:34;41843:45;;41788:101;41785:127;;;41892:18;;:::i;41923:243::-;-1:-1:-1;;;;;42038:42:35;;;41994;;;41990:91;;42093:44;;42090:70;;;42140:18;;:::i;42171:127::-;42232:10;42227:3;42223:20;42220:1;42213:31;42263:4;42260:1;42253:15;42287:4;42284:1;42277:15;42303:305;42342:1;42384;42380:2;42369:17;42421:1;42417:2;42406:17;42442:3;42432:37;;42449:18;;:::i;:::-;-1:-1:-1;;;;;;42485:48:35;;-1:-1:-1;;42535:15:35;;42481:70;42478:96;;;42554:18;;:::i;:::-;42588:14;;;42303:305;-1:-1:-1;;;42303:305:35:o;42613:227::-;42653:1;-1:-1:-1;;;;;42684:1:35;42680:42;42741:3;42731:37;;42748:18;;:::i;:::-;42830:3;-1:-1:-1;;;;;42790:1:35;42786:42;42782:52;42777:57;;;42613:227;;;;:::o;42845:268::-;-1:-1:-1;;;;;42929:26:35;;;42957;;;42925:59;43004:36;;;;43059:24;;;43049:58;;43087:18;;:::i;43118:194::-;43157:1;-1:-1:-1;;;;;43188:1:35;43184:26;43229:3;43219:37;;43236:18;;:::i;:::-;43302:3;-1:-1:-1;;;;;43278:1:35;43274:26;43270:36;43265:41;;;43118:194;;;;:::o;43731:206::-;43800:6;43853:2;43841:9;43832:7;43828:23;43824:32;43821:52;;;43869:1;43866;43859:12;43821:52;43892:39;43921:9;43892:39;:::i;44349:287::-;44478:3;44516:6;44510:13;44532:66;44591:6;44586:3;44579:4;44571:6;44567:17;44532:66;:::i;:::-;44614:16;;;;;44349:287;-1:-1:-1;;44349:287:35:o;44641:331::-;44746:9;44757;44799:8;44787:10;44784:24;44781:44;;;44821:1;44818;44811:12;44781:44;44850:6;44840:8;44837:20;44834:40;;;44870:1;44867;44860:12;44834:40;-1:-1:-1;;44896:23:35;;;44941:25;;;;;-1:-1:-1;44641:331:35:o;44977:388::-;45134:2;45123:9;45116:21;45173:6;45168:2;45157:9;45153:18;45146:34;45230:6;45222;45217:2;45206:9;45202:18;45189:48;45286:1;45257:22;;;45281:2;45253:31;;;45246:42;;;;45349:2;45328:15;;;-1:-1:-1;;45324:29:35;45309:45;45305:54;;44977:388;-1:-1:-1;44977:388:35:o;45370:385::-;45584:3;45579;45575:13;45566:6;45561:3;45557:16;45553:36;45548:3;45541:49;45523:3;45619:6;45613:13;45635:74;45702:6;45698:1;45693:3;45689:11;45682:4;45674:6;45670:17;45635:74;:::i;:::-;45729:16;;;;45747:1;45725:24;;45370:385;-1:-1:-1;;;45370:385:35:o
Swarm Source
ipfs://7614ca7dd4837854d002383e05473e986de5f533c5b55d8daa58016d90e4b49c
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$851.92
Net Worth in MON
Token Allocations
ETH
100.00%
MNT
0.00%
BTTC
0.00%
Others
0.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| BLAST | 100.00% | $2,958.07 | 0.288 | $851.92 | |
| MANTLE | <0.01% | $0.90473 | 0.0001001 | $0.000091 | |
| LINEA | <0.01% | $2,957.98 | 0.000000001001 | $0.000003 | |
| BTTC | <0.01% | <$0.000001 | 1 | <$0.000001 | |
| ETH | <0.01% | $2,957.98 | 0.0000000001 | <$0.000001 | |
| SCROLL | <0.01% | $2,957.98 | 0.0000000000000353 | <$0.000001 | |
| BASE | <0.01% | $2,957.95 | 0.000000000000000018 | <$0.000001 | |
| OPBNB | <0.01% | $886.97 | 0.000000000000000001 | <$0.000001 |
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.