Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
PythUpgradable
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity 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: 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;
}// 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 (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.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.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 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;
}// 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 (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.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: 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.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
}
}
}// 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);
function getValidTimePeriod()
public
view
virtual
override
returns (uint validTimePeriod);
function getPrice(
bytes32 id
) external view virtual override returns (PythStructs.Price memory price) {
return getPriceNoOlderThan(id, getValidTimePeriod());
}
function getEmaPrice(
bytes32 id
) external view virtual override returns (PythStructs.Price memory price) {
return getEmaPriceNoOlderThan(id, getValidTimePeriod());
}
function getPriceUnsafe(
bytes32 id
) public view virtual override returns (PythStructs.Price memory price) {
PythStructs.PriceFeed memory priceFeed = queryPriceFeed(id);
return priceFeed.price;
}
function getPriceNoOlderThan(
bytes32 id,
uint age
) public view virtual override returns (PythStructs.Price memory price) {
price = getPriceUnsafe(id);
if (diff(block.timestamp, price.publishTime) > age)
revert PythErrors.StalePrice();
return price;
}
function getEmaPriceUnsafe(
bytes32 id
) public view virtual override returns (PythStructs.Price memory price) {
PythStructs.PriceFeed memory priceFeed = queryPriceFeed(id);
return priceFeed.emaPrice;
}
function getEmaPriceNoOlderThan(
bytes32 id,
uint age
) public view virtual override returns (PythStructs.Price memory price) {
price = getEmaPriceUnsafe(id);
if (diff(block.timestamp, price.publishTime) > age)
revert PythErrors.StalePrice();
return price;
}
function diff(uint x, uint y) internal pure returns (uint) {
if (x > y) {
return x - y;
} else {
return y - x;
}
}
// Access modifier is overridden to public to be able to call it locally.
function updatePriceFeeds(
bytes[] calldata updateData
) public payable virtual override;
function updatePriceFeedsIfNecessary(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64[] calldata publishTimes
) external payable virtual override {
if (priceIds.length != publishTimes.length)
revert PythErrors.InvalidArgument();
for (uint i = 0; i < priceIds.length; i++) {
if (
!priceFeedExists(priceIds[i]) ||
queryPriceFeed(priceIds[i]).price.publishTime < publishTimes[i]
) {
updatePriceFeeds(updateData);
return;
}
}
revert PythErrors.NoFreshUpdate();
}
function parsePriceFeedUpdates(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minPublishTime,
uint64 maxPublishTime
)
external
payable
virtual
override
returns (PythStructs.PriceFeed[] memory priceFeeds);
function parsePriceFeedUpdatesUnique(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minPublishTime,
uint64 maxPublishTime
)
external
payable
virtual
override
returns (PythStructs.PriceFeed[] memory priceFeeds);
}// 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 period (in seconds) that a price feed is considered valid since its publish time
function getValidTimePeriod() external view returns (uint validTimePeriod);
/// @notice Returns the price and confidence interval.
/// @dev Reverts if the price has not been updated within the last `getValidTimePeriod()` seconds.
/// @param id The Pyth Price Feed ID of which to fetch the price and confidence interval.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getPrice(
bytes32 id
) external view returns (PythStructs.Price memory price);
/// @notice Returns the exponentially-weighted moving average price and confidence interval.
/// @dev Reverts if the EMA price is not available.
/// @param id The Pyth Price Feed ID of which to fetch the EMA price and confidence interval.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getEmaPrice(
bytes32 id
) external view returns (PythStructs.Price memory price);
/// @notice Returns the price of a price feed without any sanity checks.
/// @dev This function returns the most recent price update in this contract without any recency checks.
/// This function is unsafe as the returned price update may be arbitrarily far in the past.
///
/// Users of this function should check the `publishTime` in the price to ensure that the returned price is
/// sufficiently recent for their application. If you are considering using this function, it may be
/// safer / easier to use either `getPrice` or `getPriceNoOlderThan`.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getPriceUnsafe(
bytes32 id
) external view returns (PythStructs.Price memory price);
/// @notice Returns the price that is no older than `age` seconds of the current time.
/// @dev This function is a sanity-checked version of `getPriceUnsafe` which is useful in
/// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently
/// recently.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getPriceNoOlderThan(
bytes32 id,
uint age
) external view returns (PythStructs.Price memory price);
/// @notice Returns the exponentially-weighted moving average price of a price feed without any sanity checks.
/// @dev This function returns the same price as `getEmaPrice` in the case where the price is available.
/// However, if the price is not recent this function returns the latest available price.
///
/// The returned price can be from arbitrarily far in the past; this function makes no guarantees that
/// the returned price is recent or useful for any particular application.
///
/// Users of this function should check the `publishTime` in the price to ensure that the returned price is
/// sufficiently recent for their application. If you are considering using this function, it may be
/// safer / easier to use either `getEmaPrice` or `getEmaPriceNoOlderThan`.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getEmaPriceUnsafe(
bytes32 id
) external view returns (PythStructs.Price memory price);
/// @notice Returns the exponentially-weighted moving average price that is no older than `age` seconds
/// of the current time.
/// @dev This function is a sanity-checked version of `getEmaPriceUnsafe` which is useful in
/// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently
/// recently.
/// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.
function getEmaPriceNoOlderThan(
bytes32 id,
uint age
) external view returns (PythStructs.Price memory price);
/// @notice Update price feeds with given update messages.
/// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
/// `getUpdateFee` with the length of the `updateData` array.
/// Prices will be updated if they are more recent than the current stored prices.
/// The call will succeed even if the update is not the most recent.
/// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid.
/// @param updateData Array of price update data.
function updatePriceFeeds(bytes[] calldata updateData) external payable;
/// @notice Wrapper around updatePriceFeeds that rejects fast if a price update is not necessary. A price update is
/// necessary if the current on-chain publishTime is older than the given publishTime. It relies solely on the
/// given `publishTimes` for the price feeds and does not read the actual price update publish time within `updateData`.
///
/// This method requires the caller to pay a fee in wei; the required fee can be computed by calling
/// `getUpdateFee` with the length of the `updateData` array.
///
/// `priceIds` and `publishTimes` are two arrays with the same size that correspond to senders known publishTime
/// of each priceId when calling this method. If all of price feeds within `priceIds` have updated and have
/// a newer or equal publish time than the given publish time, it will reject the transaction to save gas.
/// Otherwise, it calls updatePriceFeeds method to update the prices.
///
/// @dev Reverts if update is not needed or the transferred fee is not sufficient or the updateData is invalid.
/// @param updateData Array of price update data.
/// @param priceIds Array of price ids.
/// @param publishTimes Array of publishTimes. `publishTimes[i]` corresponds to known `publishTime` of `priceIds[i]`
function updatePriceFeedsIfNecessary(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64[] calldata publishTimes
) external payable;
/// @notice Returns the required fee to update an array of price updates.
/// @param updateData Array of price update data.
/// @return feeAmount The required fee in Wei.
function getUpdateFee(
bytes[] calldata updateData
) external view returns (uint feeAmount);
/// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published
/// within `minPublishTime` and `maxPublishTime`.
///
/// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price;
/// otherwise, please consider using `updatePriceFeeds`. This method 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.
///
///
/// @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 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: 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 a batch price update is processed successfully.
/// @param chainId ID of the source chain that the batch price update comes from.
/// @param sequenceNumber Sequence number of the batch price update.
event BatchPriceFeedUpdate(uint16 chainId, uint64 sequenceNumber);
}// 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();
}// 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;
}
}// 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: 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; } }
// 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: 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 "../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 updatePriceBatchFromVm(bytes calldata encodedVm) private {
parseAndProcessBatchPriceAttestation(
parseAndVerifyBatchAttestationVM(encodedVm)
);
}
function updatePriceFeeds(
bytes[] calldata updateData
) public payable override {
uint totalNumUpdates = 0;
for (uint i = 0; i < updateData.length; ) {
if (
updateData[i].length > 4 &&
UnsafeCalldataBytesLib.toUint32(updateData[i], 0) ==
ACCUMULATOR_MAGIC
) {
totalNumUpdates += updatePriceInfosFromAccumulatorUpdate(
updateData[i]
);
} else {
updatePriceBatchFromVm(updateData[i]);
totalNumUpdates += 1;
}
unchecked {
i++;
}
}
uint requiredFee = getTotalFee(totalNumUpdates);
if (msg.value < requiredFee) revert PythErrors.InsufficientFee();
}
/// This method is deprecated, please use the `getUpdateFee(bytes[])` instead.
function getUpdateFee(
uint updateDataSize
) public view returns (uint feeAmount) {
// 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;
}
function getUpdateFee(
bytes[] calldata updateData
) public view override returns (uint feeAmount) {
uint totalNumUpdates = 0;
for (uint i = 0; i < updateData.length; i++) {
if (
updateData[i].length > 4 &&
UnsafeCalldataBytesLib.toUint32(updateData[i], 0) ==
ACCUMULATOR_MAGIC
) {
(
uint offset,
UpdateType updateType
) = extractUpdateTypeFromAccumulatorHeader(updateData[i]);
if (updateType != UpdateType.WormholeMerkle) {
revert PythErrors.InvalidUpdateData();
}
totalNumUpdates += parseWormholeMerkleHeaderNumUpdates(
updateData[i],
offset
);
} else {
totalNumUpdates += 1;
}
}
return getTotalFee(totalNumUpdates);
}
function verifyPythVM(
IWormhole.VM memory vm
) private view returns (bool valid) {
return isValidDataSource(vm.emitterChainId, vm.emitterAddress);
}
function parseAndProcessBatchPriceAttestation(
IWormhole.VM memory vm
) internal {
// Most of the math operations below are simple additions.
// In the places that there is more complex operation there is
// a comment explaining why it is safe. Also, byteslib
// operations have proper require.
unchecked {
bytes memory encoded = vm.payload;
(
uint index,
uint nAttestations,
uint attestationSize
) = parseBatchAttestationHeader(encoded);
// Deserialize each attestation
for (uint j = 0; j < nAttestations; j++) {
(
PythInternalStructs.PriceInfo memory info,
bytes32 priceId
) = parseSingleAttestationFromBatch(
encoded,
index,
attestationSize
);
// Respect specified attestation size for forward-compat
index += attestationSize;
// Store the attestation
updateLatestPriceIfNecessary(priceId, info);
}
emit BatchPriceFeedUpdate(vm.emitterChainId, vm.sequence);
}
}
function parseSingleAttestationFromBatch(
bytes memory encoded,
uint index,
uint attestationSize
)
internal
pure
returns (PythInternalStructs.PriceInfo memory info, bytes32 priceId)
{
unchecked {
// NOTE: We don't advance the global index immediately.
// attestationIndex is an attestation-local offset used
// for readability and easier debugging.
uint attestationIndex = 0;
// Unused bytes32 product id
attestationIndex += 32;
priceId = UnsafeBytesLib.toBytes32(
encoded,
index + attestationIndex
);
attestationIndex += 32;
info.price = int64(
UnsafeBytesLib.toUint64(encoded, index + attestationIndex)
);
attestationIndex += 8;
info.conf = UnsafeBytesLib.toUint64(
encoded,
index + attestationIndex
);
attestationIndex += 8;
info.expo = int32(
UnsafeBytesLib.toUint32(encoded, index + attestationIndex)
);
attestationIndex += 4;
info.emaPrice = int64(
UnsafeBytesLib.toUint64(encoded, index + attestationIndex)
);
attestationIndex += 8;
info.emaConf = UnsafeBytesLib.toUint64(
encoded,
index + attestationIndex
);
attestationIndex += 8;
{
// Status is an enum (encoded as uint8) with the following values:
// 0 = UNKNOWN: The price feed is not currently updating for an unknown reason.
// 1 = TRADING: The price feed is updating as expected.
// 2 = HALTED: The price feed is not currently updating because trading in the product has been halted.
// 3 = AUCTION: The price feed is not currently updating because an auction is setting the price.
uint8 status = UnsafeBytesLib.toUint8(
encoded,
index + attestationIndex
);
attestationIndex += 1;
// Unused uint32 numPublishers
attestationIndex += 4;
// Unused uint32 numPublishers
attestationIndex += 4;
// Unused uint64 attestationTime
attestationIndex += 8;
info.publishTime = UnsafeBytesLib.toUint64(
encoded,
index + attestationIndex
);
attestationIndex += 8;
if (status == 1) {
// status == TRADING
attestationIndex += 24;
} else {
// If status is not trading then the latest available price is
// the previous price info that are passed here.
// Previous publish time
info.publishTime = UnsafeBytesLib.toUint64(
encoded,
index + attestationIndex
);
attestationIndex += 8;
// Previous price
info.price = int64(
UnsafeBytesLib.toUint64(
encoded,
index + attestationIndex
)
);
attestationIndex += 8;
// Previous confidence
info.conf = UnsafeBytesLib.toUint64(
encoded,
index + attestationIndex
);
attestationIndex += 8;
}
}
if (attestationIndex > attestationSize)
revert PythErrors.InvalidUpdateData();
}
}
// This is an overwrite of the same method in AbstractPyth.sol
// to be more gas efficient.
function updatePriceFeedsIfNecessary(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64[] calldata publishTimes
) external payable override {
if (priceIds.length != publishTimes.length)
revert PythErrors.InvalidArgument();
for (uint i = 0; i < priceIds.length; ) {
// If the price does not exist, then the publish time is zero and
// this condition will work fine.
if (latestPriceInfoPublishTime(priceIds[i]) < publishTimes[i]) {
updatePriceFeeds(updateData);
return;
}
unchecked {
i++;
}
}
revert PythErrors.NoFreshUpdate();
}
// This is an overwrite of the same method in AbstractPyth.sol
// to be more gas efficient. It cannot move to PythGetters as it
// is overwriting the interface. Even indirect calling of a similar
// method from PythGetter has some gas overhead.
function getPriceUnsafe(
bytes32 id
) public view override returns (PythStructs.Price memory price) {
PythInternalStructs.PriceInfo storage info = _state.latestPriceInfo[id];
price.publishTime = info.publishTime;
price.expo = info.expo;
price.price = info.price;
price.conf = info.conf;
if (price.publishTime == 0) revert PythErrors.PriceFeedNotFound();
}
// This is an overwrite of the same method in AbstractPyth.sol
// to be more gas efficient. It cannot move to PythGetters as it
// is overwriting the interface. Even indirect calling of a similar
// method from PythGetter has some gas overhead.
function getEmaPriceUnsafe(
bytes32 id
) public view override returns (PythStructs.Price memory price) {
PythInternalStructs.PriceInfo storage info = _state.latestPriceInfo[id];
price.publishTime = info.publishTime;
price.expo = info.expo;
price.price = info.emaPrice;
price.conf = info.emaConf;
if (price.publishTime == 0) revert PythErrors.PriceFeedNotFound();
}
function parseBatchAttestationHeader(
bytes memory encoded
)
internal
pure
returns (uint index, uint nAttestations, uint attestationSize)
{
unchecked {
index = 0;
// Check header
{
uint32 magic = UnsafeBytesLib.toUint32(encoded, index);
index += 4;
if (magic != 0x50325748) revert PythErrors.InvalidUpdateData();
uint16 versionMajor = UnsafeBytesLib.toUint16(encoded, index);
index += 2;
if (versionMajor != 3) revert PythErrors.InvalidUpdateData();
// This value is only used as the check below which currently
// never reverts
// uint16 versionMinor = UnsafeBytesLib.toUint16(encoded, index);
index += 2;
// This check is always false as versionMinor is 0, so it is commented.
// in the future that the minor version increases this will have effect.
// if(versionMinor < 0) revert InvalidUpdateData();
uint16 hdrSize = UnsafeBytesLib.toUint16(encoded, index);
index += 2;
// NOTE(2022-04-19): Currently, only payloadId comes after
// hdrSize. Future extra header fields must be read using a
// separate offset to respect hdrSize, i.e.:
//
// uint hdrIndex = 0;
// bpa.header.payloadId = UnsafeBytesLib.toUint8(encoded, index + hdrIndex);
// hdrIndex += 1;
//
// bpa.header.someNewField = UnsafeBytesLib.toUint32(encoded, index + hdrIndex);
// hdrIndex += 4;
//
// // Skip remaining unknown header bytes
// index += bpa.header.hdrSize;
uint8 payloadId = UnsafeBytesLib.toUint8(encoded, index);
// Skip remaining unknown header bytes
index += hdrSize;
// Payload ID of 2 required for batch headerBa
if (payloadId != 2) revert PythErrors.InvalidUpdateData();
}
// Parse the number of attestations
nAttestations = UnsafeBytesLib.toUint16(encoded, index);
index += 2;
// Parse the attestation size
attestationSize = UnsafeBytesLib.toUint16(encoded, index);
index += 2;
// Given the message is valid the arithmetic below should not overflow, and
// even if it overflows then the require would fail.
if (encoded.length != (index + (attestationSize * nAttestations)))
revert PythErrors.InvalidUpdateData();
}
}
function parseAndVerifyBatchAttestationVM(
bytes calldata encodedVm
) internal view returns (IWormhole.VM memory vm) {
{
bool valid;
(vm, valid, ) = wormhole().parseAndVerifyVM(encodedVm);
if (!valid) revert PythErrors.InvalidWormholeVaa();
}
if (!verifyPythVM(vm)) revert PythErrors.InvalidUpdateDataSource();
}
function parsePriceFeedUpdatesInternal(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
PythInternalStructs.ParseConfig memory config
) internal returns (PythStructs.PriceFeed[] memory priceFeeds) {
{
uint requiredFee = getUpdateFee(updateData);
if (msg.value < requiredFee) revert PythErrors.InsufficientFee();
}
unchecked {
priceFeeds = new PythStructs.PriceFeed[](priceIds.length);
for (uint i = 0; i < updateData.length; i++) {
if (
updateData[i].length > 4 &&
UnsafeCalldataBytesLib.toUint32(updateData[i], 0) ==
ACCUMULATOR_MAGIC
) {
uint offset;
{
UpdateType updateType;
(
offset,
updateType
) = extractUpdateTypeFromAccumulatorHeader(
updateData[i]
);
if (updateType != UpdateType.WormholeMerkle) {
revert PythErrors.InvalidUpdateData();
}
}
bytes20 digest;
uint8 numUpdates;
bytes calldata encoded;
(
offset,
digest,
numUpdates,
encoded
) = extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedFromAccumulatorUpdate(
updateData[i],
offset
);
for (uint j = 0; j < numUpdates; j++) {
PythInternalStructs.PriceInfo memory priceInfo;
bytes32 priceId;
uint64 prevPublishTime;
(
offset,
priceInfo,
priceId,
prevPublishTime
) = extractPriceInfoFromMerkleProof(
digest,
encoded,
offset
);
updateLatestPriceIfNecessary(priceId, priceInfo);
{
// check whether caller requested for this data
uint k = findIndexOfPriceId(priceIds, priceId);
// If priceFeed[k].id != 0 then it means that there was a valid
// update for priceIds[k] and we don't need to process this one.
if (k == priceIds.length || priceFeeds[k].id != 0) {
continue;
}
uint publishTime = uint(priceInfo.publishTime);
// Check the publish time of the price is within the given range
// and only fill the priceFeedsInfo if it is.
// If is not, default id value of 0 will still be set and
// this will allow other updates for this price id to be processed.
if (
publishTime >= config.minPublishTime &&
publishTime <= config.maxPublishTime &&
(!config.checkUniqueness ||
config.minPublishTime > prevPublishTime)
) {
fillPriceFeedFromPriceInfo(
priceFeeds,
k,
priceId,
priceInfo,
publishTime
);
}
}
}
if (offset != encoded.length)
revert PythErrors.InvalidUpdateData();
} else {
bytes memory encoded;
{
IWormhole.VM
memory vm = parseAndVerifyBatchAttestationVM(
updateData[i]
);
encoded = vm.payload;
}
/** Batch price logic */
// TODO: gas optimization
(
uint index,
uint nAttestations,
uint attestationSize
) = parseBatchAttestationHeader(encoded);
// Deserialize each attestation
for (uint j = 0; j < nAttestations; j++) {
// NOTE: We don't advance the global index immediately.
// attestationIndex is an attestation-local offset used
// for readability and easier debugging.
uint attestationIndex = 0;
// Unused bytes32 product id
attestationIndex += 32;
bytes32 priceId = UnsafeBytesLib.toBytes32(
encoded,
index + attestationIndex
);
// check whether caller requested for this data
uint k = findIndexOfPriceId(priceIds, priceId);
// If priceFeed[k].id != 0 then it means that there was a valid
// update for priceIds[k] and we don't need to process this one.
if (k == priceIds.length || priceFeeds[k].id != 0) {
index += attestationSize;
continue;
}
(
PythInternalStructs.PriceInfo memory priceInfo,
) = parseSingleAttestationFromBatch(
encoded,
index,
attestationSize
);
updateLatestPriceIfNecessary(priceId, priceInfo);
uint publishTime = uint(priceInfo.publishTime);
// Check the publish time of the price is within the given range
// and only fill the priceFeedsInfo if it is.
// If is not, default id value of 0 will still be set and
// this will allow other updates for this price id to be processed.
if (
publishTime >= config.minPublishTime &&
publishTime <= config.maxPublishTime &&
!config.checkUniqueness // do not allow batch updates to be used by parsePriceFeedUpdatesUnique
) {
fillPriceFeedFromPriceInfo(
priceFeeds,
k,
priceId,
priceInfo,
publishTime
);
}
index += attestationSize;
}
}
}
for (uint k = 0; k < priceIds.length; k++) {
if (priceFeeds[k].id == 0) {
revert PythErrors.PriceFeedNotFoundWithinRange();
}
}
}
}
function parsePriceFeedUpdates(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minPublishTime,
uint64 maxPublishTime
)
external
payable
override
returns (PythStructs.PriceFeed[] memory priceFeeds)
{
return
parsePriceFeedUpdatesInternal(
updateData,
priceIds,
PythInternalStructs.ParseConfig(
minPublishTime,
maxPublishTime,
false
)
);
}
function parsePriceFeedUpdatesUnique(
bytes[] calldata updateData,
bytes32[] calldata priceIds,
uint64 minPublishTime,
uint64 maxPublishTime
)
external
payable
override
returns (PythStructs.PriceFeed[] memory priceFeeds)
{
return
parsePriceFeedUpdatesInternal(
updateData,
priceIds,
PythInternalStructs.ParseConfig(
minPublishTime,
maxPublishTime,
true
)
);
}
function getTotalFee(
uint totalNumUpdates
) private view returns (uint requiredFee) {
return totalNumUpdates * singleUpdateFeeInWei();
}
function findIndexOfPriceId(
bytes32[] calldata priceIds,
bytes32 targetPriceId
) private pure returns (uint index) {
uint k = 0;
for (; k < priceIds.length; k++) {
if (priceIds[k] == targetPriceId) {
break;
}
}
return k;
}
function fillPriceFeedFromPriceInfo(
PythStructs.PriceFeed[] memory priceFeeds,
uint k,
bytes32 priceId,
PythInternalStructs.PriceInfo memory info,
uint publishTime
) private pure {
priceFeeds[k].id = priceId;
priceFeeds[k].price.price = info.price;
priceFeeds[k].price.conf = info.conf;
priceFeeds[k].price.expo = info.expo;
priceFeeds[k].price.publishTime = publishTime;
priceFeeds[k].emaPrice.price = info.emaPrice;
priceFeeds[k].emaPrice.conf = info.emaConf;
priceFeeds[k].emaPrice.expo = info.expo;
priceFeeds[k].emaPrice.publishTime = publishTime;
}
function queryPriceFeed(
bytes32 id
) public view override returns (PythStructs.PriceFeed memory priceFeed) {
// Look up the latest price info for the given ID
PythInternalStructs.PriceInfo memory info = latestPriceInfo(id);
if (info.publishTime == 0) revert PythErrors.PriceFeedNotFound();
priceFeed.id = id;
priceFeed.price.price = info.price;
priceFeed.price.conf = info.conf;
priceFeed.price.expo = info.expo;
priceFeed.price.publishTime = uint(info.publishTime);
priceFeed.emaPrice.price = info.emaPrice;
priceFeed.emaPrice.conf = info.emaConf;
priceFeed.emaPrice.expo = info.expo;
priceFeed.emaPrice.publishTime = uint(info.publishTime);
}
function priceFeedExists(bytes32 id) public view override returns (bool) {
return (latestPriceInfoPublishTime(id) != 0);
}
function getValidTimePeriod() public view override returns (uint) {
return validTimePeriodSeconds();
}
function version() public pure returns (string memory) {
return "1.4.3";
}
}// 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
}
// This method is also used by batch attestation but moved here
// as the batch attestation will deprecate soon.
function parseAndVerifyPythVM(
bytes calldata encodedVm
) internal view returns (IWormhole.VM memory vm) {
{
bool valid;
(vm, valid, ) = wormhole().parseAndVerifyVM(encodedVm);
if (!valid) revert PythErrors.InvalidWormholeVaa();
}
if (!isValidDataSource(vm.emitterChainId, vm.emitterAddress))
revert PythErrors.InvalidUpdateDataSource();
}
function extractUpdateTypeFromAccumulatorHeader(
bytes calldata accumulatorUpdate
) internal pure returns (uint offset, UpdateType updateType) {
unchecked {
offset = 0;
{
uint32 magic = UnsafeCalldataBytesLib.toUint32(
accumulatorUpdate,
offset
);
offset += 4;
if (magic != ACCUMULATOR_MAGIC)
revert PythErrors.InvalidUpdateData();
uint8 majorVersion = UnsafeCalldataBytesLib.toUint8(
accumulatorUpdate,
offset
);
offset += 1;
if (majorVersion != MAJOR_VERSION)
revert PythErrors.InvalidUpdateData();
uint8 minorVersion = UnsafeCalldataBytesLib.toUint8(
accumulatorUpdate,
offset
);
offset += 1;
// Minor versions are forward compatible, so we only check
// that the minor version is not less than the minimum allowed
if (minorVersion < MINIMUM_ALLOWED_MINOR_VERSION)
revert PythErrors.InvalidUpdateData();
// This field ensure that we can add headers in the future
// without breaking the contract (future compatibility)
uint8 trailingHeaderSize = UnsafeCalldataBytesLib.toUint8(
accumulatorUpdate,
offset
);
offset += 1;
// We use another offset for the trailing header and in the end add the
// offset by trailingHeaderSize to skip the future headers.
//
// An example would be like this:
// uint trailingHeaderOffset = offset
// uint x = UnsafeBytesLib.ToUint8(accumulatorUpdate, trailingHeaderOffset)
// trailingHeaderOffset += 1
offset += trailingHeaderSize;
}
updateType = UpdateType(
UnsafeCalldataBytesLib.toUint8(accumulatorUpdate, offset)
);
offset += 1;
if (accumulatorUpdate.length < offset)
revert PythErrors.InvalidUpdateData();
}
}
function extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedFromAccumulatorUpdate(
bytes calldata accumulatorUpdate,
uint encodedOffset
)
internal
view
returns (
uint offset,
bytes20 digest,
uint8 numUpdates,
bytes calldata encoded
)
{
unchecked {
encoded = UnsafeCalldataBytesLib.slice(
accumulatorUpdate,
encodedOffset,
accumulatorUpdate.length - encodedOffset
);
offset = 0;
uint16 whProofSize = UnsafeCalldataBytesLib.toUint16(
encoded,
offset
);
offset += 2;
{
bytes memory encodedPayload;
{
IWormhole.VM memory vm = parseAndVerifyPythVM(
UnsafeCalldataBytesLib.slice(
encoded,
offset,
whProofSize
)
);
offset += whProofSize;
// TODO: Do we need to emit an update for accumulator update? If so what should we emit?
// emit AccumulatorUpdate(vm.chainId, vm.sequence);
encodedPayload = vm.payload;
}
uint payloadOffset = 0;
{
uint32 magic = UnsafeBytesLib.toUint32(
encodedPayload,
payloadOffset
);
payloadOffset += 4;
if (magic != ACCUMULATOR_WORMHOLE_MAGIC)
revert PythErrors.InvalidUpdateData();
UpdateType updateType = UpdateType(
UnsafeBytesLib.toUint8(encodedPayload, payloadOffset)
);
++payloadOffset;
if (updateType != UpdateType.WormholeMerkle)
revert PythErrors.InvalidUpdateData();
// This field is not used
// uint64 slot = UnsafeBytesLib.toUint64(encodedPayload, payloadoffset);
payloadOffset += 8;
// This field is not used
// uint32 ringSize = UnsafeBytesLib.toUint32(encodedPayload, payloadoffset);
payloadOffset += 4;
digest = bytes20(
UnsafeBytesLib.toAddress(encodedPayload, payloadOffset)
);
payloadOffset += 20;
// We don't check equality to enable future compatibility.
if (payloadOffset > encodedPayload.length)
revert PythErrors.InvalidUpdateData();
}
}
numUpdates = UnsafeCalldataBytesLib.toUint8(encoded, offset);
offset += 1;
}
}
function parseWormholeMerkleHeaderNumUpdates(
bytes calldata wormholeMerkleUpdate,
uint offset
) internal pure returns (uint8 numUpdates) {
uint16 whProofSize = UnsafeCalldataBytesLib.toUint16(
wormholeMerkleUpdate,
offset
);
offset += 2;
offset += whProofSize;
numUpdates = UnsafeCalldataBytesLib.toUint8(
wormholeMerkleUpdate,
offset
);
}
function extractPriceInfoFromMerkleProof(
bytes20 digest,
bytes calldata encoded,
uint offset
)
internal
pure
returns (
uint endOffset,
PythInternalStructs.PriceInfo memory priceInfo,
bytes32 priceId,
uint64 prevPublishTime
)
{
unchecked {
bytes calldata encodedMessage;
uint16 messageSize = UnsafeCalldataBytesLib.toUint16(
encoded,
offset
);
offset += 2;
encodedMessage = UnsafeCalldataBytesLib.slice(
encoded,
offset,
messageSize
);
offset += messageSize;
bool valid;
(valid, endOffset) = MerkleTree.isProofValid(
encoded,
offset,
digest,
encodedMessage
);
if (!valid) {
revert PythErrors.InvalidUpdateData();
}
MessageType messageType = MessageType(
UnsafeCalldataBytesLib.toUint8(encodedMessage, 0)
);
if (messageType == MessageType.PriceFeed) {
(priceInfo, priceId, prevPublishTime) = parsePriceFeedMessage(
encodedMessage,
1
);
} else {
revert PythErrors.InvalidUpdateData();
}
return (endOffset, priceInfo, priceId, prevPublishTime);
}
}
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 updatePriceInfosFromAccumulatorUpdate(
bytes calldata accumulatorUpdate
) internal returns (uint8 numUpdates) {
(
uint encodedOffset,
UpdateType updateType
) = extractUpdateTypeFromAccumulatorHeader(accumulatorUpdate);
if (updateType != UpdateType.WormholeMerkle) {
revert PythErrors.InvalidUpdateData();
}
uint offset;
bytes20 digest;
bytes calldata encoded;
(
offset,
digest,
numUpdates,
encoded
) = extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedFromAccumulatorUpdate(
accumulatorUpdate,
encodedOffset
);
unchecked {
for (uint i = 0; i < numUpdates; i++) {
PythInternalStructs.PriceInfo memory priceInfo;
bytes32 priceId;
uint64 prevPublishTime;
(
offset,
priceInfo,
priceId,
prevPublishTime
) = extractPriceInfoFromMerkleProof(digest, encoded, offset);
updateLatestPriceIfNecessary(priceId, priceInfo);
}
}
if (offset != encoded.length) revert PythErrors.InvalidUpdateData();
}
}// 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;
}
}// 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;
}
}// 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
);
function verifyGovernanceVM(
bytes memory encodedVM
) internal returns (IWormhole.VM memory parsedVM) {
(IWormhole.VM memory vm, bool valid, ) = wormhole().parseAndVerifyVM(
encodedVM
);
if (!valid) revert PythErrors.InvalidWormholeVaa();
if (!isValidGovernanceDataSource(vm.emitterChainId, vm.emitterAddress))
revert PythErrors.InvalidGovernanceDataSource();
if (vm.sequence <= lastExecutedGovernanceSequence())
revert PythErrors.OldGovernanceMessage();
setLastExecutedGovernanceSequence(vm.sequence);
return vm;
}
function executeGovernanceInstruction(bytes calldata encodedVM) public {
IWormhole.VM memory vm = verifyGovernanceVM(encodedVM);
GovernanceInstruction memory gi = parseGovernanceInstruction(
vm.payload
);
if (gi.targetChainId != chainId() && gi.targetChainId != 0)
revert PythErrors.InvalidGovernanceTarget();
if (gi.action == GovernanceAction.UpgradeContract) {
if (gi.targetChainId == 0)
revert PythErrors.InvalidGovernanceTarget();
upgradeContract(parseUpgradeContractPayload(gi.payload));
} else if (
gi.action == GovernanceAction.AuthorizeGovernanceDataSourceTransfer
) {
AuthorizeGovernanceDataSourceTransfer(
parseAuthorizeGovernanceDataSourceTransferPayload(gi.payload)
);
} else if (gi.action == GovernanceAction.SetDataSources) {
setDataSources(parseSetDataSourcesPayload(gi.payload));
} else if (gi.action == GovernanceAction.SetFee) {
setFee(parseSetFeePayload(gi.payload));
} else if (gi.action == GovernanceAction.SetValidPeriod) {
setValidPeriod(parseSetValidPeriodPayload(gi.payload));
} else if (
gi.action == GovernanceAction.RequestGovernanceDataSourceTransfer
) {
// RequestGovernanceDataSourceTransfer can be only part of AuthorizeGovernanceDataSourceTransfer message
revert PythErrors.InvalidGovernanceMessage();
} else if (gi.action == GovernanceAction.SetWormholeAddress) {
if (gi.targetChainId == 0)
revert PythErrors.InvalidGovernanceTarget();
setWormholeAddress(
parseSetWormholeAddressPayload(gi.payload),
encodedVM
);
} else {
revert PythErrors.InvalidGovernanceMessage();
}
}
function upgradeContract(UpgradeContractPayload memory payload) internal {
// This method on this contract does not have enough access to execute this, it should be executed on the
// upgradable contract.
upgradeUpgradableContract(payload);
}
function upgradeUpgradableContract(
UpgradeContractPayload memory payload
) internal virtual;
// Transfer the governance data source to a new value with sanity checks
// to ensure the new governance data source can manage the contract.
function AuthorizeGovernanceDataSourceTransfer(
AuthorizeGovernanceDataSourceTransferPayload memory payload
) internal {
PythInternalStructs.DataSource
memory oldGovernanceDatSource = governanceDataSource();
// Make sure the claimVaa is a valid VAA with RequestGovernanceDataSourceTransfer governance message
// If it's valid then its emitter can take over the governance from the current emitter.
// The VAA is checked here to ensure that the new governance data source is valid and can send message
// through wormhole.
(IWormhole.VM memory vm, bool valid, ) = wormhole().parseAndVerifyVM(
payload.claimVaa
);
if (!valid) revert PythErrors.InvalidWormholeVaa();
GovernanceInstruction memory gi = parseGovernanceInstruction(
vm.payload
);
if (gi.targetChainId != chainId() && gi.targetChainId != 0)
revert PythErrors.InvalidGovernanceTarget();
if (gi.action != GovernanceAction.RequestGovernanceDataSourceTransfer)
revert PythErrors.InvalidGovernanceMessage();
RequestGovernanceDataSourceTransferPayload
memory claimPayload = parseRequestGovernanceDataSourceTransferPayload(
gi.payload
);
// Governance data source index is used to prevent replay attacks, so a claimVaa cannot be used twice.
if (
governanceDataSourceIndex() >=
claimPayload.governanceDataSourceIndex
) revert PythErrors.OldGovernanceMessage();
setGovernanceDataSourceIndex(claimPayload.governanceDataSourceIndex);
PythInternalStructs.DataSource
memory newGovernanceDS = PythInternalStructs.DataSource(
vm.emitterChainId,
vm.emitterAddress
);
setGovernanceDataSource(newGovernanceDS);
// Setting the last executed governance to the claimVaa sequence to avoid using older sequences.
setLastExecutedGovernanceSequence(vm.sequence);
emit GovernanceDataSourceSet(
oldGovernanceDatSource,
governanceDataSource(),
lastExecutedGovernanceSequence()
);
}
function setDataSources(SetDataSourcesPayload memory payload) internal {
PythInternalStructs.DataSource[]
memory oldDataSources = validDataSources();
for (uint i = 0; i < oldDataSources.length; i += 1) {
_state.isValidDataSource[hashDataSource(oldDataSources[i])] = false;
}
delete _state.validDataSources;
for (uint i = 0; i < payload.dataSources.length; i++) {
_state.validDataSources.push(payload.dataSources[i]);
_state.isValidDataSource[
hashDataSource(payload.dataSources[i])
] = true;
}
emit DataSourcesSet(oldDataSources, validDataSources());
}
function setFee(SetFeePayload memory payload) internal {
uint oldFee = singleUpdateFeeInWei();
setSingleUpdateFeeInWei(payload.newFee);
emit FeeSet(oldFee, singleUpdateFeeInWei());
}
function setValidPeriod(SetValidPeriodPayload memory payload) internal {
uint oldValidPeriod = validTimePeriodSeconds();
setValidTimePeriodSeconds(payload.newValidPeriod);
emit ValidPeriodSet(oldValidPeriod, validTimePeriodSeconds());
}
function setWormholeAddress(
SetWormholeAddressPayload memory payload,
bytes memory encodedVM
) internal {
address oldWormholeAddress = address(wormhole());
setWormhole(payload.newWormholeAddress);
// We want to verify that the new wormhole address is valid, so we make sure that it can
// parse and verify the same governance VAA that is used to set it.
(IWormhole.VM memory vm, bool valid, ) = wormhole().parseAndVerifyVM(
encodedVM
);
if (!valid) revert PythErrors.InvalidGovernanceMessage();
if (!isValidGovernanceDataSource(vm.emitterChainId, vm.emitterAddress))
revert PythErrors.InvalidGovernanceMessage();
if (vm.sequence != lastExecutedGovernanceSequence())
revert PythErrors.InvalidWormholeAddressToSet();
GovernanceInstruction memory gi = parseGovernanceInstruction(
vm.payload
);
if (gi.action != GovernanceAction.SetWormholeAddress)
revert PythErrors.InvalidWormholeAddressToSet();
// Purposefully, we don't check whether the chainId is the same as the current chainId because
// we might want to change the chain id of the wormhole contract.
// The following check is not necessary for security, but is a sanity check that the new wormhole
// contract parses the payload correctly.
SetWormholeAddressPayload
memory newPayload = parseSetWormholeAddressPayload(gi.payload);
if (newPayload.newWormholeAddress != payload.newWormholeAddress)
revert PythErrors.InvalidWormholeAddressToSet();
emit WormholeAddressSet(oldWormholeAddress, address(wormhole()));
}
}// 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
}
struct GovernanceInstruction {
GovernanceModule module;
GovernanceAction action;
uint16 targetChainId;
bytes payload;
}
struct UpgradeContractPayload {
address newImplementation;
}
struct AuthorizeGovernanceDataSourceTransferPayload {
// Transfer governance control over this contract to another data source.
// The claimVaa field is a VAA created by the new data source; using a VAA prevents mistakes
// in the handoff by ensuring that the new data source can send VAAs (i.e., is not an invalid address).
bytes claimVaa;
}
struct RequestGovernanceDataSourceTransferPayload {
// Governance data source index is used to prevent replay attacks
// So a claimVaa cannot be used twice.
uint32 governanceDataSourceIndex;
}
struct SetDataSourcesPayload {
PythInternalStructs.DataSource[] dataSources;
}
struct SetFeePayload {
uint newFee;
}
struct SetValidPeriodPayload {
uint newValidPeriod;
}
struct SetWormholeAddressPayload {
address newWormholeAddress;
}
/// @dev Parse a GovernanceInstruction
function parseGovernanceInstruction(
bytes memory encodedInstruction
) public pure returns (GovernanceInstruction memory gi) {
uint index = 0;
uint32 magic = encodedInstruction.toUint32(index);
if (magic != MAGIC) revert PythErrors.InvalidGovernanceMessage();
index += 4;
uint8 modNumber = encodedInstruction.toUint8(index);
gi.module = GovernanceModule(modNumber);
index += 1;
if (gi.module != MODULE) revert PythErrors.InvalidGovernanceTarget();
uint8 actionNumber = encodedInstruction.toUint8(index);
gi.action = GovernanceAction(actionNumber);
index += 1;
gi.targetChainId = encodedInstruction.toUint16(index);
index += 2;
// As solidity performs math operations in a checked mode
// if the length of the encoded instruction be smaller than index
// it will revert. So we don't need any extra check.
gi.payload = encodedInstruction.slice(
index,
encodedInstruction.length - index
);
}
/// @dev Parse a UpgradeContractPayload (action 1) with minimal validation
function parseUpgradeContractPayload(
bytes memory encodedPayload
) public pure returns (UpgradeContractPayload memory uc) {
uint index = 0;
uc.newImplementation = address(encodedPayload.toAddress(index));
index += 20;
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a AuthorizeGovernanceDataSourceTransferPayload (action 2) with minimal validation
function parseAuthorizeGovernanceDataSourceTransferPayload(
bytes memory encodedPayload
)
public
pure
returns (AuthorizeGovernanceDataSourceTransferPayload memory sgds)
{
sgds.claimVaa = encodedPayload;
}
/// @dev Parse a AuthorizeGovernanceDataSourceTransferPayload (action 2) with minimal validation
function parseRequestGovernanceDataSourceTransferPayload(
bytes memory encodedPayload
)
public
pure
returns (RequestGovernanceDataSourceTransferPayload memory sgdsClaim)
{
uint index = 0;
sgdsClaim.governanceDataSourceIndex = encodedPayload.toUint32(index);
index += 4;
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a SetDataSourcesPayload (action 3) with minimal validation
function parseSetDataSourcesPayload(
bytes memory encodedPayload
) public pure returns (SetDataSourcesPayload memory sds) {
uint index = 0;
uint8 dataSourcesLength = encodedPayload.toUint8(index);
index += 1;
sds.dataSources = new PythInternalStructs.DataSource[](
dataSourcesLength
);
for (uint i = 0; i < dataSourcesLength; i++) {
sds.dataSources[i].chainId = encodedPayload.toUint16(index);
index += 2;
sds.dataSources[i].emitterAddress = encodedPayload.toBytes32(index);
index += 32;
}
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a SetFeePayload (action 4) with minimal validation
function parseSetFeePayload(
bytes memory encodedPayload
) public pure returns (SetFeePayload memory sf) {
uint index = 0;
uint64 val = encodedPayload.toUint64(index);
index += 8;
uint64 expo = encodedPayload.toUint64(index);
index += 8;
sf.newFee = uint256(val) * uint256(10) ** uint256(expo);
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a SetValidPeriodPayload (action 5) with minimal validation
function parseSetValidPeriodPayload(
bytes memory encodedPayload
) public pure returns (SetValidPeriodPayload memory svp) {
uint index = 0;
svp.newValidPeriod = uint256(encodedPayload.toUint64(index));
index += 8;
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
/// @dev Parse a UpdateWormholeAddressPayload (action 6) with minimal validation
function parseSetWormholeAddressPayload(
bytes memory encodedPayload
) public pure returns (SetWormholeAddressPayload memory sw) {
uint index = 0;
sw.newWormholeAddress = address(encodedPayload.toAddress(index));
index += 20;
if (encodedPayload.length != index)
revert PythErrors.InvalidGovernanceMessage();
}
}// 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;
struct ParseConfig {
uint64 minPublishTime;
uint64 maxPublishTime;
bool checkUniqueness;
}
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/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;
}
}// 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;
}
}
contract PythState {
PythStorage.State _state;
}// 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/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);
}{
"remappings": [],
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "istanbul",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InsufficientFee","type":"error"},{"inputs":[],"name":"InvalidArgument","type":"error"},{"inputs":[],"name":"InvalidGovernanceDataSource","type":"error"},{"inputs":[],"name":"InvalidGovernanceMessage","type":"error"},{"inputs":[],"name":"InvalidGovernanceTarget","type":"error"},{"inputs":[],"name":"InvalidUpdateData","type":"error"},{"inputs":[],"name":"InvalidUpdateDataSource","type":"error"},{"inputs":[],"name":"InvalidWormholeAddressToSet","type":"error"},{"inputs":[],"name":"InvalidWormholeVaa","type":"error"},{"inputs":[],"name":"NoFreshUpdate","type":"error"},{"inputs":[],"name":"OldGovernanceMessage","type":"error"},{"inputs":[],"name":"PriceFeedNotFound","type":"error"},{"inputs":[],"name":"PriceFeedNotFoundWithinRange","type":"error"},{"inputs":[],"name":"StalePrice","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"chainId","type":"uint16"},{"indexed":false,"internalType":"uint64","name":"sequenceNumber","type":"uint64"}],"name":"BatchPriceFeedUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"newImplementation","type":"address"}],"name":"ContractUpgraded","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource[]","name":"oldDataSources","type":"tuple[]"},{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource[]","name":"newDataSources","type":"tuple[]"}],"name":"DataSourcesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"FeeSet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource","name":"oldDataSource","type":"tuple"},{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"indexed":false,"internalType":"struct PythInternalStructs.DataSource","name":"newDataSource","type":"tuple"},{"indexed":false,"internalType":"uint64","name":"initialSequence","type":"uint64"}],"name":"GovernanceDataSourceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"publishTime","type":"uint64"},{"indexed":false,"internalType":"int64","name":"price","type":"int64"},{"indexed":false,"internalType":"uint64","name":"conf","type":"uint64"}],"name":"PriceFeedUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldValidPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValidPeriod","type":"uint256"}],"name":"ValidPeriodSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldWormholeAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newWormholeAddress","type":"address"}],"name":"WormholeAddressSet","type":"event"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedVM","type":"bytes"}],"name":"executeGovernanceInstruction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getEmaPrice","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"uint256","name":"age","type":"uint256"}],"name":"getEmaPriceNoOlderThan","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getEmaPriceUnsafe","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getPrice","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"uint256","name":"age","type":"uint256"}],"name":"getPriceNoOlderThan","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getPriceUnsafe","outputs":[{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"}],"name":"getUpdateFee","outputs":[{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"updateDataSize","type":"uint256"}],"name":"getUpdateFee","outputs":[{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getValidTimePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceDataSource","outputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governanceDataSourceIndex","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource","name":"ds","type":"tuple"}],"name":"hashDataSource","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"wormhole","type":"address"},{"internalType":"uint16[]","name":"dataSourceEmitterChainIds","type":"uint16[]"},{"internalType":"bytes32[]","name":"dataSourceEmitterAddresses","type":"bytes32[]"},{"internalType":"uint16","name":"governanceEmitterChainId","type":"uint16"},{"internalType":"bytes32","name":"governanceEmitterAddress","type":"bytes32"},{"internalType":"uint64","name":"governanceInitialSequence","type":"uint64"},{"internalType":"uint256","name":"validTimePeriodSeconds","type":"uint256"},{"internalType":"uint256","name":"singleUpdateFeeInWei","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"dataSourceChainId","type":"uint16"},{"internalType":"bytes32","name":"dataSourceEmitterAddress","type":"bytes32"}],"name":"isValidDataSource","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"governanceChainId","type":"uint16"},{"internalType":"bytes32","name":"governanceEmitterAddress","type":"bytes32"}],"name":"isValidGovernanceDataSource","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastExecutedGovernanceSequence","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"priceId","type":"bytes32"}],"name":"latestPriceInfoPublishTime","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseAuthorizeGovernanceDataSourceTransferPayload","outputs":[{"components":[{"internalType":"bytes","name":"claimVaa","type":"bytes"}],"internalType":"struct PythGovernanceInstructions.AuthorizeGovernanceDataSourceTransferPayload","name":"sgds","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedInstruction","type":"bytes"}],"name":"parseGovernanceInstruction","outputs":[{"components":[{"internalType":"enum PythGovernanceInstructions.GovernanceModule","name":"module","type":"uint8"},{"internalType":"enum PythGovernanceInstructions.GovernanceAction","name":"action","type":"uint8"},{"internalType":"uint16","name":"targetChainId","type":"uint16"},{"internalType":"bytes","name":"payload","type":"bytes"}],"internalType":"struct PythGovernanceInstructions.GovernanceInstruction","name":"gi","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"},{"internalType":"bytes32[]","name":"priceIds","type":"bytes32[]"},{"internalType":"uint64","name":"minPublishTime","type":"uint64"},{"internalType":"uint64","name":"maxPublishTime","type":"uint64"}],"name":"parsePriceFeedUpdates","outputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"emaPrice","type":"tuple"}],"internalType":"struct PythStructs.PriceFeed[]","name":"priceFeeds","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"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":"encodedPayload","type":"bytes"}],"name":"parseRequestGovernanceDataSourceTransferPayload","outputs":[{"components":[{"internalType":"uint32","name":"governanceDataSourceIndex","type":"uint32"}],"internalType":"struct PythGovernanceInstructions.RequestGovernanceDataSourceTransferPayload","name":"sgdsClaim","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetDataSourcesPayload","outputs":[{"components":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource[]","name":"dataSources","type":"tuple[]"}],"internalType":"struct PythGovernanceInstructions.SetDataSourcesPayload","name":"sds","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetFeePayload","outputs":[{"components":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"internalType":"struct PythGovernanceInstructions.SetFeePayload","name":"sf","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetValidPeriodPayload","outputs":[{"components":[{"internalType":"uint256","name":"newValidPeriod","type":"uint256"}],"internalType":"struct PythGovernanceInstructions.SetValidPeriodPayload","name":"svp","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseSetWormholeAddressPayload","outputs":[{"components":[{"internalType":"address","name":"newWormholeAddress","type":"address"}],"internalType":"struct PythGovernanceInstructions.SetWormholeAddressPayload","name":"sw","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedPayload","type":"bytes"}],"name":"parseUpgradeContractPayload","outputs":[{"components":[{"internalType":"address","name":"newImplementation","type":"address"}],"internalType":"struct PythGovernanceInstructions.UpgradeContractPayload","name":"uc","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"priceFeedExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pythUpgradableMagic","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"queryPriceFeed","outputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"price","type":"tuple"},{"components":[{"internalType":"int64","name":"price","type":"int64"},{"internalType":"uint64","name":"conf","type":"uint64"},{"internalType":"int32","name":"expo","type":"int32"},{"internalType":"uint256","name":"publishTime","type":"uint256"}],"internalType":"struct PythStructs.Price","name":"emaPrice","type":"tuple"}],"internalType":"struct PythStructs.PriceFeed","name":"priceFeed","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"singleUpdateFeeInWei","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"}],"name":"updatePriceFeeds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"updateData","type":"bytes[]"},{"internalType":"bytes32[]","name":"priceIds","type":"bytes32[]"},{"internalType":"uint64[]","name":"publishTimes","type":"uint64[]"}],"name":"updatePriceFeedsIfNecessary","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"validDataSources","outputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"bytes32","name":"emitterAddress","type":"bytes32"}],"internalType":"struct PythInternalStructs.DataSource[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"validTimePeriodSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"wormhole","outputs":[{"internalType":"contract IWormhole","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a06040523060601b6080523480156200001857600080fd5b50600054610100900460ff16158080156200003a5750600054600160ff909116105b806200006a575062000057306200014460201b62001d841760201c565b1580156200006a575060005460ff166001145b620000d25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff191660011790558015620000f6576000805461ff0019166101001790555b80156200013d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5062000153565b6001600160a01b03163b151590565b60805160601c61562d6200018e60003960008181610a9201528181610ad201528181610cac01528181610cec0152610d68015261562d6000f3fe6080604052600436106102725760003560e01c80638881016f1161014f578063b5ec0261116100c1578063d82d58a51161007a578063d82d58a514610819578063e17efd4814610852578063e18910a314610872578063e3795cc114610887578063ef9e5e281461089e578063f2fde38b146108b157600080fd5b8063b5ec02611461074c578063b6ed701e14610784578063b9256d28146107a4578063caaf43f1146107b7578063cb718a9b146107e4578063d47eed45146107f957600080fd5b80639a8a0592116101135780639a8a0592146106af578063a38d81c6146106d7578063a4ae35e0146106f9578063aac41292146105f9578063accca7f914610719578063b5dcc9111461072c57600080fd5b80638881016f146105f957806389a5bb4d146106315780638da5cb5b146106515780639474f45b1461066f57806396834ad31461068f57600080fd5b806352d1902d116101e85780636c72f51b116101ac5780636c72f51b14610504578063711a2e2814610530578063715018a6146105505780637b72bcae1461056557806384acd1bb1461059a57806387c5bd1b146105cc57600080fd5b806352d1902d1461045057806354fd4d5014610465578063586d3cf81461049957806358c67635146104b75780636b7f53ca146104d757600080fd5b8063437209a71161023a578063437209a7146103605780634716e9c51461039057806348b6404d146103b05780634c469d8c146103cf5780634d7a734e1461041d5780634f1ef2861461043d57600080fd5b8063146faf771461027757806314dd317f1461029957806331d98b3f146102cd5780633659cfe6146102fa578063426234e41461031a575b600080fd5b34801561028357600080fd5b50610297610292366004614926565b6108d1565b005b3480156102a557600080fd5b506102b96102b4366004614c53565b610a13565b604051905181526020015b60405180910390f35b3480156102d957600080fd5b506102ed6102e8366004614b96565b610a6d565b6040516102c49190615266565b34801561030657600080fd5b5061029761031536600461490c565b610a87565b34801561032657600080fd5b506040805180820182526000808252602091820152815180830190925260d05461ffff16825260d154908201526040516102c491906151db565b34801561036c57600080fd5b5061038061037b366004614e64565b610b6d565b60405190151581526020016102c4565b6103a361039e366004614b05565b610bc0565b6040516102c4919061504c565b3480156103bc57600080fd5b5060ce545b6040519081526020016102c4565b3480156103db57600080fd5b506104056103ea366004614b96565b600090815260d560205260409020546001600160401b031690565b6040516001600160401b0390911681526020016102c4565b34801561042957600080fd5b506102b9610438366004614c53565b610c09565b61029761044b3660046149e6565b610ca1565b34801561045c57600080fd5b506103c1610d5b565b34801561047157600080fd5b506040805180820182526005815264312e342e3360d81b602082015290516102c491906150ca565b3480156104a557600080fd5b5060d2546001600160401b0316610405565b3480156104c357600080fd5b506103806104d2366004614e64565b610e0e565b3480156104e357600080fd5b506104f76104f2366004614c53565b610e31565b6040516102c491906151f6565b34801561051057600080fd5b5060d45463ffffffff165b60405163ffffffff90911681526020016102c4565b34801561053c57600080fd5b506102ed61054b366004614bc6565b611035565b34801561055c57600080fd5b50610297611076565b34801561057157600080fd5b50610585610580366004614c53565b61108a565b604051905163ffffffff1681526020016102c4565b3480156105a657600080fd5b5060c9546001600160a01b03165b6040516001600160a01b0390911681526020016102c4565b3480156105d857600080fd5b506105ec6105e7366004614c53565b6110b8565b6040516102c491906152a0565b34801561060557600080fd5b50610619610614366004614c53565b611234565b60405190516001600160a01b031681526020016102c4565b34801561063d57600080fd5b506103c161064c366004614c85565b611265565b34801561065d57600080fd5b506033546001600160a01b03166105b4565b34801561067b57600080fd5b506102ed61068a366004614b96565b6112b7565b34801561069b57600080fd5b506102ed6106aa366004614b96565b611338565b3480156106bb57600080fd5b506106c46113bd565b60405161ffff90911681526020016102c4565b3480156106e357600080fd5b506106ec611446565b6040516102c49190615014565b34801561070557600080fd5b506102ed610714366004614bc6565b6114b9565b6103a3610727366004614b05565b6114ca565b34801561073857600080fd5b506102ed610747366004614b96565b611508565b34801561075857600080fd5b50610380610767366004614b96565b600090815260d560205260409020546001600160401b0316151590565b34801561079057600080fd5b5061029761079f366004614be7565b61151c565b6102976107b2366004614a70565b611836565b3480156107c357600080fd5b506107d76107d2366004614b96565b61192d565b6040516102c49190615257565b3480156107f057600080fd5b5060cf546103c1565b34801561080557600080fd5b506103c1610814366004614a31565b6119fb565b34801561082557600080fd5b50610845610834366004614c53565b604080516020810190915290815290565b6040516102c491906151c0565b34801561085e57600080fd5b506103c161086d366004614b96565b611b97565b34801561087e57600080fd5b506103c1611bb8565b34801561089357600080fd5b506397a6f30461051b565b6102976108ac366004614a31565b611bc3565b3480156108bd57600080fd5b506102976108cc36600461490c565b611d0e565b600054610100900460ff16158080156108f15750600054600160ff909116105b8061090b5750303b15801561090b575060005460ff166001145b6109735760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610996576000805461ff0019166101001790555b61099e611d93565b6109a6611dc2565b6109b88b8b8b8b8b8b8b8b8b8b611de9565b6109c0611076565b8015610a06576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050505050565b6040805160208101909152600081526000610a2e8382611fd1565b6001600160401b03168252610a446008826153c9565b905080835114610a67576040516397363b3560e01b815260040160405180910390fd5b50919050565b610a756145e2565b610a8182610714611bb8565b92915050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415610ad05760405162461bcd60e51b815260040161096a906150dd565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b0261202e565b6001600160a01b031614610b285760405162461bcd60e51b815260040161096a90615129565b610b318161204a565b610b6a8160005b6040519080825280601f01601f191660200182016040528015610b62576020820181803683370190505b506000612052565b50565b6040805160f09390931b6001600160f01b0319166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b6060610bfe878787876040518060600160405280896001600160401b03168152602001886001600160401b03168152602001600015158152506121d1565b979650505050505050565b604080516020810190915260008152600080610c258482611fd1565b9050610c326008836153c9565b91506000610c408584611fd1565b9050610c4d6008846153c9565b9250610c636001600160401b038216600a615424565b610c76906001600160401b0384166154cc565b845284518314610c99576040516397363b3560e01b815260040160405180910390fd5b505050919050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415610cea5760405162461bcd60e51b815260040161096a906150dd565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610d1c61202e565b6001600160a01b031614610d425760405162461bcd60e51b815260040161096a90615129565b610d4b8261204a565b610d5782826001612052565b5050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610dfb5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161096a565b506000805160206155b183398151915290565b60d05460009061ffff8481169116148015610e2a575060d15482145b9392505050565b610e5d604080516080810190915280600081526020016000815260006020820152606060409091015290565b600080610e6a8482612676565b905063ffffffff8116635054474d14610e96576040516397363b3560e01b815260040160405180910390fd5b610ea16004836153c9565b91506000610eaf85846126d3565b90508060ff166003811115610ed457634e487b7160e01b600052602160045260246000fd5b84906003811115610ef557634e487b7160e01b600052602160045260246000fd5b90816003811115610f1657634e487b7160e01b600052602160045260246000fd5b905250610f246001846153c9565b9250600184516003811115610f4957634e487b7160e01b600052602160045260246000fd5b14610f67576040516363daeb7760e01b815260040160405180910390fd5b6000610f7386856126d3565b90508060ff166006811115610f9857634e487b7160e01b600052602160045260246000fd5b85602001906006811115610fbc57634e487b7160e01b600052602160045260246000fd5b90816006811115610fdd57634e487b7160e01b600052602160045260246000fd5b905250610feb6001856153c9565b9350610ff7868561272f565b61ffff16604086015261100b6002856153c9565b93506110268485885161101e91906154eb565b88919061278c565b60608601525092949350505050565b61103d6145e2565b611046836112b7565b905081611057428360600151612899565b1115610a8157604051630cd5fa0760e11b815260040160405180910390fd5b61107e6128be565b6110886000612918565b565b60408051602081019091526000815260006110a58382612676565b63ffffffff168252610a446004826153c9565b6040805160208101909152606081526000806110d484826126d3565b90506110e16001836153c9565b91508060ff166001600160401b0381111561110c57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561115157816020015b604080518082019091526000808252602082015281526020019060019003908161112a5790505b50835260005b8160ff1681101561120b5761116c858461272f565b845180518390811061118e57634e487b7160e01b600052603260045260246000fd5b602090810291909101015161ffff90911690526111ac6002846153c9565b92506111b8858461296a565b84518051839081106111da57634e487b7160e01b600052603260045260246000fd5b602002602001015160200181815250506020836111f791906153c9565b9250806112038161552e565b915050611157565b508184511461122d576040516397363b3560e01b815260040160405180910390fd5b5050919050565b604080516020810190915260008152600061124f83826129c8565b6001600160a01b03168252610a446014826153c9565b60008160000151826020015160405160200161129a92919060f09290921b6001600160f01b0319168252600282015260220190565b604051602081830303815290604052805190602001209050919050565b6112bf6145e2565b600082815260d5602090815260409182902080546001600160401b0380821660608701819052600160401b92839004600390810b810b900b958701959095526001830154600781810b810b900b875291909104169184019190915290610a6757604051630295d7cd60e31b815260040160405180910390fd5b6113406145e2565b600082815260d5602090815260409182902080546001600160401b0380821660608701819052600160401b8304600390810b810b900b95870195909552600160601b8204600790810b810b900b8652600160a01b909104169184019190915290610a6757604051630295d7cd60e31b815260040160405180910390fd5b60006113d160c9546001600160a01b031690565b6001600160a01b0316639a8a05926040518163ffffffff1660e01b815260040160206040518083038186803b15801561140957600080fd5b505afa15801561141d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114419190614e48565b905090565b606060c9600301805480602002602001604051908101604052809291908181526020016000905b828210156114b05760008481526020908190206040805180820190915260028502909101805461ffff16825260019081015482840152908352909201910161146d565b50505050905090565b6114c16145e2565b61104683611338565b6060610bfe878787876040518060600160405280896001600160401b03168152602001886001600160401b03168152602001600115158152506121d1565b6115106145e2565b610a818261054b611bb8565b600061155d83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a2d92505050565b9050600061156e8260e00151610e31565b90506115786113bd565b61ffff16816040015161ffff161415801561159a5750604081015161ffff1615155b156115b8576040516363daeb7760e01b815260040160405180910390fd5b6000816020015160068111156115de57634e487b7160e01b600052602160045260246000fd5b141561162457604081015161ffff1661160a576040516363daeb7760e01b815260040160405180910390fd5b61161f61161a8260600151611234565b612b70565b611830565b60018160200151600681111561164a57634e487b7160e01b600052602160045260246000fd5b14156116715761161f61166c8260600151604080516020810190915290815290565b612b79565b60028160200151600681111561169757634e487b7160e01b600052602160045260246000fd5b14156116b25761161f6116ad82606001516110b8565b612e55565b6003816020015160068111156116d857634e487b7160e01b600052602160045260246000fd5b14156116f35761161f6116ee8260600151610c09565b612ffe565b60048160200151600681111561171957634e487b7160e01b600052602160045260246000fd5b14156117345761161f61172f8260600151610a13565b613050565b60058160200151600681111561175a57634e487b7160e01b600052602160045260246000fd5b1415611779576040516397363b3560e01b815260040160405180910390fd5b60068160200151600681111561179f57634e487b7160e01b600052602160045260246000fd5b141561181757604081015161ffff166117cb576040516363daeb7760e01b815260040160405180910390fd5b61161f6117db8260600151611234565b85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061308d92505050565b6040516397363b3560e01b815260040160405180910390fd5b50505050565b8281146118565760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b8381101561190b5782828281811061188157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906118969190614ea9565b6001600160401b03166118e48686848181106118c257634e487b7160e01b600052603260045260246000fd5b90506020020135600090815260d560205260409020546001600160401b031690565b6001600160401b03161015611903576118fd8787611bc3565b50611925565b600101611859565b50604051636f162bfd60e11b815260040160405180910390fd5b505050505050565b611935614609565b6000611940836132c1565b80519091506001600160401b031661196b57604051630295d7cd60e31b815260040160405180910390fd5b91815260408083015160208084018051600793840b840b905260608087015182516001600160401b039182169085015283880180518451600391820b820b9089015289519451948316948401949094526080890151878901805191880b90970b905260a089015186519083169501949094529251845190830b90920b919094015293519051931692019190915290565b600080805b83811015611b85576004858583818110611a2a57634e487b7160e01b600052603260045260246000fd5b9050602002810190611a3c91906152bb565b9050118015611a90575063504e4155611a88868684818110611a6e57634e487b7160e01b600052603260045260246000fd5b9050602002810190611a8091906152bb565b503560e01c90565b63ffffffff16145b15611b6557600080611ad2878785818110611abb57634e487b7160e01b600052603260045260246000fd5b9050602002810190611acd91906152bb565b613353565b90925090506000818015611af657634e487b7160e01b600052602160045260246000fd5b14611b145760405163734fff6760e11b815260040160405180910390fd5b611b4f878785818110611b3757634e487b7160e01b600052603260045260246000fd5b9050602002810190611b4991906152bb565b8461341a565b611b5c9060ff16856153c9565b93505050611b73565b611b706001836153c9565b91505b80611b7d8161552e565b915050611a00565b50611b8f81613451565b949350505050565b600081611ba360ce5490565b611bae9060ff6154cc565b610a8191906154cc565b600061144160cf5490565b6000805b82811015611ce0576004848483818110611bf157634e487b7160e01b600052603260045260246000fd5b9050602002810190611c0391906152bb565b9050118015611c3d575063504e4155611c35858584818110611a6e57634e487b7160e01b600052603260045260246000fd5b63ffffffff16145b15611c9057611c7c848483818110611c6557634e487b7160e01b600052603260045260246000fd5b9050602002810190611c7791906152bb565b613466565b611c899060ff16836153c9565b9150611cd8565b611cca848483818110611cb357634e487b7160e01b600052603260045260246000fd5b9050602002810190611cc591906152bb565b613547565b611cd56001836153c9565b91505b600101611bc7565b506000611cec82613451565b9050803410156118305760405162976f7560e21b815260040160405180910390fd5b611d166128be565b6001600160a01b038116611d7b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161096a565b610b6a81612918565b6001600160a01b03163b151590565b600054610100900460ff16611dba5760405162461bcd60e51b815260040161096a90615175565b611088613559565b600054610100900460ff166110885760405162461bcd60e51b815260040161096a90615175565b611df28a613589565b878614611e125760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b88811015611f7c57600060405180604001604052808c8c85818110611e4a57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611e5f9190614e2c565b61ffff1681526020018a8a85818110611e8857634e487b7160e01b600052603260045260246000fd5b905060200201358152509050611ea681600001518260200151610b6d565b15611ec45760405163a9cb9e0d60e01b815260040160405180910390fd5b600160cd6000611ed384611265565b81526020808201929092526040016000908120805460ff19169315159390931790925560cc8054600181018255925282517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebe6002909302928301805461ffff191661ffff90921691909117905591909101517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebf9091015580611f748161552e565b915050611e15565b506040805180820190915261ffff86168082526020820186905260d0805461ffff1916909117905560d1859055611fb2846135ab565b50611fbc8260cf55565b611fc58160ce55565b50505050505050505050565b6000611fde8260086153c9565b835110156120255760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b604482015260640161096a565b50016008015190565b6000805160206155b1833981519152546001600160a01b031690565b610b6a6128be565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561208a57612085836135ce565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b1580156120c357600080fd5b505afa9250505080156120f3575060408051601f3d908101601f191682019092526120f091810190614bae565b60015b6121565760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161096a565b6000805160206155b183398151915281146121c55760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161096a565b5061208583838361366a565b606060006121df87876119fb565b9050803410156122015760405162976f7560e21b815260040160405180910390fd5b50826001600160401b0381111561222857634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561226157816020015b61224e614609565b8152602001906001900390816122465790505b50905060005b8581101561260f57600487878381811061229157634e487b7160e01b600052603260045260246000fd5b90506020028101906122a391906152bb565b90501180156122dd575063504e41556122d5888884818110611a6e57634e487b7160e01b600052603260045260246000fd5b63ffffffff16145b156124c257600080612308898985818110611abb57634e487b7160e01b600052603260045260246000fd5b9092509050600081801561232c57634e487b7160e01b600052602160045260246000fd5b1461234a5760405163734fff6760e11b815260040160405180910390fd5b5060008036600061238c8c8c8881811061237457634e487b7160e01b600052603260045260246000fd5b905060200281019061238691906152bb565b8761368f565b93985091965094509250905060005b8360ff16811015612497576123ae614636565b6000806123bd8887878c6137d1565b929b50909450925090506123d182846138c5565b60006123de8f8f85613a07565b90508d81148061241857508b818151811061240957634e487b7160e01b600052603260045260246000fd5b60209081029190910101515115155b15612426575050505061248f565b83518d516001600160401b039182169116811080159061245357508d602001516001600160401b03168111155b801561247757508d60400151158061247757508d516001600160401b038085169116115b15612489576124898d83868885613a58565b50505050505b60010161239b565b508481146124b85760405163734fff6760e11b815260040160405180910390fd5b5050505050612607565b606060006125008989858181106124e957634e487b7160e01b600052603260045260246000fd5b90506020028101906124fb91906152bb565b613c98565b60e00151915060009050808061251584613d80565b92509250925060005b828110156126015760408486010151602090600061253d8d8d84613a07565b90508b811480612577575089818151811061256857634e487b7160e01b600052603260045260246000fd5b60209081029190910101515115155b1561258857505050928101926125f9565b6000612595898988613eaf565b5090506125a283826138c5565b80518c516001600160401b03918216911681108015906125cf57508c602001516001600160401b03168111155b80156125dd57508c60400151155b156125ef576125ef8c84868585613a58565b5050509483019450505b60010161251e565b50505050505b600101612267565b5060005b8381101561266c5781818151811061263b57634e487b7160e01b600052603260045260246000fd5b602090810291909101015151612664576040516345805f5d60e01b815260040160405180910390fd5b600101612613565b5095945050505050565b60006126838260046153c9565b835110156126ca5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7433325f6f75744f66426f756e647360601b604482015260640161096a565b50016004015190565b60006126e08260016153c9565b835110156127265760405162461bcd60e51b8152602060048201526013602482015272746f55696e74385f6f75744f66426f756e647360681b604482015260640161096a565b50016001015190565b600061273c8260026153c9565b835110156127835760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b604482015260640161096a565b50016002015190565b60608161279a81601f6153c9565b10156127d95760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b604482015260640161096a565b6127e382846153c9565b845110156128275760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b604482015260640161096a565b6060821580156128465760405191506000825260208201604052612890565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561287f578051835260209283019201612867565b5050858452601f01601f1916604052505b50949350505050565b6000818311156128b4576128ad82846154eb565b9050610a81565b6128ad83836154eb565b6033546001600160a01b031633146110885760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161096a565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006129778260206153c9565b835110156129bf5760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b604482015260640161096a565b50016020015190565b60006129d58260146153c9565b83511015612a1d5760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b604482015260640161096a565b500160200151600160601b900490565b612a3561466b565b600080612a4a60c9546001600160a01b031690565b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b8152600401612a7591906150ca565b60006040518083038186803b158015612a8d57600080fd5b505afa158015612aa1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612ac99190810190614cdb565b509150915080612aec57604051632acbe91560e01b815260040160405180910390fd5b612afe82606001518360800151610e0e565b612b1b5760405163360f2d8760e01b815260040160405180910390fd5b60d2546001600160401b03166001600160401b03168260a001516001600160401b031611612b5c576040516388d1b84760e01b815260040160405180910390fd5b612b698260a001516135ab565b5092915050565b610b6a81613fa0565b6000612bad6040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b9050600080612bc460c9546001600160a01b031690565b845160405163607ec5ef60e11b81526001600160a01b03929092169163c0fd8bde91612bf2916004016150ca565b60006040518083038186803b158015612c0a57600080fd5b505afa158015612c1e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c469190810190614cdb565b509150915080612c6957604051632acbe91560e01b815260040160405180910390fd5b6000612c788360e00151610e31565b9050612c826113bd565b61ffff16816040015161ffff1614158015612ca45750604081015161ffff1615155b15612cc2576040516363daeb7760e01b815260040160405180910390fd5b600581602001516006811115612ce857634e487b7160e01b600052602160045260246000fd5b14612d06576040516397363b3560e01b815260040160405180910390fd5b6000612d15826060015161108a565b805190915063ffffffff16612d2f60d45463ffffffff1690565b63ffffffff1610612d53576040516388d1b84760e01b815260040160405180910390fd5b805160d4805463ffffffff191663ffffffff90921691909117905560408051808201909152606085015161ffff1680825260808601516020830181905260d0805461ffff191690921790915560d155612daf8560a001516135ab565b7f6bce23ef3d34e51710fe4700b43ba5f1733a6215c883f384671a4ece3ea8aa2086612e036040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b60d25460408051845161ffff90811682526020958601518683015284511691810191909152929091015160608301526001600160401b0316608082015260a0015b60405180910390a150505050505050565b6000612e5f611446565b905060005b8151811015612ed757600060c96004016000612ea6858581518110612e9957634e487b7160e01b600052603260045260246000fd5b6020026020010151611265565b81526020810191909152604001600020805460ff1916911515919091179055612ed06001826153c9565b9050612e64565b50612ee460cc60006146c6565b60005b825151811015612fb9578251805160cc919083908110612f1757634e487b7160e01b600052603260045260246000fd5b60209081029190910181015182546001808201855560009485528385208351600290930201805461ffff191661ffff90931692909217825591909201519181019190915584518051919260cd929091612f889186908110612e9957634e487b7160e01b600052603260045260246000fd5b81526020810191909152604001600020805460ff191691151591909117905580612fb18161552e565b915050612ee7565b507fd451e0fcb7c5b9e13de533604d158069dad159841c45f39f09d379bfc423080d81612fe4611446565b604051612ff2929190615027565b60405180910390a15050565b600061300960ce5490565b825160ce5590507f74dbbbe280ef27b79a8a0c449d5ae2ba7a31849103241d0f98df70bbc9d03e378161303b60ce5490565b60408051928352602083019190915201612ff2565b600061305b60cf5490565b825160cf5590507fcdb88a22f82ddd76115ab7c66cf08eb1e40afe80c9b31017eb2cbdb1570b33ae8161303b60cf5490565b60006130a160c9546001600160a01b031690565b90506130b08360000151613589565b6000806130c560c9546001600160a01b031690565b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b81526004016130f091906150ca565b60006040518083038186803b15801561310857600080fd5b505afa15801561311c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131449190810190614cdb565b509150915080613167576040516397363b3560e01b815260040160405180910390fd5b61317982606001518360800151610e0e565b613196576040516397363b3560e01b815260040160405180910390fd5b60d2546001600160401b03166001600160401b03168260a001516001600160401b0316146131d7576040516309e9f6c160e11b815260040160405180910390fd5b60006131e68360e00151610e31565b905060068160200151600681111561320e57634e487b7160e01b600052602160045260246000fd5b1461322c576040516309e9f6c160e11b815260040160405180910390fd5b600061323b8260600151611234565b875181519192506001600160a01b0391821691161461326d576040516309e9f6c160e11b815260040160405180910390fd5b7fd495c4e5b386d59bccca38a2277b5d70a0f5e47d7b6587a45a6f5aca221a3125856132a160c9546001600160a01b031690565b604080516001600160a01b03938416815292909116602083015201612e44565b6132c9614636565b50600090815260d56020908152604091829020825160c08101845281546001600160401b038082168352600160401b808304600390810b810b900b95840195909552600160601b8204600790810b810b810b96840196909652600160a01b9091048116606083015260019092015480850b850b90940b60808201529190920490911660a082015290565b60046000833560e01c63504e415581146133805760405163734fff6760e11b815260040160405180910390fd5b60018084019386013560f81c9081146133ac5760405163734fff6760e11b815260040160405180910390fd5b50508184016001013560f890811c9092016002818101939186010135901c60ff1680156133e957634e487b7160e01b600052602160045260246000fd5b600192909201919050818310156134135760405163734fff6760e11b815260040160405180910390fd5b9250929050565b60008382013560f01c61342e6002846153c9565b925061343e61ffff8216846153c9565b92508483013560f81c5b95945050505050565b600061345c60ce5490565b610a8190836154cc565b60008060006134758585613353565b9092509050600081801561349957634e487b7160e01b600052602160045260246000fd5b146134b75760405163734fff6760e11b815260040160405180910390fd5b6000803660006134c889898861368f565b919a50929650909450909250905060005b8760ff1681101561351a576134ec614636565b6000806134fb8787878b6137d1565b929a509094509250905061350f82846138c5565b5050506001016134d9565b5083811461353b5760405163734fff6760e11b815260040160405180910390fd5b50505050505092915050565b610d576135548383613c98565b61409e565b600054610100900460ff166135805760405162461bcd60e51b815260040161096a90615175565b61108833612918565b60c980546001600160a01b0319166001600160a01b0392909216919091179055565b60d2805467ffffffffffffffff19166001600160401b0392909216919091179055565b6001600160a01b0381163b61363b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161096a565b6000805160206155b183398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61367383614145565b6000825111806136805750805b15612085576118308383614185565b6000808036816136a3888888808203614270565b600296509092509050813560f01c606060006136c96136c486868b87614270565b61429a565b60e0015160048082015161ffff86169a909a01999193509150634155575663ffffffff82161461370c5760405163734fff6760e11b815260040160405180910390fd5b8183016001015160009060ff16801561373557634e487b7160e01b600052602160045260246000fd5b6001909301929050600081801561375c57634e487b7160e01b600052602160045260246000fd5b1461377a5760405163734fff6760e11b815260040160405180910390fd5b602c84840101518451600160601b90910460601b99506020909301928311156137b65760405163734fff6760e11b815260040160405180910390fd5b5050600188019b969a505050509381013560f81c9550935050565b60006137db614636565b600283019260009081903690829089013560f01c6137fb8a8a8a84614270565b925092508061ffff168801975060006138188b8b8b8f888861436e565b985090508061383a5760405163734fff6760e11b815260040160405180910390fd5b6000843560f81c801561385d57634e487b7160e01b600052602160045260246000fd5b9050600081801561387e57634e487b7160e01b600052602160045260246000fd5b141561389c5761389085856001614416565b919950975095506138b5565b60405163734fff6760e11b815260040160405180910390fd5b5050505050945094509450949050565b600082815260d5602052604090205481516001600160401b03918216911681101561208557600083815260d560209081526040918290208451815486840151878601516060808a01516001600160401b039586166001600160601b03199095168517600160401b63ffffffff60039690960b959095168502176fffffffffffffffffffffffffffffffff60601b1916600160601b600794850b8089169190910267ffffffffffffffff60a01b191691909117600160a01b92881692830217885560808c01516001909801805460a08e01519990950b88166fffffffffffffffffffffffffffffffff1990951694909417979096169093029590951790558551918252938101919091529283019190915284917fd06a6b7f4918494b3719217d1802786c1f5112a6c1d88fe2cfec00b4584f6aec910160405180910390a2505050565b6000805b83811015611b8f5782858583818110613a3457634e487b7160e01b600052603260045260246000fd5b905060200201351415613a4657611b8f565b80613a508161552e565b915050613a0b565b82858581518110613a7957634e487b7160e01b600052603260045260246000fd5b602002602001015160000181815250508160400151858581518110613aae57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516000019060070b908160070b815250508160600151858581518110613aef57634e487b7160e01b600052603260045260246000fd5b602002602001015160200151602001906001600160401b031690816001600160401b0316815250508160200151858581518110613b3c57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516040019060030b908160030b8152505080858581518110613b7957634e487b7160e01b600052603260045260246000fd5b60200260200101516020015160600181815250508160800151858581518110613bb257634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516000019060070b908160070b815250508160a00151858581518110613bf357634e487b7160e01b600052603260045260246000fd5b602002602001015160400151602001906001600160401b031690816001600160401b0316815250508160200151858581518110613c4057634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516040019060030b908160030b8152505080858581518110613c7d57634e487b7160e01b600052603260045260246000fd5b60200260200101516040015160600181815250505050505050565b613ca061466b565b6000613cb460c9546001600160a01b031690565b6001600160a01b031663c0fd8bde85856040518363ffffffff1660e01b8152600401613ce192919061509b565b60006040518083038186803b158015613cf957600080fd5b505afa158015613d0d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613d359190810190614cdb565b50909250905080613d5957604051632acbe91560e01b815260040160405180910390fd5b50613d6381614504565b610a815760405163e60dce7160e01b815260040160405180910390fd5b6000808080613d93858260049101015190565b90506004840193508063ffffffff16635032574814613dc55760405163734fff6760e11b815260040160405180910390fd5b6002858501810151940193600361ffff821614613df55760405163734fff6760e11b815260040160405180910390fd5b6002850194506000613e0b878760029101015190565b90506002860195506000613e23888860019101015190565b90508161ffff16870196508060ff16600214613e525760405163734fff6760e11b815260040160405180910390fd5b505050508284016002015161ffff169150600283019250613e77848460029101015190565b61ffff1690506002830192508181028301845114613ea85760405163734fff6760e11b815260040160405180910390fd5b9193909250565b613eb7614636565b6040838501818101516048820151600790810b810b9385019390935260508201516001600160401b0390811660608601526054830151600390810b900b6020860152605c830151840b90930b60808501526064820151831660a08501526065820151607d9283015190931684529160ff811660011415613f3c57601882019150613f75565b858201870160088101516001600160401b0390811686526010820151600790810b900b6040870152601891820151166060860152909101905b5083811115613f975760405163734fff6760e11b815260040160405180910390fd5b50935093915050565b6000613faa61202e565b8251909150613fba906000610b38565b306001600160a01b031663e3795cc16040518163ffffffff1660e01b815260040160206040518083038186803b158015613ff357600080fd5b505afa158015614007573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061402b9190614e8f565b63ffffffff166397a6f30414614054576040516397363b3560e01b815260040160405180910390fd5b7f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a498161407e61202e565b604080516001600160a01b03938416815292909116602083015201612ff2565b60e0810151600080806140b084613d80565b92509250925060005b828110156140ec576000806140cf878786613eaf565b9150915083860195506140e281836138c5565b50506001016140b9565b50606085015160a08601516040805161ffff90931683526001600160401b0390911660208301527f943f0e8a16c19895fb87cbeb1a349ed86d7f31923089dd36c1a1ed5e300f267b910160405180910390a15050505050565b61414e816135ce565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6141ed5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161096a565b600080846001600160a01b0316846040516142089190614fc9565b600060405180830381855af49150503d8060008114614243576040519150601f19603f3d011682016040523d82523d6000602084013e614248565b606091505b509150915061344882826040518060600160405280602781526020016155d160279139614520565b36600085848661428086836153c9565b9261428d939291906153a1565b9150915094509492505050565b6142a261466b565b60006142b660c9546001600160a01b031690565b6001600160a01b031663c0fd8bde85856040518363ffffffff1660e01b81526004016142e392919061509b565b60006040518083038186803b1580156142fb57600080fd5b505afa15801561430f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526143379190810190614cdb565b5090925090508061435b57604051632acbe91560e01b815260040160405180910390fd5b50613d6381606001518260800151610b6d565b60008060006143b285858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061453992505050565b600188019790915089013560f81c60005b8160ff168110156143f55760148901988b01356001600160601b0319166143ea848261456c565b9350506001016143c3565b50506001600160601b03199081169516949094149794965093945050505050565b61441e614636565b60208483018181013560c090811c600790810b900b6040858101919091526028830135821c6060860152603083013560e01c600390810b900b85850152603483013590911c84528051601f8701849004840281018401909152858152603c909401939035916000916144ac918890889081908401838280828437600092019190915250889250614518915050565b868501600881013560c090811c600790810b900b6080870152601090910135901c60a08501526018909401939050848411156144fb5760405163734fff6760e11b815260040160405180910390fd5b93509350939050565b6000610a8182606001518360800151610b6d565b016008015190565b6060831561452f575081610e2a565b610e2a83836145b8565b6000610a81600083604051602001614552929190614fe5565b604051602081830303815290604052805160209091012090565b60006001600160601b03198083169084161115614587579091905b604051600160f81b60208201526001600160601b0319808516602183015283166035820152610e2a90604901614552565b8151156145c85781518083602001fd5b8060405162461bcd60e51b815260040161096a91906150ca565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604080516060810190915260008152602081016146246145e2565b81526020016146316145e2565b905290565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201819052610100820183905261012082015261014081019190915290565b5080546000825560020290600052602060002090810190610b6a91905b8082111561470357805461ffff19168155600060018201556002016146e3565b5090565b80356001600160a01b038116811461471e57600080fd5b919050565b60008083601f840112614734578182fd5b5081356001600160401b0381111561474a578182fd5b6020830191508360208260051b850101111561341357600080fd5b600082601f830112614775578081fd5b815160206001600160401b0382111561479057614790615575565b61479e818360051b0161534a565b80838252828201915082860187848660071b89010111156147bd578586fd5b855b8581101561482057608080838b0312156147d7578788fd5b6147df6152ff565b83518152868401518782015260406147f88186016148fb565b9082015260606148098582016148fb565b9082015285529385019391909101906001016147bf565b5090979650505050505050565b8051801515811461471e57600080fd5b600082601f83011261484d578081fd5b813561486061485b8261537a565b61534a565b818152846020838601011115614874578283fd5b816020850160208301379081016020019190915292915050565b600082601f83011261489e578081fd5b81516148ac61485b8261537a565b8181528460208386010111156148c0578283fd5b611b8f826020830160208701615502565b805161471e8161558b565b805163ffffffff8116811461471e57600080fd5b805161471e8161559b565b805160ff8116811461471e57600080fd5b60006020828403121561491d578081fd5b610e2a82614707565b6000806000806000806000806000806101008b8d031215614945578586fd5b61494e8b614707565b995060208b01356001600160401b0380821115614969578788fd5b6149758e838f01614723565b909b50995060408d013591508082111561498d578788fd5b5061499a8d828e01614723565b90985096505060608b01356149ae8161558b565b945060808b0135935060a08b01356149c58161559b565b8093505060c08b0135915060e08b013590509295989b9194979a5092959850565b600080604083850312156149f8578182fd5b614a0183614707565b915060208301356001600160401b03811115614a1b578182fd5b614a278582860161483d565b9150509250929050565b60008060208385031215614a43578182fd5b82356001600160401b03811115614a58578283fd5b614a6485828601614723565b90969095509350505050565b60008060008060008060608789031215614a88578384fd5b86356001600160401b0380821115614a9e578586fd5b614aaa8a838b01614723565b90985096506020890135915080821115614ac2578586fd5b614ace8a838b01614723565b90965094506040890135915080821115614ae6578384fd5b50614af389828a01614723565b979a9699509497509295939492505050565b60008060008060008060808789031215614b1d578384fd5b86356001600160401b0380821115614b33578586fd5b614b3f8a838b01614723565b90985096506020890135915080821115614b57578586fd5b50614b6489828a01614723565b9095509350506040870135614b788161559b565b91506060870135614b888161559b565b809150509295509295509295565b600060208284031215614ba7578081fd5b5035919050565b600060208284031215614bbf578081fd5b5051919050565b60008060408385031215614bd8578182fd5b50508035926020909101359150565b60008060208385031215614bf9578182fd5b82356001600160401b0380821115614c0f578384fd5b818501915085601f830112614c22578384fd5b813581811115614c30578485fd5b866020828501011115614c41578485fd5b60209290920196919550909350505050565b600060208284031215614c64578081fd5b81356001600160401b03811115614c79578182fd5b611b8f8482850161483d565b600060408284031215614c96578081fd5b604051604081018181106001600160401b0382111715614cb857614cb8615575565b6040528235614cc68161558b565b81526020928301359281019290925250919050565b600080600060608486031215614cef578081fd5b83516001600160401b0380821115614d05578283fd5b908501906101608288031215614d19578283fd5b614d21615327565b614d2a836148fb565b8152614d38602084016148dc565b6020820152614d49604084016148dc565b6040820152614d5a606084016148d1565b606082015260808301516080820152614d7560a084016148f0565b60a0820152614d8660c084016148fb565b60c082015260e083015182811115614d9c578485fd5b614da88982860161488e565b60e083015250610100614dbc8185016148dc565b908201526101208381015183811115614dd3578586fd5b614ddf8a828701614765565b918301919091525061014083810151908201529450614e006020870161482d565b93506040860151915080821115614e15578283fd5b50614e228682870161488e565b9150509250925092565b600060208284031215614e3d578081fd5b8135610e2a8161558b565b600060208284031215614e59578081fd5b8151610e2a8161558b565b60008060408385031215614e76578182fd5b8235614e818161558b565b946020939093013593505050565b600060208284031215614ea0578081fd5b610e2a826148dc565b600060208284031215614eba578081fd5b8135610e2a8161559b565b6000815180845260208085019450808401835b83811015614f0c57614ef9878351805161ffff168252602090810151910152565b6040969096019590820190600101614ed8565b509495945050505050565b60008151808452614f2f816020860160208601615502565b601f01601f19169290920160200192915050565b805182526020810151614f896020840182805160070b82526001600160401b036020820151166020830152604081015160030b6040830152606081015160608301525050565b50604081810151805160070b60a085015260208101516001600160401b031660c08501529081015160030b60e08401526060810151610100840152612085565b60008251614fdb818460208701615502565b9190910192915050565b60ff60f81b8360f81b16815260008251615006816001850160208701615502565b919091016001019392505050565b602081526000610e2a6020830184614ec5565b60408152600061503a6040830185614ec5565b82810360208401526134488185614ec5565b6020808252825182820181905260009190848201906040850190845b8181101561508f5761507b838551614f43565b928401926101209290920191600101615068565b50909695505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b602081526000610e2a6020830184614f17565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6020815260008251602080840152611b8f6040840182614f17565b815161ffff1681526020808301519082015260408101610a81565b60208152600082516004811061520e5761520e61555f565b8060208401525060208301516007811061522a5761522a61555f565b8060408401525061ffff60408401511660608301526060830151608080840152611b8f60a0840182614f17565b6101208101610a818284614f43565b815160070b81526020808301516001600160401b03169082015260408083015160030b908201526060808301519082015260808101610a81565b6020815260008251602080840152611b8f6040840182614ec5565b6000808335601e198436030181126152d1578283fd5b8301803591506001600160401b038211156152ea578283fd5b60200191503681900382131561341357600080fd5b604051608081016001600160401b038111828210171561532157615321615575565b60405290565b60405161016081016001600160401b038111828210171561532157615321615575565b604051601f8201601f191681016001600160401b038111828210171561537257615372615575565b604052919050565b60006001600160401b0382111561539357615393615575565b50601f01601f191660200190565b600080858511156153b0578182fd5b838611156153bc578182fd5b5050820193919092039150565b600082198211156153dc576153dc615549565b500190565b600181815b8085111561541c57816000190482111561540257615402615549565b8085161561540f57918102915b93841c93908002906153e6565b509250929050565b6000610e2a838360008261543a57506001610a81565b8161544757506000610a81565b816001811461545d576002811461546757615483565b6001915050610a81565b60ff84111561547857615478615549565b50506001821b610a81565b5060208310610133831016604e8410600b84101617156154a6575081810a610a81565b6154b083836153e1565b80600019048211156154c4576154c4615549565b029392505050565b60008160001904831182151516156154e6576154e6615549565b500290565b6000828210156154fd576154fd615549565b500390565b60005b8381101561551d578181015183820152602001615505565b838111156118305750506000910152565b600060001982141561554257615542615549565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b61ffff81168114610b6a57600080fd5b6001600160401b0381168114610b6a57600080fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220ab7582184ce1397c9a45ad113da76101d50500a9eecd891a38118da7c3ec8d7864736f6c63430008040033
Deployed Bytecode
0x6080604052600436106102725760003560e01c80638881016f1161014f578063b5ec0261116100c1578063d82d58a51161007a578063d82d58a514610819578063e17efd4814610852578063e18910a314610872578063e3795cc114610887578063ef9e5e281461089e578063f2fde38b146108b157600080fd5b8063b5ec02611461074c578063b6ed701e14610784578063b9256d28146107a4578063caaf43f1146107b7578063cb718a9b146107e4578063d47eed45146107f957600080fd5b80639a8a0592116101135780639a8a0592146106af578063a38d81c6146106d7578063a4ae35e0146106f9578063aac41292146105f9578063accca7f914610719578063b5dcc9111461072c57600080fd5b80638881016f146105f957806389a5bb4d146106315780638da5cb5b146106515780639474f45b1461066f57806396834ad31461068f57600080fd5b806352d1902d116101e85780636c72f51b116101ac5780636c72f51b14610504578063711a2e2814610530578063715018a6146105505780637b72bcae1461056557806384acd1bb1461059a57806387c5bd1b146105cc57600080fd5b806352d1902d1461045057806354fd4d5014610465578063586d3cf81461049957806358c67635146104b75780636b7f53ca146104d757600080fd5b8063437209a71161023a578063437209a7146103605780634716e9c51461039057806348b6404d146103b05780634c469d8c146103cf5780634d7a734e1461041d5780634f1ef2861461043d57600080fd5b8063146faf771461027757806314dd317f1461029957806331d98b3f146102cd5780633659cfe6146102fa578063426234e41461031a575b600080fd5b34801561028357600080fd5b50610297610292366004614926565b6108d1565b005b3480156102a557600080fd5b506102b96102b4366004614c53565b610a13565b604051905181526020015b60405180910390f35b3480156102d957600080fd5b506102ed6102e8366004614b96565b610a6d565b6040516102c49190615266565b34801561030657600080fd5b5061029761031536600461490c565b610a87565b34801561032657600080fd5b506040805180820182526000808252602091820152815180830190925260d05461ffff16825260d154908201526040516102c491906151db565b34801561036c57600080fd5b5061038061037b366004614e64565b610b6d565b60405190151581526020016102c4565b6103a361039e366004614b05565b610bc0565b6040516102c4919061504c565b3480156103bc57600080fd5b5060ce545b6040519081526020016102c4565b3480156103db57600080fd5b506104056103ea366004614b96565b600090815260d560205260409020546001600160401b031690565b6040516001600160401b0390911681526020016102c4565b34801561042957600080fd5b506102b9610438366004614c53565b610c09565b61029761044b3660046149e6565b610ca1565b34801561045c57600080fd5b506103c1610d5b565b34801561047157600080fd5b506040805180820182526005815264312e342e3360d81b602082015290516102c491906150ca565b3480156104a557600080fd5b5060d2546001600160401b0316610405565b3480156104c357600080fd5b506103806104d2366004614e64565b610e0e565b3480156104e357600080fd5b506104f76104f2366004614c53565b610e31565b6040516102c491906151f6565b34801561051057600080fd5b5060d45463ffffffff165b60405163ffffffff90911681526020016102c4565b34801561053c57600080fd5b506102ed61054b366004614bc6565b611035565b34801561055c57600080fd5b50610297611076565b34801561057157600080fd5b50610585610580366004614c53565b61108a565b604051905163ffffffff1681526020016102c4565b3480156105a657600080fd5b5060c9546001600160a01b03165b6040516001600160a01b0390911681526020016102c4565b3480156105d857600080fd5b506105ec6105e7366004614c53565b6110b8565b6040516102c491906152a0565b34801561060557600080fd5b50610619610614366004614c53565b611234565b60405190516001600160a01b031681526020016102c4565b34801561063d57600080fd5b506103c161064c366004614c85565b611265565b34801561065d57600080fd5b506033546001600160a01b03166105b4565b34801561067b57600080fd5b506102ed61068a366004614b96565b6112b7565b34801561069b57600080fd5b506102ed6106aa366004614b96565b611338565b3480156106bb57600080fd5b506106c46113bd565b60405161ffff90911681526020016102c4565b3480156106e357600080fd5b506106ec611446565b6040516102c49190615014565b34801561070557600080fd5b506102ed610714366004614bc6565b6114b9565b6103a3610727366004614b05565b6114ca565b34801561073857600080fd5b506102ed610747366004614b96565b611508565b34801561075857600080fd5b50610380610767366004614b96565b600090815260d560205260409020546001600160401b0316151590565b34801561079057600080fd5b5061029761079f366004614be7565b61151c565b6102976107b2366004614a70565b611836565b3480156107c357600080fd5b506107d76107d2366004614b96565b61192d565b6040516102c49190615257565b3480156107f057600080fd5b5060cf546103c1565b34801561080557600080fd5b506103c1610814366004614a31565b6119fb565b34801561082557600080fd5b50610845610834366004614c53565b604080516020810190915290815290565b6040516102c491906151c0565b34801561085e57600080fd5b506103c161086d366004614b96565b611b97565b34801561087e57600080fd5b506103c1611bb8565b34801561089357600080fd5b506397a6f30461051b565b6102976108ac366004614a31565b611bc3565b3480156108bd57600080fd5b506102976108cc36600461490c565b611d0e565b600054610100900460ff16158080156108f15750600054600160ff909116105b8061090b5750303b15801561090b575060005460ff166001145b6109735760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610996576000805461ff0019166101001790555b61099e611d93565b6109a6611dc2565b6109b88b8b8b8b8b8b8b8b8b8b611de9565b6109c0611076565b8015610a06576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050505050565b6040805160208101909152600081526000610a2e8382611fd1565b6001600160401b03168252610a446008826153c9565b905080835114610a67576040516397363b3560e01b815260040160405180910390fd5b50919050565b610a756145e2565b610a8182610714611bb8565b92915050565b306001600160a01b037f00000000000000000000000035a58beee77a2ad547fcded7e8cb1c6e19746b13161415610ad05760405162461bcd60e51b815260040161096a906150dd565b7f00000000000000000000000035a58beee77a2ad547fcded7e8cb1c6e19746b136001600160a01b0316610b0261202e565b6001600160a01b031614610b285760405162461bcd60e51b815260040161096a90615129565b610b318161204a565b610b6a8160005b6040519080825280601f01601f191660200182016040528015610b62576020820181803683370190505b506000612052565b50565b6040805160f09390931b6001600160f01b0319166020808501919091526022808501939093528151808503909301835260429093018152815191830191909120600090815260cd90925290205460ff1690565b6060610bfe878787876040518060600160405280896001600160401b03168152602001886001600160401b03168152602001600015158152506121d1565b979650505050505050565b604080516020810190915260008152600080610c258482611fd1565b9050610c326008836153c9565b91506000610c408584611fd1565b9050610c4d6008846153c9565b9250610c636001600160401b038216600a615424565b610c76906001600160401b0384166154cc565b845284518314610c99576040516397363b3560e01b815260040160405180910390fd5b505050919050565b306001600160a01b037f00000000000000000000000035a58beee77a2ad547fcded7e8cb1c6e19746b13161415610cea5760405162461bcd60e51b815260040161096a906150dd565b7f00000000000000000000000035a58beee77a2ad547fcded7e8cb1c6e19746b136001600160a01b0316610d1c61202e565b6001600160a01b031614610d425760405162461bcd60e51b815260040161096a90615129565b610d4b8261204a565b610d5782826001612052565b5050565b6000306001600160a01b037f00000000000000000000000035a58beee77a2ad547fcded7e8cb1c6e19746b131614610dfb5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161096a565b506000805160206155b183398151915290565b60d05460009061ffff8481169116148015610e2a575060d15482145b9392505050565b610e5d604080516080810190915280600081526020016000815260006020820152606060409091015290565b600080610e6a8482612676565b905063ffffffff8116635054474d14610e96576040516397363b3560e01b815260040160405180910390fd5b610ea16004836153c9565b91506000610eaf85846126d3565b90508060ff166003811115610ed457634e487b7160e01b600052602160045260246000fd5b84906003811115610ef557634e487b7160e01b600052602160045260246000fd5b90816003811115610f1657634e487b7160e01b600052602160045260246000fd5b905250610f246001846153c9565b9250600184516003811115610f4957634e487b7160e01b600052602160045260246000fd5b14610f67576040516363daeb7760e01b815260040160405180910390fd5b6000610f7386856126d3565b90508060ff166006811115610f9857634e487b7160e01b600052602160045260246000fd5b85602001906006811115610fbc57634e487b7160e01b600052602160045260246000fd5b90816006811115610fdd57634e487b7160e01b600052602160045260246000fd5b905250610feb6001856153c9565b9350610ff7868561272f565b61ffff16604086015261100b6002856153c9565b93506110268485885161101e91906154eb565b88919061278c565b60608601525092949350505050565b61103d6145e2565b611046836112b7565b905081611057428360600151612899565b1115610a8157604051630cd5fa0760e11b815260040160405180910390fd5b61107e6128be565b6110886000612918565b565b60408051602081019091526000815260006110a58382612676565b63ffffffff168252610a446004826153c9565b6040805160208101909152606081526000806110d484826126d3565b90506110e16001836153c9565b91508060ff166001600160401b0381111561110c57634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561115157816020015b604080518082019091526000808252602082015281526020019060019003908161112a5790505b50835260005b8160ff1681101561120b5761116c858461272f565b845180518390811061118e57634e487b7160e01b600052603260045260246000fd5b602090810291909101015161ffff90911690526111ac6002846153c9565b92506111b8858461296a565b84518051839081106111da57634e487b7160e01b600052603260045260246000fd5b602002602001015160200181815250506020836111f791906153c9565b9250806112038161552e565b915050611157565b508184511461122d576040516397363b3560e01b815260040160405180910390fd5b5050919050565b604080516020810190915260008152600061124f83826129c8565b6001600160a01b03168252610a446014826153c9565b60008160000151826020015160405160200161129a92919060f09290921b6001600160f01b0319168252600282015260220190565b604051602081830303815290604052805190602001209050919050565b6112bf6145e2565b600082815260d5602090815260409182902080546001600160401b0380821660608701819052600160401b92839004600390810b810b900b958701959095526001830154600781810b810b900b875291909104169184019190915290610a6757604051630295d7cd60e31b815260040160405180910390fd5b6113406145e2565b600082815260d5602090815260409182902080546001600160401b0380821660608701819052600160401b8304600390810b810b900b95870195909552600160601b8204600790810b810b900b8652600160a01b909104169184019190915290610a6757604051630295d7cd60e31b815260040160405180910390fd5b60006113d160c9546001600160a01b031690565b6001600160a01b0316639a8a05926040518163ffffffff1660e01b815260040160206040518083038186803b15801561140957600080fd5b505afa15801561141d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114419190614e48565b905090565b606060c9600301805480602002602001604051908101604052809291908181526020016000905b828210156114b05760008481526020908190206040805180820190915260028502909101805461ffff16825260019081015482840152908352909201910161146d565b50505050905090565b6114c16145e2565b61104683611338565b6060610bfe878787876040518060600160405280896001600160401b03168152602001886001600160401b03168152602001600115158152506121d1565b6115106145e2565b610a818261054b611bb8565b600061155d83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a2d92505050565b9050600061156e8260e00151610e31565b90506115786113bd565b61ffff16816040015161ffff161415801561159a5750604081015161ffff1615155b156115b8576040516363daeb7760e01b815260040160405180910390fd5b6000816020015160068111156115de57634e487b7160e01b600052602160045260246000fd5b141561162457604081015161ffff1661160a576040516363daeb7760e01b815260040160405180910390fd5b61161f61161a8260600151611234565b612b70565b611830565b60018160200151600681111561164a57634e487b7160e01b600052602160045260246000fd5b14156116715761161f61166c8260600151604080516020810190915290815290565b612b79565b60028160200151600681111561169757634e487b7160e01b600052602160045260246000fd5b14156116b25761161f6116ad82606001516110b8565b612e55565b6003816020015160068111156116d857634e487b7160e01b600052602160045260246000fd5b14156116f35761161f6116ee8260600151610c09565b612ffe565b60048160200151600681111561171957634e487b7160e01b600052602160045260246000fd5b14156117345761161f61172f8260600151610a13565b613050565b60058160200151600681111561175a57634e487b7160e01b600052602160045260246000fd5b1415611779576040516397363b3560e01b815260040160405180910390fd5b60068160200151600681111561179f57634e487b7160e01b600052602160045260246000fd5b141561181757604081015161ffff166117cb576040516363daeb7760e01b815260040160405180910390fd5b61161f6117db8260600151611234565b85858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061308d92505050565b6040516397363b3560e01b815260040160405180910390fd5b50505050565b8281146118565760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b8381101561190b5782828281811061188157634e487b7160e01b600052603260045260246000fd5b90506020020160208101906118969190614ea9565b6001600160401b03166118e48686848181106118c257634e487b7160e01b600052603260045260246000fd5b90506020020135600090815260d560205260409020546001600160401b031690565b6001600160401b03161015611903576118fd8787611bc3565b50611925565b600101611859565b50604051636f162bfd60e11b815260040160405180910390fd5b505050505050565b611935614609565b6000611940836132c1565b80519091506001600160401b031661196b57604051630295d7cd60e31b815260040160405180910390fd5b91815260408083015160208084018051600793840b840b905260608087015182516001600160401b039182169085015283880180518451600391820b820b9089015289519451948316948401949094526080890151878901805191880b90970b905260a089015186519083169501949094529251845190830b90920b919094015293519051931692019190915290565b600080805b83811015611b85576004858583818110611a2a57634e487b7160e01b600052603260045260246000fd5b9050602002810190611a3c91906152bb565b9050118015611a90575063504e4155611a88868684818110611a6e57634e487b7160e01b600052603260045260246000fd5b9050602002810190611a8091906152bb565b503560e01c90565b63ffffffff16145b15611b6557600080611ad2878785818110611abb57634e487b7160e01b600052603260045260246000fd5b9050602002810190611acd91906152bb565b613353565b90925090506000818015611af657634e487b7160e01b600052602160045260246000fd5b14611b145760405163734fff6760e11b815260040160405180910390fd5b611b4f878785818110611b3757634e487b7160e01b600052603260045260246000fd5b9050602002810190611b4991906152bb565b8461341a565b611b5c9060ff16856153c9565b93505050611b73565b611b706001836153c9565b91505b80611b7d8161552e565b915050611a00565b50611b8f81613451565b949350505050565b600081611ba360ce5490565b611bae9060ff6154cc565b610a8191906154cc565b600061144160cf5490565b6000805b82811015611ce0576004848483818110611bf157634e487b7160e01b600052603260045260246000fd5b9050602002810190611c0391906152bb565b9050118015611c3d575063504e4155611c35858584818110611a6e57634e487b7160e01b600052603260045260246000fd5b63ffffffff16145b15611c9057611c7c848483818110611c6557634e487b7160e01b600052603260045260246000fd5b9050602002810190611c7791906152bb565b613466565b611c899060ff16836153c9565b9150611cd8565b611cca848483818110611cb357634e487b7160e01b600052603260045260246000fd5b9050602002810190611cc591906152bb565b613547565b611cd56001836153c9565b91505b600101611bc7565b506000611cec82613451565b9050803410156118305760405162976f7560e21b815260040160405180910390fd5b611d166128be565b6001600160a01b038116611d7b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161096a565b610b6a81612918565b6001600160a01b03163b151590565b600054610100900460ff16611dba5760405162461bcd60e51b815260040161096a90615175565b611088613559565b600054610100900460ff166110885760405162461bcd60e51b815260040161096a90615175565b611df28a613589565b878614611e125760405163a9cb9e0d60e01b815260040160405180910390fd5b60005b88811015611f7c57600060405180604001604052808c8c85818110611e4a57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611e5f9190614e2c565b61ffff1681526020018a8a85818110611e8857634e487b7160e01b600052603260045260246000fd5b905060200201358152509050611ea681600001518260200151610b6d565b15611ec45760405163a9cb9e0d60e01b815260040160405180910390fd5b600160cd6000611ed384611265565b81526020808201929092526040016000908120805460ff19169315159390931790925560cc8054600181018255925282517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebe6002909302928301805461ffff191661ffff90921691909117905591909101517f47197230e1e4b29fc0bd84d7d78966c0925452aff72a2a121538b102457e9ebf9091015580611f748161552e565b915050611e15565b506040805180820190915261ffff86168082526020820186905260d0805461ffff1916909117905560d1859055611fb2846135ab565b50611fbc8260cf55565b611fc58160ce55565b50505050505050505050565b6000611fde8260086153c9565b835110156120255760405162461bcd60e51b8152602060048201526014602482015273746f55696e7436345f6f75744f66426f756e647360601b604482015260640161096a565b50016008015190565b6000805160206155b1833981519152546001600160a01b031690565b610b6a6128be565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561208a57612085836135ce565b505050565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b815260040160206040518083038186803b1580156120c357600080fd5b505afa9250505080156120f3575060408051601f3d908101601f191682019092526120f091810190614bae565b60015b6121565760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161096a565b6000805160206155b183398151915281146121c55760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161096a565b5061208583838361366a565b606060006121df87876119fb565b9050803410156122015760405162976f7560e21b815260040160405180910390fd5b50826001600160401b0381111561222857634e487b7160e01b600052604160045260246000fd5b60405190808252806020026020018201604052801561226157816020015b61224e614609565b8152602001906001900390816122465790505b50905060005b8581101561260f57600487878381811061229157634e487b7160e01b600052603260045260246000fd5b90506020028101906122a391906152bb565b90501180156122dd575063504e41556122d5888884818110611a6e57634e487b7160e01b600052603260045260246000fd5b63ffffffff16145b156124c257600080612308898985818110611abb57634e487b7160e01b600052603260045260246000fd5b9092509050600081801561232c57634e487b7160e01b600052602160045260246000fd5b1461234a5760405163734fff6760e11b815260040160405180910390fd5b5060008036600061238c8c8c8881811061237457634e487b7160e01b600052603260045260246000fd5b905060200281019061238691906152bb565b8761368f565b93985091965094509250905060005b8360ff16811015612497576123ae614636565b6000806123bd8887878c6137d1565b929b50909450925090506123d182846138c5565b60006123de8f8f85613a07565b90508d81148061241857508b818151811061240957634e487b7160e01b600052603260045260246000fd5b60209081029190910101515115155b15612426575050505061248f565b83518d516001600160401b039182169116811080159061245357508d602001516001600160401b03168111155b801561247757508d60400151158061247757508d516001600160401b038085169116115b15612489576124898d83868885613a58565b50505050505b60010161239b565b508481146124b85760405163734fff6760e11b815260040160405180910390fd5b5050505050612607565b606060006125008989858181106124e957634e487b7160e01b600052603260045260246000fd5b90506020028101906124fb91906152bb565b613c98565b60e00151915060009050808061251584613d80565b92509250925060005b828110156126015760408486010151602090600061253d8d8d84613a07565b90508b811480612577575089818151811061256857634e487b7160e01b600052603260045260246000fd5b60209081029190910101515115155b1561258857505050928101926125f9565b6000612595898988613eaf565b5090506125a283826138c5565b80518c516001600160401b03918216911681108015906125cf57508c602001516001600160401b03168111155b80156125dd57508c60400151155b156125ef576125ef8c84868585613a58565b5050509483019450505b60010161251e565b50505050505b600101612267565b5060005b8381101561266c5781818151811061263b57634e487b7160e01b600052603260045260246000fd5b602090810291909101015151612664576040516345805f5d60e01b815260040160405180910390fd5b600101612613565b5095945050505050565b60006126838260046153c9565b835110156126ca5760405162461bcd60e51b8152602060048201526014602482015273746f55696e7433325f6f75744f66426f756e647360601b604482015260640161096a565b50016004015190565b60006126e08260016153c9565b835110156127265760405162461bcd60e51b8152602060048201526013602482015272746f55696e74385f6f75744f66426f756e647360681b604482015260640161096a565b50016001015190565b600061273c8260026153c9565b835110156127835760405162461bcd60e51b8152602060048201526014602482015273746f55696e7431365f6f75744f66426f756e647360601b604482015260640161096a565b50016002015190565b60608161279a81601f6153c9565b10156127d95760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b604482015260640161096a565b6127e382846153c9565b845110156128275760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b604482015260640161096a565b6060821580156128465760405191506000825260208201604052612890565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561287f578051835260209283019201612867565b5050858452601f01601f1916604052505b50949350505050565b6000818311156128b4576128ad82846154eb565b9050610a81565b6128ad83836154eb565b6033546001600160a01b031633146110885760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161096a565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006129778260206153c9565b835110156129bf5760405162461bcd60e51b8152602060048201526015602482015274746f427974657333325f6f75744f66426f756e647360581b604482015260640161096a565b50016020015190565b60006129d58260146153c9565b83511015612a1d5760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b604482015260640161096a565b500160200151600160601b900490565b612a3561466b565b600080612a4a60c9546001600160a01b031690565b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b8152600401612a7591906150ca565b60006040518083038186803b158015612a8d57600080fd5b505afa158015612aa1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612ac99190810190614cdb565b509150915080612aec57604051632acbe91560e01b815260040160405180910390fd5b612afe82606001518360800151610e0e565b612b1b5760405163360f2d8760e01b815260040160405180910390fd5b60d2546001600160401b03166001600160401b03168260a001516001600160401b031611612b5c576040516388d1b84760e01b815260040160405180910390fd5b612b698260a001516135ab565b5092915050565b610b6a81613fa0565b6000612bad6040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b9050600080612bc460c9546001600160a01b031690565b845160405163607ec5ef60e11b81526001600160a01b03929092169163c0fd8bde91612bf2916004016150ca565b60006040518083038186803b158015612c0a57600080fd5b505afa158015612c1e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612c469190810190614cdb565b509150915080612c6957604051632acbe91560e01b815260040160405180910390fd5b6000612c788360e00151610e31565b9050612c826113bd565b61ffff16816040015161ffff1614158015612ca45750604081015161ffff1615155b15612cc2576040516363daeb7760e01b815260040160405180910390fd5b600581602001516006811115612ce857634e487b7160e01b600052602160045260246000fd5b14612d06576040516397363b3560e01b815260040160405180910390fd5b6000612d15826060015161108a565b805190915063ffffffff16612d2f60d45463ffffffff1690565b63ffffffff1610612d53576040516388d1b84760e01b815260040160405180910390fd5b805160d4805463ffffffff191663ffffffff90921691909117905560408051808201909152606085015161ffff1680825260808601516020830181905260d0805461ffff191690921790915560d155612daf8560a001516135ab565b7f6bce23ef3d34e51710fe4700b43ba5f1733a6215c883f384671a4ece3ea8aa2086612e036040805180820182526000808252602091820152815180830190925260d05461ffff16825260d1549082015290565b60d25460408051845161ffff90811682526020958601518683015284511691810191909152929091015160608301526001600160401b0316608082015260a0015b60405180910390a150505050505050565b6000612e5f611446565b905060005b8151811015612ed757600060c96004016000612ea6858581518110612e9957634e487b7160e01b600052603260045260246000fd5b6020026020010151611265565b81526020810191909152604001600020805460ff1916911515919091179055612ed06001826153c9565b9050612e64565b50612ee460cc60006146c6565b60005b825151811015612fb9578251805160cc919083908110612f1757634e487b7160e01b600052603260045260246000fd5b60209081029190910181015182546001808201855560009485528385208351600290930201805461ffff191661ffff90931692909217825591909201519181019190915584518051919260cd929091612f889186908110612e9957634e487b7160e01b600052603260045260246000fd5b81526020810191909152604001600020805460ff191691151591909117905580612fb18161552e565b915050612ee7565b507fd451e0fcb7c5b9e13de533604d158069dad159841c45f39f09d379bfc423080d81612fe4611446565b604051612ff2929190615027565b60405180910390a15050565b600061300960ce5490565b825160ce5590507f74dbbbe280ef27b79a8a0c449d5ae2ba7a31849103241d0f98df70bbc9d03e378161303b60ce5490565b60408051928352602083019190915201612ff2565b600061305b60cf5490565b825160cf5590507fcdb88a22f82ddd76115ab7c66cf08eb1e40afe80c9b31017eb2cbdb1570b33ae8161303b60cf5490565b60006130a160c9546001600160a01b031690565b90506130b08360000151613589565b6000806130c560c9546001600160a01b031690565b6001600160a01b031663c0fd8bde856040518263ffffffff1660e01b81526004016130f091906150ca565b60006040518083038186803b15801561310857600080fd5b505afa15801561311c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526131449190810190614cdb565b509150915080613167576040516397363b3560e01b815260040160405180910390fd5b61317982606001518360800151610e0e565b613196576040516397363b3560e01b815260040160405180910390fd5b60d2546001600160401b03166001600160401b03168260a001516001600160401b0316146131d7576040516309e9f6c160e11b815260040160405180910390fd5b60006131e68360e00151610e31565b905060068160200151600681111561320e57634e487b7160e01b600052602160045260246000fd5b1461322c576040516309e9f6c160e11b815260040160405180910390fd5b600061323b8260600151611234565b875181519192506001600160a01b0391821691161461326d576040516309e9f6c160e11b815260040160405180910390fd5b7fd495c4e5b386d59bccca38a2277b5d70a0f5e47d7b6587a45a6f5aca221a3125856132a160c9546001600160a01b031690565b604080516001600160a01b03938416815292909116602083015201612e44565b6132c9614636565b50600090815260d56020908152604091829020825160c08101845281546001600160401b038082168352600160401b808304600390810b810b900b95840195909552600160601b8204600790810b810b810b96840196909652600160a01b9091048116606083015260019092015480850b850b90940b60808201529190920490911660a082015290565b60046000833560e01c63504e415581146133805760405163734fff6760e11b815260040160405180910390fd5b60018084019386013560f81c9081146133ac5760405163734fff6760e11b815260040160405180910390fd5b50508184016001013560f890811c9092016002818101939186010135901c60ff1680156133e957634e487b7160e01b600052602160045260246000fd5b600192909201919050818310156134135760405163734fff6760e11b815260040160405180910390fd5b9250929050565b60008382013560f01c61342e6002846153c9565b925061343e61ffff8216846153c9565b92508483013560f81c5b95945050505050565b600061345c60ce5490565b610a8190836154cc565b60008060006134758585613353565b9092509050600081801561349957634e487b7160e01b600052602160045260246000fd5b146134b75760405163734fff6760e11b815260040160405180910390fd5b6000803660006134c889898861368f565b919a50929650909450909250905060005b8760ff1681101561351a576134ec614636565b6000806134fb8787878b6137d1565b929a509094509250905061350f82846138c5565b5050506001016134d9565b5083811461353b5760405163734fff6760e11b815260040160405180910390fd5b50505050505092915050565b610d576135548383613c98565b61409e565b600054610100900460ff166135805760405162461bcd60e51b815260040161096a90615175565b61108833612918565b60c980546001600160a01b0319166001600160a01b0392909216919091179055565b60d2805467ffffffffffffffff19166001600160401b0392909216919091179055565b6001600160a01b0381163b61363b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161096a565b6000805160206155b183398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61367383614145565b6000825111806136805750805b15612085576118308383614185565b6000808036816136a3888888808203614270565b600296509092509050813560f01c606060006136c96136c486868b87614270565b61429a565b60e0015160048082015161ffff86169a909a01999193509150634155575663ffffffff82161461370c5760405163734fff6760e11b815260040160405180910390fd5b8183016001015160009060ff16801561373557634e487b7160e01b600052602160045260246000fd5b6001909301929050600081801561375c57634e487b7160e01b600052602160045260246000fd5b1461377a5760405163734fff6760e11b815260040160405180910390fd5b602c84840101518451600160601b90910460601b99506020909301928311156137b65760405163734fff6760e11b815260040160405180910390fd5b5050600188019b969a505050509381013560f81c9550935050565b60006137db614636565b600283019260009081903690829089013560f01c6137fb8a8a8a84614270565b925092508061ffff168801975060006138188b8b8b8f888861436e565b985090508061383a5760405163734fff6760e11b815260040160405180910390fd5b6000843560f81c801561385d57634e487b7160e01b600052602160045260246000fd5b9050600081801561387e57634e487b7160e01b600052602160045260246000fd5b141561389c5761389085856001614416565b919950975095506138b5565b60405163734fff6760e11b815260040160405180910390fd5b5050505050945094509450949050565b600082815260d5602052604090205481516001600160401b03918216911681101561208557600083815260d560209081526040918290208451815486840151878601516060808a01516001600160401b039586166001600160601b03199095168517600160401b63ffffffff60039690960b959095168502176fffffffffffffffffffffffffffffffff60601b1916600160601b600794850b8089169190910267ffffffffffffffff60a01b191691909117600160a01b92881692830217885560808c01516001909801805460a08e01519990950b88166fffffffffffffffffffffffffffffffff1990951694909417979096169093029590951790558551918252938101919091529283019190915284917fd06a6b7f4918494b3719217d1802786c1f5112a6c1d88fe2cfec00b4584f6aec910160405180910390a2505050565b6000805b83811015611b8f5782858583818110613a3457634e487b7160e01b600052603260045260246000fd5b905060200201351415613a4657611b8f565b80613a508161552e565b915050613a0b565b82858581518110613a7957634e487b7160e01b600052603260045260246000fd5b602002602001015160000181815250508160400151858581518110613aae57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516000019060070b908160070b815250508160600151858581518110613aef57634e487b7160e01b600052603260045260246000fd5b602002602001015160200151602001906001600160401b031690816001600160401b0316815250508160200151858581518110613b3c57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516040019060030b908160030b8152505080858581518110613b7957634e487b7160e01b600052603260045260246000fd5b60200260200101516020015160600181815250508160800151858581518110613bb257634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516000019060070b908160070b815250508160a00151858581518110613bf357634e487b7160e01b600052603260045260246000fd5b602002602001015160400151602001906001600160401b031690816001600160401b0316815250508160200151858581518110613c4057634e487b7160e01b600052603260045260246000fd5b6020026020010151604001516040019060030b908160030b8152505080858581518110613c7d57634e487b7160e01b600052603260045260246000fd5b60200260200101516040015160600181815250505050505050565b613ca061466b565b6000613cb460c9546001600160a01b031690565b6001600160a01b031663c0fd8bde85856040518363ffffffff1660e01b8152600401613ce192919061509b565b60006040518083038186803b158015613cf957600080fd5b505afa158015613d0d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613d359190810190614cdb565b50909250905080613d5957604051632acbe91560e01b815260040160405180910390fd5b50613d6381614504565b610a815760405163e60dce7160e01b815260040160405180910390fd5b6000808080613d93858260049101015190565b90506004840193508063ffffffff16635032574814613dc55760405163734fff6760e11b815260040160405180910390fd5b6002858501810151940193600361ffff821614613df55760405163734fff6760e11b815260040160405180910390fd5b6002850194506000613e0b878760029101015190565b90506002860195506000613e23888860019101015190565b90508161ffff16870196508060ff16600214613e525760405163734fff6760e11b815260040160405180910390fd5b505050508284016002015161ffff169150600283019250613e77848460029101015190565b61ffff1690506002830192508181028301845114613ea85760405163734fff6760e11b815260040160405180910390fd5b9193909250565b613eb7614636565b6040838501818101516048820151600790810b810b9385019390935260508201516001600160401b0390811660608601526054830151600390810b900b6020860152605c830151840b90930b60808501526064820151831660a08501526065820151607d9283015190931684529160ff811660011415613f3c57601882019150613f75565b858201870160088101516001600160401b0390811686526010820151600790810b900b6040870152601891820151166060860152909101905b5083811115613f975760405163734fff6760e11b815260040160405180910390fd5b50935093915050565b6000613faa61202e565b8251909150613fba906000610b38565b306001600160a01b031663e3795cc16040518163ffffffff1660e01b815260040160206040518083038186803b158015613ff357600080fd5b505afa158015614007573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061402b9190614e8f565b63ffffffff166397a6f30414614054576040516397363b3560e01b815260040160405180910390fd5b7f2e4cc16c100f0b55e2df82ab0b1a7e294aa9cbd01b48fbaf622683fbc0507a498161407e61202e565b604080516001600160a01b03938416815292909116602083015201612ff2565b60e0810151600080806140b084613d80565b92509250925060005b828110156140ec576000806140cf878786613eaf565b9150915083860195506140e281836138c5565b50506001016140b9565b50606085015160a08601516040805161ffff90931683526001600160401b0390911660208301527f943f0e8a16c19895fb87cbeb1a349ed86d7f31923089dd36c1a1ed5e300f267b910160405180910390a15050505050565b61414e816135ce565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606001600160a01b0383163b6141ed5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b606482015260840161096a565b600080846001600160a01b0316846040516142089190614fc9565b600060405180830381855af49150503d8060008114614243576040519150601f19603f3d011682016040523d82523d6000602084013e614248565b606091505b509150915061344882826040518060600160405280602781526020016155d160279139614520565b36600085848661428086836153c9565b9261428d939291906153a1565b9150915094509492505050565b6142a261466b565b60006142b660c9546001600160a01b031690565b6001600160a01b031663c0fd8bde85856040518363ffffffff1660e01b81526004016142e392919061509b565b60006040518083038186803b1580156142fb57600080fd5b505afa15801561430f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526143379190810190614cdb565b5090925090508061435b57604051632acbe91560e01b815260040160405180910390fd5b50613d6381606001518260800151610b6d565b60008060006143b285858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061453992505050565b600188019790915089013560f81c60005b8160ff168110156143f55760148901988b01356001600160601b0319166143ea848261456c565b9350506001016143c3565b50506001600160601b03199081169516949094149794965093945050505050565b61441e614636565b60208483018181013560c090811c600790810b900b6040858101919091526028830135821c6060860152603083013560e01c600390810b900b85850152603483013590911c84528051601f8701849004840281018401909152858152603c909401939035916000916144ac918890889081908401838280828437600092019190915250889250614518915050565b868501600881013560c090811c600790810b900b6080870152601090910135901c60a08501526018909401939050848411156144fb5760405163734fff6760e11b815260040160405180910390fd5b93509350939050565b6000610a8182606001518360800151610b6d565b016008015190565b6060831561452f575081610e2a565b610e2a83836145b8565b6000610a81600083604051602001614552929190614fe5565b604051602081830303815290604052805160209091012090565b60006001600160601b03198083169084161115614587579091905b604051600160f81b60208201526001600160601b0319808516602183015283166035820152610e2a90604901614552565b8151156145c85781518083602001fd5b8060405162461bcd60e51b815260040161096a91906150ca565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604080516060810190915260008152602081016146246145e2565b81526020016146316145e2565b905290565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b604080516101608101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201819052610100820183905261012082015261014081019190915290565b5080546000825560020290600052602060002090810190610b6a91905b8082111561470357805461ffff19168155600060018201556002016146e3565b5090565b80356001600160a01b038116811461471e57600080fd5b919050565b60008083601f840112614734578182fd5b5081356001600160401b0381111561474a578182fd5b6020830191508360208260051b850101111561341357600080fd5b600082601f830112614775578081fd5b815160206001600160401b0382111561479057614790615575565b61479e818360051b0161534a565b80838252828201915082860187848660071b89010111156147bd578586fd5b855b8581101561482057608080838b0312156147d7578788fd5b6147df6152ff565b83518152868401518782015260406147f88186016148fb565b9082015260606148098582016148fb565b9082015285529385019391909101906001016147bf565b5090979650505050505050565b8051801515811461471e57600080fd5b600082601f83011261484d578081fd5b813561486061485b8261537a565b61534a565b818152846020838601011115614874578283fd5b816020850160208301379081016020019190915292915050565b600082601f83011261489e578081fd5b81516148ac61485b8261537a565b8181528460208386010111156148c0578283fd5b611b8f826020830160208701615502565b805161471e8161558b565b805163ffffffff8116811461471e57600080fd5b805161471e8161559b565b805160ff8116811461471e57600080fd5b60006020828403121561491d578081fd5b610e2a82614707565b6000806000806000806000806000806101008b8d031215614945578586fd5b61494e8b614707565b995060208b01356001600160401b0380821115614969578788fd5b6149758e838f01614723565b909b50995060408d013591508082111561498d578788fd5b5061499a8d828e01614723565b90985096505060608b01356149ae8161558b565b945060808b0135935060a08b01356149c58161559b565b8093505060c08b0135915060e08b013590509295989b9194979a5092959850565b600080604083850312156149f8578182fd5b614a0183614707565b915060208301356001600160401b03811115614a1b578182fd5b614a278582860161483d565b9150509250929050565b60008060208385031215614a43578182fd5b82356001600160401b03811115614a58578283fd5b614a6485828601614723565b90969095509350505050565b60008060008060008060608789031215614a88578384fd5b86356001600160401b0380821115614a9e578586fd5b614aaa8a838b01614723565b90985096506020890135915080821115614ac2578586fd5b614ace8a838b01614723565b90965094506040890135915080821115614ae6578384fd5b50614af389828a01614723565b979a9699509497509295939492505050565b60008060008060008060808789031215614b1d578384fd5b86356001600160401b0380821115614b33578586fd5b614b3f8a838b01614723565b90985096506020890135915080821115614b57578586fd5b50614b6489828a01614723565b9095509350506040870135614b788161559b565b91506060870135614b888161559b565b809150509295509295509295565b600060208284031215614ba7578081fd5b5035919050565b600060208284031215614bbf578081fd5b5051919050565b60008060408385031215614bd8578182fd5b50508035926020909101359150565b60008060208385031215614bf9578182fd5b82356001600160401b0380821115614c0f578384fd5b818501915085601f830112614c22578384fd5b813581811115614c30578485fd5b866020828501011115614c41578485fd5b60209290920196919550909350505050565b600060208284031215614c64578081fd5b81356001600160401b03811115614c79578182fd5b611b8f8482850161483d565b600060408284031215614c96578081fd5b604051604081018181106001600160401b0382111715614cb857614cb8615575565b6040528235614cc68161558b565b81526020928301359281019290925250919050565b600080600060608486031215614cef578081fd5b83516001600160401b0380821115614d05578283fd5b908501906101608288031215614d19578283fd5b614d21615327565b614d2a836148fb565b8152614d38602084016148dc565b6020820152614d49604084016148dc565b6040820152614d5a606084016148d1565b606082015260808301516080820152614d7560a084016148f0565b60a0820152614d8660c084016148fb565b60c082015260e083015182811115614d9c578485fd5b614da88982860161488e565b60e083015250610100614dbc8185016148dc565b908201526101208381015183811115614dd3578586fd5b614ddf8a828701614765565b918301919091525061014083810151908201529450614e006020870161482d565b93506040860151915080821115614e15578283fd5b50614e228682870161488e565b9150509250925092565b600060208284031215614e3d578081fd5b8135610e2a8161558b565b600060208284031215614e59578081fd5b8151610e2a8161558b565b60008060408385031215614e76578182fd5b8235614e818161558b565b946020939093013593505050565b600060208284031215614ea0578081fd5b610e2a826148dc565b600060208284031215614eba578081fd5b8135610e2a8161559b565b6000815180845260208085019450808401835b83811015614f0c57614ef9878351805161ffff168252602090810151910152565b6040969096019590820190600101614ed8565b509495945050505050565b60008151808452614f2f816020860160208601615502565b601f01601f19169290920160200192915050565b805182526020810151614f896020840182805160070b82526001600160401b036020820151166020830152604081015160030b6040830152606081015160608301525050565b50604081810151805160070b60a085015260208101516001600160401b031660c08501529081015160030b60e08401526060810151610100840152612085565b60008251614fdb818460208701615502565b9190910192915050565b60ff60f81b8360f81b16815260008251615006816001850160208701615502565b919091016001019392505050565b602081526000610e2a6020830184614ec5565b60408152600061503a6040830185614ec5565b82810360208401526134488185614ec5565b6020808252825182820181905260009190848201906040850190845b8181101561508f5761507b838551614f43565b928401926101209290920191600101615068565b50909695505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b602081526000610e2a6020830184614f17565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6020815260008251602080840152611b8f6040840182614f17565b815161ffff1681526020808301519082015260408101610a81565b60208152600082516004811061520e5761520e61555f565b8060208401525060208301516007811061522a5761522a61555f565b8060408401525061ffff60408401511660608301526060830151608080840152611b8f60a0840182614f17565b6101208101610a818284614f43565b815160070b81526020808301516001600160401b03169082015260408083015160030b908201526060808301519082015260808101610a81565b6020815260008251602080840152611b8f6040840182614ec5565b6000808335601e198436030181126152d1578283fd5b8301803591506001600160401b038211156152ea578283fd5b60200191503681900382131561341357600080fd5b604051608081016001600160401b038111828210171561532157615321615575565b60405290565b60405161016081016001600160401b038111828210171561532157615321615575565b604051601f8201601f191681016001600160401b038111828210171561537257615372615575565b604052919050565b60006001600160401b0382111561539357615393615575565b50601f01601f191660200190565b600080858511156153b0578182fd5b838611156153bc578182fd5b5050820193919092039150565b600082198211156153dc576153dc615549565b500190565b600181815b8085111561541c57816000190482111561540257615402615549565b8085161561540f57918102915b93841c93908002906153e6565b509250929050565b6000610e2a838360008261543a57506001610a81565b8161544757506000610a81565b816001811461545d576002811461546757615483565b6001915050610a81565b60ff84111561547857615478615549565b50506001821b610a81565b5060208310610133831016604e8410600b84101617156154a6575081810a610a81565b6154b083836153e1565b80600019048211156154c4576154c4615549565b029392505050565b60008160001904831182151516156154e6576154e6615549565b500290565b6000828210156154fd576154fd615549565b500390565b60005b8381101561551d578181015183820152602001615505565b838111156118305750506000910152565b600060001982141561554257615542615549565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b61ffff81168114610b6a57600080fd5b6001600160401b0381168114610b6a57600080fdfe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220ab7582184ce1397c9a45ad113da76101d50500a9eecd891a38118da7c3ec8d7864736f6c63430008040033
Deployed Bytecode Sourcemap
488:2163:32:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;614:796;;;;;;;;;;-1:-1:-1;614:796:32;;;;;:::i;:::-;;:::i;:::-;;6209:359:28;;;;;;;;;;-1:-1:-1;6209:359:28;;;;;:::i;:::-;;:::i;:::-;;;31154:13:35;;31136:32;;31124:2;31109:18;6209:359:28;;;;;;;;871:185:14;;;;;;;;;;-1:-1:-1;871:185:14;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;3317:197:5:-;;;;;;;;;;-1:-1:-1;3317:197:5;;;;;:::i;:::-;;:::i;2060:171:26:-;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;2190:34:26;;;;;;;;2197:27;2190:34;;;;;;;;;;;2060:171;;;;;;:::i;897:408::-;;;;;;;;;;-1:-1:-1;897:408:26;;;;;:::i;:::-;;:::i;:::-;;;19031:14:35;;19024:22;19006:41;;18994:2;18979:18;897:408:26;18961:92:35;23205:586:23;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2237:110:26:-;;;;;;;;;;-1:-1:-1;2313:27:26;;2237:110;;;19204:25:35;;;19192:2;19177:18;2237:110:26;19159:76:35;530:163:26;;;;;;;;;;-1:-1:-1;530:163:26;;;;;:::i;:::-;618:6;643:31;;;:22;:31;;;;;:43;-1:-1:-1;;;;;643:43:26;;530:163;;;;-1:-1:-1;;;;;33316:31:35;;;33298:50;;33286:2;33271:18;530:163:26;33253:101:35;5659:466:28;;;;;;;;;;-1:-1:-1;5659:466:28;;;;;:::i;:::-;;:::i;3763:222:5:-;;;;;;:::i;:::-;;:::i;3006:131::-;;;;;;;;;;;;;:::i;26592:86:23:-;;;;;;;;;;-1:-1:-1;26657:14:23;;;;;;;;;;;-1:-1:-1;;;26657:14:23;;;;26592:86;;;;26657:14;26592:86;:::i;1751:132:26:-;;;;;;;;;;-1:-1:-1;1839:37:26;;-1:-1:-1;;;;;1839:37:26;1751:132;;1311:336;;;;;;;;;;-1:-1:-1;1311:336:26;;;;;:::i;:::-;;:::i;2327:1080:28:-;;;;;;;;;;-1:-1:-1;2327:1080:28;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2473:122:26:-;;;;;;;;;;-1:-1:-1;2556:32:26;;;;2473:122;;;33131:10:35;33119:23;;;33101:42;;33089:2;33074:18;2473:122:26;33056:93:35;2053:320:14;;;;;;;;;;-1:-1:-1;2053:320:14;;;;;:::i;:::-;;:::i;2071:101:0:-;;;;;;;;;;;;;:::i;4326:443:28:-;;;;;;;;;;-1:-1:-1;4326:443:28;;;;;:::i;:::-;;:::i;:::-;;;30499:13:35;;30514:10;30495:30;30477:49;;30465:2;30450:18;4326:443:28;30432:100:35;239:102:26;;;;;;;;;;-1:-1:-1;318:6:26;:15;-1:-1:-1;;;;;318:15:26;239:102;;;-1:-1:-1;;;;;16860:32:35;;;16842:51;;16830:2;16815:18;239:102:26;16797::35;4853:730:28;;;;;;;;;;-1:-1:-1;4853:730:28;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;3492:364::-;;;;;;;;;;-1:-1:-1;3492:364:28;;;;;:::i;:::-;;:::i;:::-;;;31700:13:35;;-1:-1:-1;;;;;31696:39:35;31678:58;;31666:2;31651:18;3492:364:28;31633:109:35;699:192:26;;;;;;;;;;-1:-1:-1;699:192:26;;;;;:::i;:::-;;:::i;1441:85:0:-;;;;;;;;;;-1:-1:-1;1513:6:0;;-1:-1:-1;;;;;1513:6:0;1441:85;;11762:429:23;;;;;;;;;;-1:-1:-1;11762:429:23;;;;;:::i;:::-;;:::i;11075:420::-;;;;;;;;;;-1:-1:-1;11075:420:23;;;;;:::i;:::-;;:::i;1653:92:26:-;;;;;;;;;;;;;:::i;:::-;;;32216:6:35;32204:19;;;32186:38;;32174:2;32159:18;1653:92:26;32141:89:35;1889:165:26;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;1493:314:14:-;;;;;;;;;;-1:-1:-1;1493:314:14;;;;;:::i;:::-;;:::i;23797:591:23:-;;;;;;:::i;:::-;;:::i;1062:191:14:-;;;;;;;;;;-1:-1:-1;1062:191:14;;;;;:::i;:::-;;:::i;26332:134:23:-;;;;;;;;;;-1:-1:-1;26332:134:23;;;;;:::i;:::-;26399:4;643:31:26;;;:22;:31;;;;;:43;-1:-1:-1;;;;;643:43:26;26423:35:23;;;26332:134;1831:1916:27;;;;;;;;;;-1:-1:-1;1831:1916:27;;;;;:::i;:::-;;:::i;10067:741:23:-;;;;;;:::i;:::-;;:::i;25567:759::-;;;;;;;;;;-1:-1:-1;25567:759:23;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2353:114:26:-;;;;;;;;;;-1:-1:-1;2431:29:26;;2353:114;;3546:976:23;;;;;;;;;;-1:-1:-1;3546:976:23;;;;;:::i;:::-;;:::i;3963:256:28:-;;;;;;;;;;-1:-1:-1;3963:256:28;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;4182:30:28;;;-1:-1:-1;3963:256:28;;;;;;;;:::i;3217:323:23:-;;;;;;;;;;-1:-1:-1;3217:323:23;;;;;:::i;:::-;;:::i;26472:114::-;;;;;;;;;;;;;:::i;1853:94:32:-;;;;;;;;;;-1:-1:-1;1930:10:32;1853:94;;2306:822:23;;;;;;:::i;:::-;;:::i;2321:198:0:-;;;;;;;;;;-1:-1:-1;2321:198:0;;;;;:::i;:::-;;:::i;614:796:32:-;3268:19:4;3291:13;;;;;;3290:14;;3336:34;;;;-1:-1:-1;3354:12:4;;3369:1;3354:12;;;;:16;3336:34;3335:108;;;-1:-1:-1;3415:4:4;1476:19:6;:23;;;3376:66:4;;-1:-1:-1;3425:12:4;;;;;:17;3376:66;3314:201;;;;-1:-1:-1;;;3314:201:4;;23818:2:35;3314:201:4;;;23800:21:35;23857:2;23837:18;;;23830:30;23896:34;23876:18;;;23869:62;-1:-1:-1;;;23947:18:35;;;23940:44;24001:19;;3314:201:4;;;;;;;;;3525:12;:16;;-1:-1:-1;;3525:16:4;3540:1;3525:16;;;3551:65;;;;3585:13;:20;;-1:-1:-1;;3585:20:4;;;;;3551:65;1000:16:32::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:4::0;3636:99;;;3686:5;3670:21;;-1:-1:-1;;3670:21:4;;;3710:14;;-1:-1:-1;20236:36:35;;3710:14:4;;20224:2:35;20209:18;3710:14:4;;;;;;;3636:99;614:796:32;;;;;;;;;;;:::o;6209:359:28:-;-1:-1:-1;;;;;;;;;;;;6353:10:28;6407:30;:14;6353:10;6407:23;:30::i;:::-;-1:-1:-1;;;;;6399:39:28;6378:60;;6448:10;6457:1;6448:10;;:::i;:::-;;;6498:5;6473:14;:21;:30;6469:92;;6524:37;;-1:-1:-1;;;6524:37:28;;;;;;;;;;;6469:92;6209:359;;;;:::o;871:185:14:-;955:30;;:::i;:::-;1004:45;1024:2;1028:20;:18;:20::i;1004:45::-;997:52;871:185;-1:-1:-1;;871:185:14:o;3317:197:5:-;1889:4;-1:-1:-1;;;;;1898:6:5;1881:23;;;1873:80;;;;-1:-1:-1;;;1873:80:5;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:5;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:5;;1963:87;;;;-1:-1:-1;;;1963:87:5;;;;;;;:::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:5::1;;3501:5;3446:21;:61::i;:::-;3317:197:::0;:::o;897:408:26:-;1135:131;;;15821:3:35;15799:16;;;;-1:-1:-1;;;;;;15795:38:35;1135:131:26;;;;15783:51:35;;;;15850:11;;;;15843:27;;;;1135:131:26;;;;;;;;;;15886:12:35;;;;1135:131:26;;1104:180;;;;;;;;;-1:-1:-1;1062:236:26;;;:24;:236;;;;;;;;;897:408::o;23205:586:23:-;23445:41;23521:263;23568:10;;23596:8;;23622:148;;;;;;;;23675:14;-1:-1:-1;;;;;23622:148:23;;;;;23711:14;-1:-1:-1;;;;;23622:148:23;;;;;23747:5;23622:148;;;;;23521:29;:263::i;:::-;23502:282;23205:586;-1:-1:-1;;;;;;;23205:586:23:o;5659:466:28:-;-1:-1:-1;;;;;;;;;;;;5786:10:28;;5824:30;:14;5786:10;5824:23;:30::i;:::-;5811:43;-1:-1:-1;5864:10:28;5873:1;5864:10;;:::i;:::-;;-1:-1:-1;5885:11:28;5899:30;:14;5864:10;5899:23;:30::i;:::-;5885:44;-1:-1:-1;5939:10:28;5948:1;5939:10;;:::i;:::-;;-1:-1:-1;5987:28:28;-1:-1:-1;;;;;6002:13:28;;5995:2;5987:28;:::i;:::-;5972:43;;-1:-1:-1;;;;;5972:12:28;;:43;:::i;:::-;5960:55;;6030:21;;:30;;6026:92;;6081:37;;-1:-1:-1;;;6081:37:28;;;;;;;;;;;6026:92;5659:466;;;;;;:::o;3763:222:5:-;1889:4;-1:-1:-1;;;;;1898:6:5;1881:23;;;1873:80;;;;-1:-1:-1;;;1873:80:5;;;;;;;:::i;:::-;1995:6;-1:-1:-1;;;;;1971:30:5;:20;:18;:20::i;:::-;-1:-1:-1;;;;;1971:30:5;;1963:87;;;;-1:-1:-1;;;1963:87:5;;;;;;;:::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:5;2316:23;;2308:92;;;;-1:-1:-1;;;2308:92:5;;22983:2:35;2308:92:5;;;22965:21:35;23022:2;23002:18;;;22995:30;23061:34;23041:18;;;23034:62;23132:26;23112:18;;;23105:54;23176:19;;2308:92:5;22955:246:35;2308:92:5;-1:-1:-1;;;;;;;;;;;;3006:131:5;:::o;1311:336:26:-;1486:27;:35;1451:4;;1486:56;;;;:35;;:56;:154;;;;-1:-1:-1;1558:42:26;;:82;;1486:154;1467:173;1311:336;-1:-1:-1;;;1311:336:26:o;2327:1080:28:-;2431:31;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2431:31:28;2474:10;;2514:34;:18;2474:10;2514:27;:34::i;:::-;2499:49;-1:-1:-1;2563:14:28;;;535:10;2563:14;2559:64;;2586:37;;-1:-1:-1;;;2586:37:28;;;;;;;;;;;2559:64;2634:10;2643:1;2634:10;;:::i;:::-;;-1:-1:-1;2655:15:28;2673:33;:18;2634:10;2673:26;:33::i;:::-;2655:51;;2745:9;2728:27;;;;;;;;-1:-1:-1;;;2728:27:28;;;;;;;;;2716:2;;:39;;;;;;-1:-1:-1;;;2716:39:28;;;;;;;;;;;;;;;;;-1:-1:-1;;;2716:39:28;;;;;;;;;;;-1:-1:-1;2765:10:28;2774:1;2765:10;;:::i;:::-;;-1:-1:-1;823:23:28;2790:9;;:19;;;;;;-1:-1:-1;;;2790:19:28;;;;;;;;;;2786:68;;2818:36;;-1:-1:-1;;;2818:36:28;;;;;;;;;;;2786:68;2865:18;2886:33;:18;2913:5;2886:26;:33::i;:::-;2865:54;;2958:12;2941:30;;;;;;;;-1:-1:-1;;;2941:30:28;;;;;;;;;2929:2;:9;;:42;;;;;;;-1:-1:-1;;;2929:42:28;;;;;;;;;;;;;;;;;-1:-1:-1;;;2929:42:28;;;;;;;;;;;-1:-1:-1;2981:10:28;2990:1;2981:10;;:::i;:::-;;-1:-1:-1;3021:34:28;:18;2981:10;3021:27;:34::i;:::-;3002:53;;:16;;;:53;3065:10;3074:1;3065:10;;:::i;:::-;;;3300:100;3338:5;3385;3357:18;:25;:33;;;;:::i;:::-;3300:18;;:100;:24;:100::i;:::-;3287:10;;;:113;-1:-1:-1;3287:2:28;;2327:1080;-1:-1:-1;;;;2327:1080:28:o;2053:320:14:-;2167:30;;:::i;:::-;2217:21;2235:2;2217:17;:21::i;:::-;2209:29;;2296:3;2253:40;2258:15;2275:5;:17;;;2253:4;:40::i;:::-;:46;2249:94;;;2320:23;;-1:-1:-1;;;2320:23:14;;;;;;;;;;;2071:101:0;1334:13;:11;:13::i;:::-;2135:30:::1;2162:1;2135:18;:30::i;:::-;2071:101::o:0;4326:443:28:-;-1:-1:-1;;;;;;;;;;;;4546:10:28;4609:30;:14;4546:10;4609:23;:30::i;:::-;4571:68;;;;4649:10;4658:1;4649:10;;:::i;4853:730::-;-1:-1:-1;;;;;;;;;;;;4997:10:28;;5048:29;:14;4997:10;5048:22;:29::i;:::-;5022:55;-1:-1:-1;5087:10:28;5096:1;5087:10;;:::i;:::-;;;5176:17;5126:77;;-1:-1:-1;;;;;5126:77:28;;;;;-1:-1:-1;;;5126:77:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;5126:77:28;;;;;;;;;;;;;;;-1:-1:-1;5108:95:28;;:15;5214:260;5235:17;5231:21;;:1;:21;5214:260;;;5302:30;:14;5326:5;5302:23;:30::i;:::-;5273:15;;:18;;5289:1;;5273:18;;;;-1:-1:-1;;;5273:18:28;;;;;;;;;;;;;;;;;;;:59;;;;;;5346:10;5355:1;5346:10;;:::i;:::-;;-1:-1:-1;5407:31:28;:14;5346:10;5407:24;:31::i;:::-;5371:15;;:18;;5387:1;;5371:18;;;;-1:-1:-1;;;5371:18:28;;;;;;;;;;;;;;;:33;;:67;;;;;5461:2;5452:11;;;;;:::i;:::-;;-1:-1:-1;5254:3:28;;;;:::i;:::-;;;;5214:260;;;;5513:5;5488:14;:21;:30;5484:92;;5539:37;;-1:-1:-1;;;5539:37:28;;;;;;;;;;;5484:92;4853:730;;;;;:::o;3492:364::-;-1:-1:-1;;;;;;;;;;;;3637:10:28;3693:31;:14;3637:10;3693:24;:31::i;:::-;-1:-1:-1;;;;;3662:63:28;;;3735:11;3744:2;3735:11;;:::i;699:192:26:-;800:7;853:2;:10;;;865:2;:17;;;836:47;;;;;;;;15821:3:35;15799:16;;;;-1:-1:-1;;;;;;15795:38:35;15783:51;;15859:1;15850:11;;15843:27;15895:2;15886:12;;15773:131;836:47:26;;;;;;;;;;;;;826:58;;;;;;819:65;;699:192;;;:::o;11762:429:23:-;11845:30;;:::i;:::-;11887:42;11932:26;;;:22;:26;;;;;;;;;11988:16;;-1:-1:-1;;;;;11988:16:23;;;11968:17;;;:36;;;-1:-1:-1;;;12027:9:23;;;;;;;;12014:22;;;;:10;;;:22;;;;11988:16;12060:13;;;;;;;12046:27;;;;;;12096:12;;;;;12083:10;;;:25;;;;11932:26;12119:65;;12154:30;;-1:-1:-1;;;12154:30:23;;;;;;;;;;;11075:420;11155:30;;:::i;:::-;11197:42;11242:26;;;:22;:26;;;;;;;;;11298:16;;-1:-1:-1;;;;;11298:16:23;;;11278:17;;;:36;;;-1:-1:-1;;;11337:9:23;;;;;;11324:22;;;;:10;;;:22;;;;-1:-1:-1;;;11370:10:23;;;;;;11356:24;;;;;;-1:-1:-1;;;11403:9:23;;;;11390:10;;;:22;;;;11242:26;11423:65;;11458:30;;-1:-1:-1;;;11458:30:23;;;;;;;;;;;1653:92:26;1693:6;1718:10;318:6;:15;-1:-1:-1;;;;;318:15:26;;239:102;1718:10;-1:-1:-1;;;;;1718:18:26;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1711:27;;1653:92;:::o;1889:165::-;1962:39;2024:6;:23;;2017:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1889:165;:::o;1493:314:14:-;1604:30;;:::i;:::-;1654:18;1669:2;1654:14;:18::i;23797:591:23:-;24043:41;24119:262;24166:10;;24194:8;;24220:147;;;;;;;;24273:14;-1:-1:-1;;;;;24220:147:23;;;;;24309:14;-1:-1:-1;;;;;24220:147:23;;;;;24345:4;24220:147;;;;;24119:29;:262::i;1062:191:14:-;1149:30;;:::i;:::-;1198:48;1221:2;1225:20;:18;:20::i;1831:1916:27:-;1912:22;1937:29;1956:9;;1937:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1937:18:27;;-1:-1:-1;;;1937:29:27:i;:::-;1912:54;;1977:31;2011:60;2051:2;:10;;;2011:26;:60::i;:::-;1977:94;;2106:9;:7;:9::i;:::-;2086:29;;:2;:16;;;:29;;;;:54;;;;-1:-1:-1;2119:16:27;;;;:21;;;;2086:54;2082:115;;;2161:36;;-1:-1:-1;;;2161:36:27;;;;;;;;;;;2082:115;2225:32;2212:2;:9;;;:45;;;;;;-1:-1:-1;;;2212:45:27;;;;;;;;;;2208:1533;;;2277:16;;;;:21;;2273:86;;2323:36;;-1:-1:-1;;;2323:36:27;;;;;;;;;;;2273:86;2373:56;2389:39;2417:2;:10;;;2389:27;:39::i;:::-;2373:15;:56::i;:::-;2208:1533;;;2476:54;2463:2;:9;;;:67;;;;;;-1:-1:-1;;;2463:67:27;;;;;;;;;;2446:1295;;;2555:130;2610:61;2660:2;:10;;;-1:-1:-1;;;;;;;;;4182:30:28;;;-1:-1:-1;3963:256:28;2610:61:27;2555:37;:130::i;2446:1295::-;2719:31;2706:2;:9;;;:44;;;;;;-1:-1:-1;;;2706:44:27;;;;;;;;;;2702:1039;;;2766:54;2781:38;2808:2;:10;;;2781:26;:38::i;:::-;2766:14;:54::i;2702:1039::-;2854:23;2841:2;:9;;;:36;;;;;;-1:-1:-1;;;2841:36:27;;;;;;;;;;2837:904;;;2893:38;2900:30;2919:2;:10;;;2900:18;:30::i;:::-;2893:6;:38::i;2837:904::-;2965:31;2952:2;:9;;;:44;;;;;;-1:-1:-1;;;2952:44:27;;;;;;;;;;2948:793;;;3012:54;3027:38;3054:2;:10;;;3027:26;:38::i;:::-;3012:14;:54::i;2948:793::-;3113:52;3100:2;:9;;;:65;;;;;;-1:-1:-1;;;3100:65:27;;;;;;;;;;3083:658;;;3314:37;;-1:-1:-1;;;3314:37:27;;;;;;;;;;;3083:658;3385:35;3372:2;:9;;;:48;;;;;;-1:-1:-1;;;3372:48:27;;;;;;;;;;3368:373;;;3440:16;;;;:21;;3436:86;;3486:36;;-1:-1:-1;;;3486:36:27;;;;;;;;;;;3436:86;3536:119;3572:42;3603:2;:10;;;3572:30;:42::i;:::-;3632:9;;3536:119;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3536:18:27;;-1:-1:-1;;;3536:119:27:i;3368:373::-;3693:37;;-1:-1:-1;;;3693:37:27;;;;;;;;;;;3368:373;1831:1916;;;;:::o;10067:741:23:-;10264:38;;;10260:91;;10323:28;;-1:-1:-1;;;10323:28:23;;;;;;;;;;;10260:91;10367:6;10362:396;10379:19;;;10362:396;;;10586:12;;10599:1;10586:15;;;;;-1:-1:-1;;;10586:15:23;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;10544:57:23;:39;10571:8;;10580:1;10571:11;;;;;-1:-1:-1;;;10571:11:23;;;;;;;;;;;;;;;618:6:26;643:31;;;:22;:31;;;;;:43;-1:-1:-1;;;;;643:43:26;;530:163;10544:39:23;-1:-1:-1;;;;;10544:57:23;;10540:148;;;10621:28;10638:10;;10621:16;:28::i;:::-;10667:7;;;10540:148;10730:3;;10362:396;;;;10775:26;;-1:-1:-1;;;10775:26:23;;;;;;;;;;;10067:741;;;;;;;:::o;25567:759::-;25647:38;;:::i;:::-;25755:41;25799:19;25815:2;25799:15;:19::i;:::-;25832:16;;25755:63;;-1:-1:-1;;;;;;25832:21:23;25828:64;;25862:30;;-1:-1:-1;;;25862:30:23;;;;;;;;;;;25828:64;25903:17;;;25954:10;;;;;25930:15;;;;;;:34;;;;;;;;25997:9;;;;;25974:15;;-1:-1:-1;;;;;25974:32:23;;;:20;;;:32;26039:9;;;;;26016:15;;:32;;;;;;:20;;;:32;26093:16;;26058:15;;26088:22;;;26058:27;;;:52;;;;26148:13;;;;26121:18;;;;;:40;;;;;;;;26197:12;;;;26171:18;;:38;;;:23;;:38;;;;26245:9;;26219:18;;:35;;;;;;:23;;;;:35;26302:16;;26264:18;;26297:22;;26264:30;;:55;;;;25903:9;25567:759::o;3546:976::-;3641:14;;;3701:770;3718:21;;;3701:770;;;3804:1;3781:10;;3792:1;3781:13;;;;;-1:-1:-1;;;3781:13:23;;;;;;;;;;;;;;;;;;;;:::i;:::-;:20;;:24;:130;;;;-1:-1:-1;595:10:24;3825:49:23;3857:10;;3868:1;3857:13;;;;;-1:-1:-1;;;3857:13:23;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;1954:40:22;1949:3;1945:50;;1764:273;3825:49:23;:86;;;3781:130;3760:701;;;3966:11;3999:21;4041:53;4080:10;;4091:1;4080:13;;;;;-1:-1:-1;;;4080:13:23;;;;;;;;;;;;;;;;;;;;:::i;:::-;4041:38;:53::i;:::-;3944:150;;-1:-1:-1;3944:150:23;-1:-1:-1;4130:25:23;4116:10;:39;;;;-1:-1:-1;;;4116:39:23;;;;;;;;;;4112:123;;4186:30;;-1:-1:-1;;;4186:30:23;;;;;;;;;;;4112:123;4271:116;4328:10;;4339:1;4328:13;;;;;-1:-1:-1;;;4328:13:23;;;;;;;;;;;;;;;;;;;;:::i;:::-;4363:6;4271:35;:116::i;:::-;4252:135;;;;;;:::i;:::-;;;3760:701;;;;;4426:20;4445:1;4426:20;;:::i;:::-;;;3760:701;3741:3;;;;:::i;:::-;;;;3701:770;;;;4487:28;4499:15;4487:11;:28::i;:::-;4480:35;3546:976;-1:-1:-1;;;;3546:976:23:o;3217:323::-;3295:14;3519;3494:22;2313:27:26;;;2237:110;3494:22:23;3488:28;;:3;:28;:::i;:::-;:45;;;;:::i;26472:114::-;26532:4;26555:24;2431:29:26;;;2353:114;2306:822:23;2409:20;2448:6;2443:548;2460:21;;;2443:548;;;2543:1;2520:10;;2531:1;2520:13;;;;;-1:-1:-1;;;2520:13:23;;;;;;;;;;;;;;;;;;;;:::i;:::-;:20;;:24;:130;;;;-1:-1:-1;595:10:24;2564:49:23;2596:10;;2607:1;2596:13;;;;;-1:-1:-1;;;2596:13:23;;;;;;;;2564:49;:86;;;2520:130;2499:422;;;2702:90;2761:10;;2772:1;2761:13;;;;;-1:-1:-1;;;2761:13:23;;;;;;;;;;;;;;;;;;;;:::i;:::-;2702:37;:90::i;:::-;2683:109;;;;;;:::i;:::-;;;2499:422;;;2831:37;2854:10;;2865:1;2854:13;;;;;-1:-1:-1;;;2854:13:23;;;;;;;;;;;;;;;;;;;;:::i;:::-;2831:22;:37::i;:::-;2886:20;2905:1;2886:20;;:::i;:::-;;;2499:422;2963:3;;2443:548;;;;3000:16;3019:28;3031:15;3019:11;:28::i;:::-;3000:47;;3073:11;3061:9;:23;3057:64;;;3093:28;;-1:-1:-1;;;3093:28:23;;;;;;;;;;;2321:198:0;1334:13;:11;:13::i;:::-;-1:-1:-1;;;;;2409:22:0;::::1;2401:73;;;::::0;-1:-1:-1;;;2401:73:0;;20709:2:35;2401:73:0::1;::::0;::::1;20691:21:35::0;20748:2;20728:18;;;20721:30;20787:34;20767:18;;;20760:62;-1:-1:-1;;;20838:18:35;;;20831:36;20884:19;;2401:73:0::1;20681:228:35::0;2401:73:0::1;2484:28;2503:8;2484:18;:28::i;1186:320:6:-:0;-1:-1:-1;;;;;1476:19:6;;:23;;;1186:320::o;1003:95:0:-;5363:13:4;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:4;;;;;;;:::i;:::-;1065:26:0::1;:24;:26::i;1042:67:5:-:0;5363:13:4;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:4;;;;;;;:::i;515:1593:23:-;892:21;904:8;892:11;:21::i;:::-;941:81;;;924:144;;1040:28;;-1:-1:-1;;;1040:28:23;;;;;;;;;;;924:144;1084:6;1079:538;1096:36;;;1079:538;;;1153:40;1196:166;;;;;;;;1265:25;;1291:1;1265:28;;;;;-1:-1:-1;;;1265:28:23;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1196:166;;;;;;1315:26;;1342:1;1315:29;;;;;-1:-1:-1;;;1315:29:23;;;;;;;;;;;;;;;1196:166;;;1153:209;;1381:60;1411:2;:10;;;1423:2;:17;;;1381:29;:60::i;:::-;1377:117;;;1466:28;;-1:-1:-1;;;1466:28:23;;;;;;;;;;;1377:117;1556:4;1509:24;:44;1534:18;1549:2;1534:14;:18::i;:::-;1509:44;;;;;;;;;;;;-1:-1:-1;1509:44:23;;;:51;;-1:-1:-1;;1509:51:23;;;;;;;;;;;1574:23;:32;;-1:-1:-1;1574:32:23;;;;;;;;;;;;;;;;;;-1:-1:-1;;1574:32:23;;;;;;;;;;;;;;;;;;;;;1134:3;;;;:::i;:::-;;;;1079:538;;;-1:-1:-1;1684:99:23;;;;;;;;;;;;;;;;;;;;;1194:27:30;:43;;-1:-1:-1;;1194:43:30;;;;;;;;;;1850:102:23;1913:25;1850:45;:102::i;:::-;515:1593;1973:61;2011:22;1008:29:30;:54;925:144;1973:61:23;2044:57;2080:20;879:27:30;:33;817:102;2044:57:23;515:1593;;;;;;;;;;:::o;13973:327:20:-;14073:6;14116:10;:6;14125:1;14116:10;:::i;:::-;14099:6;:13;:27;;14091:60;;;;-1:-1:-1;;;14091:60:20;;22291:2:35;14091:60:20;;;22273:21:35;22330:2;22310:18;;;22303:30;-1:-1:-1;;;22349:18:35;;;22342:50;22409:18;;14091:60:20;22263:170:35;14091:60:20;-1:-1:-1;14228:29:20;14244:3;14228:29;14222:36;;13973:327::o;1563:151:2:-;-1:-1:-1;;;;;;;;;;;1642:65:2;-1:-1:-1;;;;;1642:65:2;;1563:151::o;1781:66:32:-;1334:13:0;:11;:13::i;2938:974:2:-;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:2;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3531:63:2;;;;;;;;-1:-1:-1;;3531:63:2;;;;;;;;;;;;:::i;:::-;;;3527:302;;3758:56;;-1:-1:-1;;;3758:56:2;;24233:2:35;3758:56:2;;;24215:21:35;24272:2;24252:18;;;24245:30;24311:34;24291:18;;;24284:62;-1:-1:-1;;;24362:18:35;;;24355:44;24416:19;;3758:56:2;24205:236:35;3527:302:2;-1:-1:-1;;;;;;;;;;;3644:28:2;;3636:82;;;;-1:-1:-1;;;3636:82:2;;23408:2:35;3636:82:2;;;23390:21:35;23447:2;23427:18;;;23420:30;23486:34;23466:18;;;23459:62;-1:-1:-1;;;23537:18:35;;;23530:39;23586:19;;3636:82:2;23380:231:35;3636:82:2;3595:138;3842:53;3860:17;3879:4;3885:9;3842:17;:53::i;15374:7825:23:-;15566:41;15633:16;15652:24;15665:10;;15652:12;:24::i;:::-;15633:43;;15706:11;15694:9;:23;15690:64;;;15726:28;;-1:-1:-1;;;15726:28:23;;;;;;;;;;;15690:64;-1:-1:-1;15839:8:23;-1:-1:-1;;;;;15811:44:23;;;;;-1:-1:-1;;;15811:44:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;15798:57;;15874:6;15869:7109;15886:21;;;15869:7109;;;15980:1;15957:10;;15968:1;15957:13;;;;;-1:-1:-1;;;15957:13:23;;;;;;;;;;;;;;;;;;;;:::i;:::-;:20;;:24;:138;;;;-1:-1:-1;595:10:24;16005:49:23;16037:10;;16048:1;16037:13;;;;;-1:-1:-1;;;16037:13:23;;;;;;;;16005:49;:90;;;15957:138;15932:7032;;;16136:11;16195:21;16347:107;16415:10;;16426:1;16415:13;;;;;-1:-1:-1;;;16415:13:23;;;;;;;;16347:107;16242:212;;-1:-1:-1;16242:212:23;-1:-1:-1;16499:25:23;16485:10;:39;;;;-1:-1:-1;;;16485:39:23;;;;;;;;;;16481:139;;16563:30;;-1:-1:-1;;;16563:30:23;;;;;;;;;;;16481:139;15932:7032;16664:14;16700:16;16738:22;;16940:170;17043:10;;17054:1;17043:13;;;;;-1:-1:-1;;;17043:13:23;;;;;;;;;;;;;;;;;;;;:::i;:::-;17082:6;16940:77;:170::i;:::-;16782:328;;-1:-1:-1;16782:328:23;;-1:-1:-1;16782:328:23;-1:-1:-1;16782:328:23;-1:-1:-1;16782:328:23;-1:-1:-1;17138:6:23;17133:2341;17154:10;17150:14;;:1;:14;17133:2341;;;17197:46;;:::i;:::-;17269:15;17310:22;17544:166;17605:6;17641:7;;17678:6;17544:31;:166::i;:::-;17358:352;;-1:-1:-1;17358:352:23;;-1:-1:-1;17358:352:23;-1:-1:-1;17358:352:23;-1:-1:-1;17736:48:23;17358:352;;17736:28;:48::i;:::-;17916:6;17925:37;17944:8;;17954:7;17925:18;:37::i;:::-;17916:46;-1:-1:-1;18182:20:23;;;;:45;;;18206:10;18217:1;18206:13;;;;;;-1:-1:-1;;;18206:13:23;;;;;;;;;;;;;;;;;;;:16;:21;;18182:45;18178:124;;;18263:8;;;;;;18178:124;18356:21;;18809;;-1:-1:-1;;;;;18351:27:23;;;;18794:36;;;;;;:108;;;18881:6;:21;;;-1:-1:-1;;;;;18866:36:23;:11;:36;;18794:108;:248;;;;;18940:6;:22;;;18939:23;:102;;;-1:-1:-1;19002:21:23;;-1:-1:-1;;;;;19002:39:23;;;;;;18939:102;18757:669;;;19107:288;19171:10;19219:1;19258:7;19303:9;19350:11;19107:26;:288::i;:::-;17133:2341;;;;;;17166:3;;17133:2341;;;-1:-1:-1;19499:24:23;;;19495:91;;19556:30;;-1:-1:-1;;;19556:30:23;;;;;;;;;;;19495:91;15932:7032;;;;;;;;19633:20;19701:50;19754:109;19820:10;;19831:1;19820:13;;;;;-1:-1:-1;;;19820:13:23;;;;;;;;;;;;;;;;;;;;:::i;:::-;19754:32;:109::i;:::-;19899:10;;;;-1:-1:-1;20071:10:23;;-1:-1:-1;20071:10:23;;20196:36;19899:10;20196:27;:36::i;:::-;20045:187;;;;;;20312:6;20307:2639;20328:13;20324:1;:17;20307:2639;;;14953:30:21;;;;;14947:37;20724:2:23;;21011:6;21020:37;21039:8;;21049:7;21020:18;:37::i;:::-;21011:46;-1:-1:-1;21265:20:23;;;;:45;;;21289:10;21300:1;21289:13;;;;;;-1:-1:-1;;;21289:13:23;;;;;;;;;;;;;;;;;;;:16;:21;;21265:45;21261:170;;;-1:-1:-1;;;21342:24:23;;;;21396:8;;21261:170;21487:46;21564:190;21629:7;21670:5;21709:15;21564:31;:190::i;:::-;21457:297;;;21781:48;21810:7;21819:9;21781:28;:48::i;:::-;21880:21;;22309;;-1:-1:-1;;;;;21875:27:23;;;;22294:36;;;;;;:104;;;22377:6;:21;;;-1:-1:-1;;;;;22362:36:23;:11;:36;;22294:104;:159;;;;;22431:6;:22;;;22430:23;22294:159;22261:612;;;22582:264;22642:10;22686:1;22721:7;22762:9;22805:11;22582:26;:264::i;:::-;-1:-1:-1;;;22899:24:23;;;;-1:-1:-1;;20307:2639:23;20343:3;;20307:2639;;;;15932:7032;;;;;15909:3;;15869:7109;;;;22997:6;22992:191;23009:19;;;22992:191;;;23057:10;23068:1;23057:13;;;;;;-1:-1:-1;;;23057:13:23;;;;;;;;;;;;;;;;;;;:16;23053:116;;23109:41;;-1:-1:-1;;;23109:41:23;;;;;;;;;;;23053:116;23030:3;;22992:191;;;;15374:7825;;;;;;;:::o;13640:327:20:-;13740:6;13783:10;:6;13792:1;13783:10;:::i;:::-;13766:6;:13;:27;;13758:60;;;;-1:-1:-1;;;13758:60:20;;27636:2:35;13758:60:20;;;27618:21:35;27675:2;27655:18;;;27648:30;-1:-1:-1;;;27694:18:35;;;27687:50;27754:18;;13758:60:20;27608:170:35;13758:60:20;-1:-1:-1;13895:29:20;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:20;;26876:2:35;13094:59:20;;;26858:21:35;26915:2;26895:18;;;26888:30;-1:-1:-1;;;26934:18:35;;;26927:49;26993:18;;13094:59:20;26848:169:35;13094:59:20;-1:-1:-1;13229:29:20;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:20;;21529:2:35;13425:60:20;;;21511:21:35;21568:2;21548:18;;;21541:30;-1:-1:-1;;;21587:18:35;;;21580:50;21647:18;;13425:60:20;21501:170:35;13425:60:20;-1:-1:-1;13562:29:20;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:20;;22640:2:35;9704:50:20;;;22622:21:35;22679:2;22659:18;;;22652:30;-1:-1:-1;;;22698:18:35;;;22691:44;22752:18;;9704:50:20;22612:164:35;9704:50:20;9789:16;9798:7;9789:6;:16;:::i;:::-;9772:6;:13;:33;;9764:63;;;;-1:-1:-1;;;9764:63:20;;26530:2:35;9764:63:20;;;26512:21:35;26569:2;26549:18;;;26542:30;-1:-1:-1;;;26588:18:35;;;26581:47;26645:18;;9764:63:20;26502:167:35;9764:63:20;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:20;;;12087:2;12070:11;-1:-1:-1;;12066:25:20;12060:4;12053:39;-1:-1:-1;9894:2607:20;-1:-1:-1;12528:9:20;9558:2986;-1:-1:-1;;;;9558:2986:20:o;2379:166:14:-;2432:4;2456:1;2452;:5;2448:91;;;2480:5;2484:1;2480;:5;:::i;:::-;2473:12;;;;2448:91;2523:5;2527:1;2523;:5;:::i;1599:130:0:-;1513:6;;-1:-1:-1;;;;;1513:6:0;929:10:7;1662:23:0;1654:68;;;;-1:-1:-1;;;1654:68:0;;25412:2:35;1654:68:0;;;25394:21:35;;;25431:18;;;25424:30;25490:34;25470:18;;;25463:62;25542:18;;1654:68:0;25384:182:35;2673:187:0;2765:6;;;-1:-1:-1;;;;;2781:17:0;;;-1:-1:-1;;;;;;2781:17:0;;;;;;;2813:40;;2765:6;;;2781:17;2765:6;;2813:40;;2746:16;;2813:40;2673:187;;:::o;15318:342:20:-;15419:7;15463:11;:6;15472:2;15463:11;:::i;:::-;15446:6;:13;:28;;15438:62;;;;-1:-1:-1;;;15438:62:20;;24648:2:35;15438:62:20;;;24630:21:35;24687:2;24667:18;;;24660:30;-1:-1:-1;;;24706:18:35;;;24699:51;24767:18;;15438:62:20;24620:171:35;15438:62:20;-1:-1:-1;15584:30:20;15600:4;15584:30;15578:37;;15318:342::o;12550:422::-;12651:7;12695:11;:6;12704:2;12695:11;:::i;:::-;12678:6;:13;:28;;12670:62;;;;-1:-1:-1;;;12670:62:20;;25773:2:35;12670:62:20;;;25755:21:35;25812:2;25792:18;;;25785:30;-1:-1:-1;;;25831:18:35;;;25824:51;25892:18;;12670:62:20;25745:171:35;12670:62:20;-1:-1:-1;12837:30:20;12853:4;12837:30;12831:37;-1:-1:-1;;;12810:117:20;;;12550:422::o;1197:628:27:-;1281:28;;:::i;:::-;1322:22;1346:10;1362;318:6:26;:15;-1:-1:-1;;;;;318:15:26;;239:102;1362:10:27;-1:-1:-1;;;;;1362:27:27;;1403:9;1362:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1362:60:27;;;;;;;;;;;;:::i;:::-;1321:101;;;;;1438:5;1433:50;;1452:31;;-1:-1:-1;;;1452:31:27;;;;;;;;;;;1433:50;1499:65;1527:2;:17;;;1546:2;:17;;;1499:27;:65::i;:::-;1494:131;;1585:40;;-1:-1:-1;;;1585:40:27;;;;;;;;;;;1494:131;1839:37:26;;-1:-1:-1;;;;;1839:37:26;-1:-1:-1;;;;;1640:47:27;:2;:11;;;-1:-1:-1;;;;;1640:47:27;;1636:105;;1708:33;;-1:-1:-1;;;1708:33:27;;;;;;;;;;;1636:105;1752:46;1786:2;:11;;;1752:33;:46::i;:::-;-1:-1:-1;1816:2:27;1197:628;-1:-1:-1;;1197:628:27:o;3753:270::-;3982:34;4008:7;3982:25;:34::i;4290:2238::-;4431:72;4506:22;-1:-1:-1;;;;;;;;;;;;;;;;;2190:34:26;;;;;;;;2197:27;2190:34;;;;;;;;;;;;2060:171;4506:22:27;4431:97;;4886:22;4910:10;4926;318:6:26;:15;-1:-1:-1;;;;;318:15:26;;239:102;4926:10:27;4967:16;;4926:67;;-1:-1:-1;;;4926:67:27;;-1:-1:-1;;;;;4926:27:27;;;;;;;:67;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4926:67:27;;;;;;;;;;;;:::i;:::-;4885:108;;;;;5008:5;5003:50;;5022:31;;-1:-1:-1;;;5022:31:27;;;;;;;;;;;5003:50;5064:31;5098:60;5138:2;:10;;;5098:26;:60::i;:::-;5064:94;;5192:9;:7;:9::i;:::-;5172:29;;:2;:16;;;:29;;;;:54;;;;-1:-1:-1;5205:16:27;;;;:21;;;;5172:54;5168:115;;;5247:36;;-1:-1:-1;;;5247:36:27;;;;;;;;;;;5168:115;5311:52;5298:2;:9;;;:65;;;;;;-1:-1:-1;;;5298:65:27;;;;;;;;;;5294:127;;5384:37;;-1:-1:-1;;;5384:37:27;;;;;;;;;;;5294:127;5432:74;5509:89;5574:2;:10;;;5509:47;:89::i;:::-;5780:38;;5432:166;;-1:-1:-1;5737:81:27;;:27;2556:32:26;;;;;2473:122;5737:27:27;:81;;;5720:149;;5836:33;;-1:-1:-1;;;5836:33:27;;;;;;;;;;;5720:149;5909:38;;1464:32:30;:43;;-1:-1:-1;;1464:43:30;;;;;;;;;;;6027:114:27;;;;;;;;;6075:17;;;;6027:114;;;;;6110:17;;;;6027:114;;;;;;1194:27:30;:43;;-1:-1:-1;;1194:43:30;;;;;;;;;6308:46:27;6342:2;:11;;;6308:33;:46::i;:::-;6370:151;6407:22;6443;-1:-1:-1;;;;;;;;;;;;;;;;;2190:34:26;;;;;;;;2197:27;2190:34;;;;;;;;;;;;2060:171;6443:22:27;1839:37:26;;6370:151:27;;;14611:12:35;;14625:6;14607:25;;;14595:38;;14682:4;14671:16;;;14665:23;14649:14;;;14642:47;14611:12;;14607:25;28864:18;;;14595:38;;;;14671:16;;;;14665:23;14649:14;;;14642:47;-1:-1:-1;;;;;1839:37:26;28914:3:35;28899:19;;28892:60;28758:3;28743:19;6370:151:27;;;;;;;;4290:2238;;;;;;;:::o;6534:691::-;6615:66;6684:18;:16;:18::i;:::-;6615:87;;6718:6;6713:144;6734:14;:21;6730:1;:25;6713:144;;;6841:5;6779:6;:24;;:59;6804:33;6819:14;6834:1;6819:17;;;;;;-1:-1:-1;;;6819:17:27;;;;;;;;;;;;;;;6804:14;:33::i;:::-;6779:59;;;;;;;;;;;-1:-1:-1;6779:59:27;:67;;-1:-1:-1;;6779:67:27;;;;;;;;;;6757:6;-1:-1:-1;6757:6:27;;:::i;:::-;;;6713:144;;;-1:-1:-1;6867:30:27;6874:23;;6867:30;:::i;:::-;6912:6;6907:246;6928:19;;:26;6924:30;;6907:246;;;7004:19;;:22;;6975:23;;7004:19;7024:1;;7004:22;;;;-1:-1:-1;;;7004:22:27;;;;;;;;;;;;;;;;;;;;6975:52;;;;;;;;-1:-1:-1;6975:52:27;;;;;;;;;;;;;;;-1:-1:-1;;6975:52:27;;;;;;;;;;;;;;;;;;;;;;;7098:19;;:22;;6975:52;;7041:24;;-1:-1:-1;;7083:38:27;;7118:1;;7098:22;;;;-1:-1:-1;;;7098:22:27;;;;;;;;7083:38;7041:94;;;;;;;;;;;-1:-1:-1;7041:94:27;:101;;-1:-1:-1;;7041:101:27;;;;;;;;;;6956:3;;;;:::i;:::-;;;;6907:246;;;;7168:50;7183:14;7199:18;:16;:18::i;:::-;7168:50;;;;;;;:::i;:::-;;;;;;;;6534:691;;:::o;7231:211::-;7296:11;7310:22;2313:27:26;;;2237:110;7310:22:27;7366:14;;879:27:30;:33;7296:36:27;-1:-1:-1;7397:38:27;7404:6;7412:22;2313:27:26;;;2237:110;7412:22:27;7397:38;;;32878:25:35;;;32934:2;32919:18;;32912:34;;;;32851:18;7397:38:27;32833:119:35;7448:265:27;7529:19;7551:24;2431:29:26;;;2353:114;7551:24:27;7611:22;;1008:29:30;:54;7529:46:27;-1:-1:-1;7650:56:27;7665:14;7681:24;2431:29:26;;;2353:114;7719:1737:27;7854:26;7891:10;318:6:26;:15;-1:-1:-1;;;;;318:15:26;;239:102;7891:10:27;7854:48;;7912:39;7924:7;:26;;;7912:11;:39::i;:::-;8136:22;8160:10;8176;318:6:26;:15;-1:-1:-1;;;;;318:15:26;;239:102;8176:10:27;-1:-1:-1;;;;;8176:27:27;;8217:9;8176:60;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8176:60:27;;;;;;;;;;;;:::i;:::-;8135:101;;;;;8252:5;8247:56;;8266:37;;-1:-1:-1;;;8266:37:27;;;;;;;;;;;8247:56;8319:65;8347:2;:17;;;8366:2;:17;;;8319:27;:65::i;:::-;8314:128;;8405:37;;-1:-1:-1;;;8405:37:27;;;;;;;;;;;8314:128;1839:37:26;;-1:-1:-1;;;;;1839:37:26;-1:-1:-1;;;;;8457:47:27;:2;:11;;;-1:-1:-1;;;;;8457:47:27;;8453:112;;8525:40;;-1:-1:-1;;;8525:40:27;;;;;;;;;;;8453:112;8576:31;8610:60;8650:2;:10;;;8610:26;:60::i;:::-;8576:94;-1:-1:-1;8698:35:27;8685:2;:9;;;:48;;;;;;-1:-1:-1;;;8685:48:27;;;;;;;;;;8681:113;;8754:40;;-1:-1:-1;;;8754:40:27;;;;;;;;;;;8681:113;9139:55;9197:42;9228:2;:10;;;9197:30;:42::i;:::-;9287:26;;9254:29;;9139:100;;-1:-1:-1;;;;;;9254:59:27;;;;;;9250:124;;9334:40;;-1:-1:-1;;;9334:40:27;;;;;;;;;;;9250:124;9390:59;9409:18;9437:10;318:6:26;:15;-1:-1:-1;;;;;318:15:26;;239:102;9437:10:27;9390:59;;;-1:-1:-1;;;;;17134:15:35;;;17116:34;;17186:15;;;;17181:2;17166:18;;17159:43;17051:18;9390:59:27;17033:175:35;347:177:26;426:41;;:::i;:::-;-1:-1:-1;486:31:26;;;;:22;:31;;;;;;;;;479:38;;;;;;;;;-1:-1:-1;;;;;479:38:26;;;;;-1:-1:-1;;;479:38:26;;;;;;;;;;;;;;;;;;-1:-1:-1;;;479:38:26;;;;;;;;;;;;;;;;;-1:-1:-1;;;479:38:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;347:177::o;1535:2361:24:-;1926:1;1654:11;1954:40:22;;1949:3;1945:50;595:10:24;1950:26;;1946:89;;2005:30;;-1:-1:-1;;;2005:30:24;;;;;;;;;;;1946:89;2219:1;2209:11;;;;1409:26:22;;1396:40;1391:3;1387:50;;2243:29:24;;2239:92;;2301:30;;-1:-1:-1;;;2301:30:24;;;;;;;;;;;2239:92;-1:-1:-1;;1409:26:22;;;2515:1:24;1409:26:22;1396:40;1391:3;1387:50;;;3577:28:24;;;;;;;;1409:26:22;;;;1396:40;1387:50;;3647:99:24;;;;;;-1:-1:-1;;;3647:99:24;;;;;;;;;3771:1;3761:11;;;;;3634:112;-1:-1:-1;3791:33:24;;;3787:92;;;3849:30;;-1:-1:-1;;;3849:30:24;;;;;;;;;;;3787:92;1535:2361;;;;;:::o;6904:460::-;7044:16;1688:26:22;;;1675:40;1670:3;1666:50;7198:11:24;7208:1;1688:26:22;7198:11:24;:::i;:::-;;-1:-1:-1;7219:21:24;;;;7198:11;7219:21;:::i;:::-;;-1:-1:-1;1409:26:22;;;1396:40;1391:3;1387:50;7263:94:24;7250:107;6904:460;-1:-1:-1;;;;;6904:460:24:o;24394:161:23:-;24473:16;24526:22;2313:27:26;;;2237:110;24526:22:23;24508:40;;:15;:40;:::i;10988:1330:24:-;11101:16;11143:18;11175:21;11209:57;11248:17;;11209:38;:57::i;:::-;11129:137;;-1:-1:-1;11129:137:24;-1:-1:-1;11295:25:24;11281:10;:39;;;;-1:-1:-1;;;11281:39:24;;;;;;;;;;11277:107;;11343:30;;-1:-1:-1;;;11343:30:24;;;;;;;;;;;11277:107;11394:11;11415:14;11439:22;;11569:145;11660:17;;11691:13;11569:77;:145::i;:::-;11471:243;;-1:-1:-1;11471:243:24;;-1:-1:-1;11471:243:24;;-1:-1:-1;11471:243:24;;-1:-1:-1;11471:243:24;-1:-1:-1;11754:6:24;11749:476;11770:10;11766:14;;:1;:14;11749:476;;;11805:46;;:::i;:::-;11869:15;11902:22;12088:56;12120:6;12128:7;;12137:6;12088:31;:56::i;:::-;11942:202;;-1:-1:-1;11942:202:24;;-1:-1:-1;11942:202:24;-1:-1:-1;11942:202:24;-1:-1:-1;12162:48:24;11942:202;;12162:28;:48::i;:::-;-1:-1:-1;;;11782:3:24;;11749:476;;;-1:-1:-1;12248:24:24;;;12244:67;;12281:30;;-1:-1:-1;;;12281:30:24;;;;;;;;;;;12244:67;10988:1330;;;;;;;;;;:::o;2114:186:23:-;2190:103;2240:43;2273:9;;2240:32;:43::i;:::-;2190:36;:103::i;1104:111:0:-;5363:13:4;;;;;;;5355:69;;;;-1:-1:-1;;;5355:69:4;;;;;;;:::i;:::-;1176:32:0::1;929:10:7::0;1176:18:0::1;:32::i;225:88:30:-:0;277:6;:29;;-1:-1:-1;;;;;;277:29:30;-1:-1:-1;;;;;277:29:30;;;;;;;;;;225:88::o;1250:134::-;1329:37;:48;;-1:-1:-1;;1329:48:30;-1:-1:-1;;;;;1329:48:30;;;;;;;;;;1250:134::o;1805:281:2:-;-1:-1:-1;;;;;1476:19:6;;;1878:106:2;;;;-1:-1:-1;;;1878:106:2;;24998:2:35;1878:106:2;;;24980:21:35;25037:2;25017:18;;;25010:30;25076:34;25056:18;;;25049:62;-1:-1:-1;;;25127:18:35;;;25120:43;25180:19;;1878:106:2;24970:235:35;1878:106:2;-1:-1:-1;;;;;;;;;;;1994:85:2;;-1:-1:-1;;;;;;1994:85:2;-1:-1:-1;;;;;1994:85:2;;;;;;;;;;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;3902:2996:24:-;4125:11;;;4208:22;4125:11;4289:166;4335:17;;4370:13;4401:40;;;4289:28;:166::i;:::-;4633:1;;-1:-1:-1;4279:176:24;;-1:-1:-1;4279:176:24;-1:-1:-1;1675:40:22;;1670:3;1666:50;4667:27:24;4478:1;4759:236;4805:168;4279:176;;4633:1;1666:50:22;4805:28:24;:168::i;:::-;4759:20;:236::i;:::-;5259:10;;;13637:3:21;13621:29;;;13615:36;5017:21:24;;;;;;;;5259:10;;-1:-1:-1;13637:3:21;-1:-1:-1;709:10:24;5574:35;;;;5570:102;;5642:30;;-1:-1:-1;;;5642:30:24;;;;;;;;;;;5570:102;13095:29:21;;;13111:3;13095:29;13089:36;5695:21:24;;5719:111;;;;;;-1:-1:-1;;;5719:111:24;;;;;;;;;5852:15;;;;;5695:135;-1:-1:-1;5908:25:24;5894:10;:39;;;;-1:-1:-1;;;5894:39:24;;;;;;;;;;5890:106;;5966:30;;-1:-1:-1;;;5966:30:24;;;;;;;;;;;5890:106;12772:30:21;;;;;12766:37;6665:21:24;;-1:-1:-1;;;12745:117:21;;;6392:110:24;;;-1:-1:-1;6524:19:24;;;;;6649:37;;6645:104;;;6719:30;;-1:-1:-1;;;6719:30:24;;;;;;;;;;;6645:104;-1:-1:-1;;6880:1:24;6870:11;;;3902:2996;;-1:-1:-1;;;;1409:26:22;;;1396:40;1391:3;1387:50;;-1:-1:-1;1409:26:22;-1:-1:-1;;3902:2996:24:o;7370:1561::-;7554:14;7582:46;;:::i;:::-;7924:1;7914:11;;;7642:15;;;;7742:29;;7642:15;;1688:26:22;;1675:40;1670:3;1666:50;7957:120:24;1688:26:22;8003:7:24;7914:11;1666:50:22;7957:28:24;:120::i;:::-;7940:137;;;;8101:11;8091:21;;;;;;8127:10;8172:142;8213:7;;8238:6;8262;8286:14;;8172:23;:142::i;:::-;8151:163;-1:-1:-1;8151:163:24;-1:-1:-1;8151:163:24;8328:82;;8365:30;;-1:-1:-1;;;8365:30:24;;;;;;;;;;;8328:82;8424:23;1396:40:22;;1391:3;1387:50;8450:92:24;;;;-1:-1:-1;;;8450:92:24;;;;;;;;;8424:118;-1:-1:-1;8575:21:24;8560:11;:36;;;;-1:-1:-1;;;8560:36:24;;;;;;;;;;8556:289;;;8656:98;8699:14;;8735:1;8656:21;:98::i;:::-;8616:138;;-1:-1:-1;8616:138:24;-1:-1:-1;8616:138:24;-1:-1:-1;8556:289:24;;;8800:30;;-1:-1:-1;;;8800:30:24;;;;;;;;;;;8556:289;8859:55;;;;;7370:1561;;;;;;;;;:::o;319:492:30:-;458:24;485:31;;;:22;:31;;;;;:43;542:16;;-1:-1:-1;;;;;485:43:30;;;;542:36;;-1:-1:-1;538:267:30;;;594:31;;;;:22;:31;;;;;;;;;:38;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;594:38:30;;;-1:-1:-1;;;;;;594:38:30;;;;;-1:-1:-1;;;594:38:30;;;;;;;;;;;;;-1:-1:-1;;;;594:38:30;-1:-1:-1;;;594:38:30;;;;;;;;;;;-1:-1:-1;;;;594:38:30;;;;;-1:-1:-1;;;594:38:30;;;;;;;;;;;;;-1:-1:-1;594:38:30;;;;;;;;;;;;;;;-1:-1:-1;;594:38:30;;;;;;;;;;;;;;;;;;;;651:143;;33590:34:35;;;33640:18;;;33633:49;;;;33698:18;;;33691:43;;;;594:31:30;;651:143;;33526:18:35;651:143:30;;;;;;;319:492;;;:::o;24561:319:23:-;24685:10;;24727:129;24734:19;;;24727:129;;;24793:13;24778:8;;24787:1;24778:11;;;;;-1:-1:-1;;;24778:11:23;;;;;;;;;;;;;;;:28;24774:72;;;24826:5;;24774:72;24755:3;;;;:::i;:::-;;;;24727:129;;24886:675;25139:7;25120:10;25131:1;25120:13;;;;;;-1:-1:-1;;;25120:13:23;;;;;;;;;;;;;;;:16;;:26;;;;;25184:4;:10;;;25156;25167:1;25156:13;;;;;;-1:-1:-1;;;25156:13:23;;;;;;;;;;;;;;;:19;;;:25;;:38;;;;;;;;;;;25231:4;:9;;;25204:10;25215:1;25204:13;;;;;;-1:-1:-1;;;25204:13:23;;;;;;;;;;;;;;;:19;;;:24;;:36;-1:-1:-1;;;;;25204:36:23;;;-1:-1:-1;;;;;25204:36:23;;;;;25277:4;:9;;;25250:10;25261:1;25250:13;;;;;;-1:-1:-1;;;25250:13:23;;;;;;;;;;;;;;;:19;;;:24;;:36;;;;;;;;;;;25330:11;25296:10;25307:1;25296:13;;;;;;-1:-1:-1;;;25296:13:23;;;;;;;;;;;;;;;:19;;;:31;;:45;;;;;25382:4;:13;;;25351:10;25362:1;25351:13;;;;;;-1:-1:-1;;;25351:13:23;;;;;;;;;;;;;;;:22;;;:28;;:44;;;;;;;;;;;25435:4;:12;;;25405:10;25416:1;25405:13;;;;;;-1:-1:-1;;;25405:13:23;;;;;;;;;;;;;;;:22;;;:27;;:42;-1:-1:-1;;;;;25405:42:23;;;-1:-1:-1;;;;;25405:42:23;;;;;25487:4;:9;;;25457:10;25468:1;25457:13;;;;;;-1:-1:-1;;;25457:13:23;;;;;;;;;;;;;;;:22;;;:27;;:39;;;;;;;;;;;25543:11;25506:10;25517:1;25506:13;;;;;;-1:-1:-1;;;25506:13:23;;;;;;;;;;;;;;;:22;;;:34;;:48;;;;;24886:675;;;;;:::o;14979:389::-;15084:22;;:::i;:::-;15132:10;15172;318:6:26;:15;-1:-1:-1;;;;;318:15:26;;239:102;15172:10:23;-1:-1:-1;;;;;15172:27:23;;15200:9;;15172:38;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;15172:38:23;;;;;;;;;;;;:::i;:::-;-1:-1:-1;15156:54:23;;-1:-1:-1;15156:54:23;-1:-1:-1;15156:54:23;15224:50;;15243:31;;-1:-1:-1;;;15243:31:23;;;;;;;;;;;15224:50;14979:389;15300:16;15313:2;15300:12;:16::i;:::-;15295:66;;15325:36;;-1:-1:-1;;;15325:36:23;;;;;;;;;;;12197:2776;12317:10;;;;12494:39;12518:7;12317:10;13637:3:21;13621:29;;;13615:36;;13436:257;12494:39:23;12479:54;;12560:1;12551:10;;;;12583:5;:19;;12592:10;12583:19;12579:62;;12611:30;;-1:-1:-1;;;12611:30:23;;;;;;;;;;;12579:62;13374:3:21;13358:29;;;;;13352:36;12739:10:23;;;12787:1;12771:17;;;;12767:60;;12797:30;;-1:-1:-1;;;12797:30:23;;;;;;;;;;;12767:60;13048:1;13039:10;;;;13314:14;13331:39;13355:7;13364:5;13374:3:21;13358:29;;;13352:36;;13173:257;13331:39:23;13314:56;;13397:1;13388:10;;;;14089:15;14107:38;14130:7;14139:5;13111:3:21;13095:29;;;13089:36;;12913:254;14107:38:23;14089:56;;14228:7;14219:16;;;;;;14321:9;:14;;14334:1;14321:14;14317:57;;14344:30;;-1:-1:-1;;;14344:30:23;;;;;;;;;;;14317:57;-1:-1:-1;;;;13358:29:21;;;13374:3;13358:29;13352:36;14451:55:23;;;;14529:1;14520:10;;;;14605:39;14629:7;14638:5;13374:3:21;13358:29;;;13352:36;;13173:257;14605:39:23;14587:57;;;;14667:1;14658:10;;;;14886:13;14868:15;:31;14859:5;:41;14840:7;:14;:61;14836:120;;14926:30;;-1:-1:-1;;;14926:30:23;;;;;;;;;;;14836:120;12197:2776;;;;;:::o;6005:3956::-;6179:41;;:::i;:::-;14953:30:21;;;;;;;14947:37;13884:29;;;13878:36;6750:108:23;;;;;;:10;;;:108;;;;13884:29:21;;;13878:36;-1:-1:-1;;;;;6908:116:23;;;:9;;;:116;13621:29:21;;;13615:36;7074:107:23;;;;;;:9;;;:107;13884:29:21;;;13878:36;7231:111:23;;;;;:13;;;:111;13884:29:21;;;13878:36;7392:119:23;;:12;;;:119;13095:29:21;;;13089:36;13884:29;;;;13878:36;8515:135:23;;;;;14947:37:21;8712:11:23;;;8722:1;8712:11;8708:1115;;;8808:2;8788:22;;;;8708:1115;;;9156:24;;;13884:29:21;;13900:3;13884:29;;13878:36;-1:-1:-1;;;;;9055:147:23;;;;;13884:29:21;;;13878:36;9306:206:23;;;;;;:10;;;:206;13884:29:21;;;;13878:36;9621:140:23;:9;;;:140;9783:21;;;;8708:1115;6005:3956;9874:15;9855:16;:34;9851:93;;;9914:30;;-1:-1:-1;;;9914:30:23;;;;;;;;;;;9851:93;6005:3956;;;;;;;:::o;2005:644:32:-;2121:25;2149:20;:18;:20::i;:::-;2201:25;;2121:48;;-1:-1:-1;2179:69:32;;2201:25;2228:12;;2179:69;2471:4;-1:-1:-1;;;;;2471:24:32;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:40;;2501:10;2471:40;2467:102;;2532:37;;-1:-1:-1;;;2532:37:32;;;;;;;;;;;2467:102;2585:57;2602:17;2621:20;:18;:20::i;:::-;2585:57;;;-1:-1:-1;;;;;17134:15:35;;;17116:34;;17186:15;;;;17181:2;17166:18;;17159:43;17051:18;2585:57:32;17033:175:35;4707:1292:23;5101:10;;;;5078:20;;;5244:36;5101:10;5244:27;:36::i;:::-;5125:155;;;;;;5344:6;5339:572;5360:13;5356:1;:17;5339:572;;;5420:41;5483:15;5519:158;5576:7;5609:5;5640:15;5519:31;:158::i;:::-;5398:279;;;;5778:15;5769:24;;;;5853:43;5882:7;5891:4;5853:28;:43::i;:::-;-1:-1:-1;;5375:3:23;;5339:572;;;-1:-1:-1;5951:17:23;;;;5970:11;;;;5930:52;;;32435:6:35;32423:19;;;32405:38;;-1:-1:-1;;;;;32479:31:35;;;32474:2;32459:18;;32452:59;5930:52:23;;32378:18:35;5930:52:23;;;;;;;4707:1292;;;;;:::o;2192:152:2:-;2258:37;2277:17;2258:18;:37::i;:::-;2310:27;;-1:-1:-1;;;;;2310:27:2;;;;;;;;2192:152;:::o;7088:455::-;7171:12;-1:-1:-1;;;;;1476:19:6;;;7195:88:2;;;;-1:-1:-1;;;7195:88:2;;26123:2:35;7195:88:2;;;26105:21:35;26162:2;26142:18;;;26135:30;26201:34;26181:18;;;26174:62;-1:-1:-1;;;26252:18:35;;;26245:36;26298:19;;7195:88:2;26095:228:35;7195:88:2;7354:12;7368:23;7395:6;-1:-1:-1;;;;;7395:19:2;7415:4;7395:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7353:67;;;;7437:99;7473:7;7482:10;7437:99;;;;;;;;;;;;;;;;;:35;:99::i;541:195:22:-;665:14;;698:6;705;698;712:16;721:7;705:6;712:16;:::i;:::-;698:31;;;;;;;:::i;:::-;691:38;;;;541:195;;;;;;;:::o;1101:428:24:-;1194:22;;:::i;:::-;1242:10;1282;318:6:26;:15;-1:-1:-1;;;;;318:15:26;;239:102;1282:10:24;-1:-1:-1;;;;;1282:27:24;;1310:9;;1282:38;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1282:38:24;;;;;;;;;;;;:::i;:::-;-1:-1:-1;1266:54:24;;-1:-1:-1;1266:54:24;-1:-1:-1;1266:54:24;1334:50;;1353:31;;-1:-1:-1;;;1353:31:24;;;;;;;;;;;1334:50;1101:428;1410:55;1428:2;:17;;;1447:2;:17;;;1410;:55::i;1676:939:19:-;1845:10;1857:14;1907:21;1931:29;1951:8;;1931:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1931:19:19;;-1:-1:-1;;;1931:29:19:i;:::-;2125:1;2110:16;;;1907:53;;-1:-1:-1;1409:26:22;;1396:40;1391:3;1387:50;1975:15:19;2141:377;2162:9;2158:13;;:1;:13;2141:377;;;2359:2;2344:17;;;1130:26:22;;1117:40;-1:-1:-1;;;;;;2220:106:19;2396:107;2437:13;2220:106;2396:19;:107::i;:::-;2380:123;-1:-1:-1;;2173:3:19;;2141:377;;;-1:-1:-1;;;;;;;;2540:21:19;;;;;;;;;;2587:11;;-1:-1:-1;1676:939:19;;-1:-1:-1;;;;;1676:939:19:o;8937:2045:24:-;9095:46;;:::i;:::-;9393:2;3358:26:22;;;2246;;;2233:40;2228:3;2224:50;;;9410:112:24;;;;;;:15;;;;:112;;;;9536:11;2246:26:22;;2233:40;2224:50;;9562:14:24;;;:120;9696:11;1967:26:22;;1954:40;1949:3;1945:50;9722:111:24;;;;;;:14;;;:111;9847:11;2246:26:22;;2233:40;2224:50;;;10189:127:24;;10467:49;;;;;;;;;;;;;;;;;;;;10330:11;;;;;3345:40:22;;;9155:15:24;;10467:49;;3358:26:22;;10467:49:24;;;;;;3358:26:22;10467:49:24;;3358:26:22;10467:49:24;;;;;;;;;-1:-1:-1;10509:6:24;;-1:-1:-1;10467:23:24;;-1:-1:-1;;10467:49:24:i;:::-;2246:26:22;;;10540:1:24;2246:26:22;;2233:40;2228:3;2224:50;;;10556:115:24;;;;;;:18;;;:115;10685:11;2246:26:22;;;2233:40;2224:50;;10711:17:24;;;:123;10848:11;;;;;10449:67;-1:-1:-1;10878:32:24;;;10874:91;;;10935:30;;-1:-1:-1;;;10935:30:24;;;;;;;;;;;10874:91;8937:2045;;;;;;;:::o;4528:173:23:-;4610:10;4639:55;4657:2;:17;;;4676:2;:17;;;4639;:55::i;13699:257:21:-;13884:29;13900:3;13884:29;13878:36;;13699:257::o;7438:295:6:-;7584:12;7612:7;7608:119;;;-1:-1:-1;7642:10:6;7635:17;;7608:119;7683:33;7691:10;7703:12;7683:7;:33::i;635:141:19:-;695:7;721:48;279:1;763:4;726:42;;;;;;;;;:::i;:::-;;;;;;;;;;;;;470:16;;;;;;;;379:115;782:276;877:7;-1:-1:-1;;;;;;900:15:19;;;;;;;896:81;;;951:6;;959;896:81;998:52;;-1:-1:-1;;;998:52:19;;;16090:49:35;-1:-1:-1;;;;;;16218:15:35;;;16205:11;;;16198:36;16264:15;;16250:12;;;16243:37;993:58:19;;16296:12:35;;998:52:19;16080:234:35;7739:540:6;7898:17;;:21;7894:379;;8126:10;8120:17;8182:15;8169:10;8165:2;8161:19;8154:44;8079:133;8249:12;8242:20;;-1:-1:-1;;;8242:20:6;;;;;;;;:::i;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:173:35:-;82:20;;-1:-1:-1;;;;;131:31:35;;121:42;;111:2;;177:1;174;167:12;111:2;63:124;;;:::o;192:395::-;255:8;265:6;319:3;312:4;304:6;300:17;296:27;286:2;;344:8;334;327:26;286:2;-1:-1:-1;374:20:35;;-1:-1:-1;;;;;406:30:35;;403:2;;;456:8;446;439:26;403:2;500:4;492:6;488:17;476:29;;560:3;553:4;543:6;540:1;536:14;528:6;524:27;520:38;517:47;514:2;;;577:1;574;567:12;592:1169;666:5;719:3;712:4;704:6;700:17;696:27;686:2;;741:5;734;727:20;686:2;774:6;768:13;800:4;-1:-1:-1;;;;;819:2:35;816:26;813:2;;;845:18;;:::i;:::-;885:36;917:2;912;909:1;905:10;901:19;885:36;:::i;:::-;943:3;967:2;962:3;955:15;995:2;990:3;986:12;979:19;;1030:2;1022:6;1018:15;1082:3;1077:2;1071;1068:1;1064:10;1056:6;1052:23;1048:32;1045:41;1042:2;;;1103:5;1096;1089:20;1042:2;1129:5;1143:589;1157:2;1154:1;1151:9;1143:589;;;1212:4;1251:2;1245:3;1240;1236:13;1232:22;1229:2;;;1271:5;1264;1257:20;1229:2;1305:22;;:::i;:::-;1360:3;1354:10;1347:5;1340:25;1416:2;1411:3;1407:12;1401:19;1396:2;1389:5;1385:14;1378:43;1444:2;1482:41;1519:2;1514:3;1510:12;1482:41;:::i;:::-;1466:14;;;1459:65;1547:2;1585:41;1613:12;;;1585:41;:::i;:::-;1569:14;;;1562:65;1640:18;;1678:12;;;;1710;;;;;1175:1;1168:9;1143:589;;;-1:-1:-1;1750:5:35;;676:1085;-1:-1:-1;;;;;;;676:1085:35:o;1766:164::-;1842:13;;1891;;1884:21;1874:32;;1864:2;;1920:1;1917;1910:12;1935:482;1977:5;2030:3;2023:4;2015:6;2011:17;2007:27;1997:2;;2052:5;2045;2038:20;1997:2;2092:6;2079:20;2123:48;2139:31;2167:2;2139:31;:::i;:::-;2123:48;:::i;:::-;2196:2;2187:7;2180:19;2242:3;2235:4;2230:2;2222:6;2218:15;2214:26;2211:35;2208:2;;;2263:5;2256;2249:20;2208:2;2332;2325:4;2317:6;2313:17;2306:4;2297:7;2293:18;2280:55;2355:16;;;2373:4;2351:27;2344:42;;;;2359:7;1987:430;-1:-1:-1;;1987:430:35:o;2422:444::-;2475:5;2528:3;2521:4;2513:6;2509:17;2505:27;2495:2;;2550:5;2543;2536:20;2495:2;2583:6;2577:13;2614:48;2630:31;2658:2;2630:31;:::i;2614:48::-;2687:2;2678:7;2671:19;2733:3;2726:4;2721:2;2713:6;2709:15;2705:26;2702:35;2699:2;;;2754:5;2747;2740:20;2699:2;2771:64;2832:2;2825:4;2816:7;2812:18;2805:4;2797:6;2793:17;2771:64;:::i;2871:136::-;2949:13;;2971:30;2949:13;2971:30;:::i;3012:167::-;3090:13;;3143:10;3132:22;;3122:33;;3112:2;;3169:1;3166;3159:12;3184:136;3262:13;;3284:30;3262:13;3284:30;:::i;3325:160::-;3402:13;;3455:4;3444:16;;3434:27;;3424:2;;3475:1;3472;3465:12;3490:196;3549:6;3602:2;3590:9;3581:7;3577:23;3573:32;3570:2;;;3623:6;3615;3608:22;3570:2;3651:29;3670:9;3651:29;:::i;3691:1357::-;3864:6;3872;3880;3888;3896;3904;3912;3920;3928;3936;3989:3;3977:9;3968:7;3964:23;3960:33;3957:2;;;4011:6;4003;3996:22;3957:2;4039:29;4058:9;4039:29;:::i;:::-;4029:39;;4119:2;4108:9;4104:18;4091:32;-1:-1:-1;;;;;4183:2:35;4175:6;4172:14;4169:2;;;4204:6;4196;4189:22;4169:2;4248:70;4310:7;4301:6;4290:9;4286:22;4248:70;:::i;:::-;4337:8;;-1:-1:-1;4222:96:35;-1:-1:-1;4425:2:35;4410:18;;4397:32;;-1:-1:-1;4441:16:35;;;4438:2;;;4475:6;4467;4460:22;4438:2;;4519:72;4583:7;4572:8;4561:9;4557:24;4519:72;:::i;:::-;4610:8;;-1:-1:-1;4493:98:35;-1:-1:-1;;4695:2:35;4680:18;;4667:32;4708:30;4667:32;4708:30;:::i;:::-;4757:5;-1:-1:-1;4809:3:35;4794:19;;4781:33;;-1:-1:-1;4866:3:35;4851:19;;4838:33;4880:32;4838:33;4880:32;:::i;:::-;4931:7;4921:17;;;4985:3;4974:9;4970:19;4957:33;4947:43;;5037:3;5026:9;5022:19;5009:33;4999:43;;3947:1101;;;;;;;;;;;;;:::o;5053:414::-;5130:6;5138;5191:2;5179:9;5170:7;5166:23;5162:32;5159:2;;;5212:6;5204;5197:22;5159:2;5240:29;5259:9;5240:29;:::i;:::-;5230:39;;5320:2;5309:9;5305:18;5292:32;-1:-1:-1;;;;;5339:6:35;5336:30;5333:2;;;5384:6;5376;5369:22;5333:2;5412:49;5453:7;5444:6;5433:9;5429:22;5412:49;:::i;:::-;5402:59;;;5149:318;;;;;:::o;5472:468::-;5569:6;5577;5630:2;5618:9;5609:7;5605:23;5601:32;5598:2;;;5651:6;5643;5636:22;5598:2;5696:9;5683:23;-1:-1:-1;;;;;5721:6:35;5718:30;5715:2;;;5766:6;5758;5751:22;5715:2;5810:70;5872:7;5863:6;5852:9;5848:22;5810:70;:::i;:::-;5899:8;;5784:96;;-1:-1:-1;5588:352:35;-1:-1:-1;;;;5588:352:35:o;5945:1138::-;6113:6;6121;6129;6137;6145;6153;6206:2;6194:9;6185:7;6181:23;6177:32;6174:2;;;6227:6;6219;6212:22;6174:2;6272:9;6259:23;-1:-1:-1;;;;;6342:2:35;6334:6;6331:14;6328:2;;;6363:6;6355;6348:22;6328:2;6407:70;6469:7;6460:6;6449:9;6445:22;6407:70;:::i;:::-;6496:8;;-1:-1:-1;6381:96:35;-1:-1:-1;6584:2:35;6569:18;;6556:32;;-1:-1:-1;6600:16:35;;;6597:2;;;6634:6;6626;6619:22;6597:2;6678:72;6742:7;6731:8;6720:9;6716:24;6678:72;:::i;:::-;6769:8;;-1:-1:-1;6652:98:35;-1:-1:-1;6857:2:35;6842:18;;6829:32;;-1:-1:-1;6873:16:35;;;6870:2;;;6907:6;6899;6892:22;6870:2;;6951:72;7015:7;7004:8;6993:9;6989:24;6951:72;:::i;:::-;6164:919;;;;-1:-1:-1;6164:919:35;;-1:-1:-1;6164:919:35;;7042:8;;6164:919;-1:-1:-1;;;6164:919:35:o;7088:1087::-;7237:6;7245;7253;7261;7269;7277;7330:3;7318:9;7309:7;7305:23;7301:33;7298:2;;;7352:6;7344;7337:22;7298:2;7397:9;7384:23;-1:-1:-1;;;;;7467:2:35;7459:6;7456:14;7453:2;;;7488:6;7480;7473:22;7453:2;7532:70;7594:7;7585:6;7574:9;7570:22;7532:70;:::i;:::-;7621:8;;-1:-1:-1;7506:96:35;-1:-1:-1;7709:2:35;7694:18;;7681:32;;-1:-1:-1;7725:16:35;;;7722:2;;;7759:6;7751;7744:22;7722:2;;7803:72;7867:7;7856:8;7845:9;7841:24;7803:72;:::i;:::-;7894:8;;-1:-1:-1;7777:98:35;-1:-1:-1;;7979:2:35;7964:18;;7951:32;7992:30;7951:32;7992:30;:::i;:::-;8041:5;-1:-1:-1;8098:2:35;8083:18;;8070:32;8111;8070;8111;:::i;:::-;8162:7;8152:17;;;7288:887;;;;;;;;:::o;8180:190::-;8239:6;8292:2;8280:9;8271:7;8267:23;8263:32;8260:2;;;8313:6;8305;8298:22;8260:2;-1:-1:-1;8341:23:35;;8250:120;-1:-1:-1;8250:120:35:o;8375:194::-;8445:6;8498:2;8486:9;8477:7;8473:23;8469:32;8466:2;;;8519:6;8511;8504:22;8466:2;-1:-1:-1;8547:16:35;;8456:113;-1:-1:-1;8456:113:35:o;8574:258::-;8642:6;8650;8703:2;8691:9;8682:7;8678:23;8674:32;8671:2;;;8724:6;8716;8709:22;8671:2;-1:-1:-1;;8752:23:35;;;8822:2;8807:18;;;8794:32;;-1:-1:-1;8661:171:35:o;8837:641::-;8907:6;8915;8968:2;8956:9;8947:7;8943:23;8939:32;8936:2;;;8989:6;8981;8974:22;8936:2;9034:9;9021:23;-1:-1:-1;;;;;9104:2:35;9096:6;9093:14;9090:2;;;9125:6;9117;9110:22;9090:2;9168:6;9157:9;9153:22;9143:32;;9213:7;9206:4;9202:2;9198:13;9194:27;9184:2;;9240:6;9232;9225:22;9184:2;9285;9272:16;9311:2;9303:6;9300:14;9297:2;;;9332:6;9324;9317:22;9297:2;9382:7;9377:2;9368:6;9364:2;9360:15;9356:24;9353:37;9350:2;;;9408:6;9400;9393:22;9350:2;9444;9436:11;;;;;9466:6;;-1:-1:-1;8926:552:35;;-1:-1:-1;;;;8926:552:35:o;9483:340::-;9551:6;9604:2;9592:9;9583:7;9579:23;9575:32;9572:2;;;9625:6;9617;9610:22;9572:2;9670:9;9657:23;-1:-1:-1;;;;;9695:6:35;9692:30;9689:2;;;9740:6;9732;9725:22;9689:2;9768:49;9809:7;9800:6;9789:9;9785:22;9768:49;:::i;9828:583::-;9915:6;9968:2;9956:9;9947:7;9943:23;9939:32;9936:2;;;9989:6;9981;9974:22;9936:2;10027;10021:9;10069:2;10061:6;10057:15;10138:6;10126:10;10123:22;-1:-1:-1;;;;;10090:10:35;10087:34;10084:62;10081:2;;;10149:18;;:::i;:::-;10185:2;10178:22;10222:23;;10254:30;10222:23;10254:30;:::i;:::-;10293:21;;10375:2;10360:18;;;10347:32;10330:15;;;10323:57;;;;-1:-1:-1;10300:6:35;9926:485;-1:-1:-1;9926:485:35:o;10416:1844::-;10531:6;10539;10547;10600:2;10588:9;10579:7;10575:23;10571:32;10568:2;;;10621:6;10613;10606:22;10568:2;10659:9;10653:16;-1:-1:-1;;;;;10729:2:35;10721:6;10718:14;10715:2;;;10750:6;10742;10735:22;10715:2;10778:22;;;;10834:6;10816:16;;;10812:29;10809:2;;;10859:6;10851;10844:22;10809:2;10890:22;;:::i;:::-;10935:31;10963:2;10935:31;:::i;:::-;10928:5;10921:46;10999:41;11036:2;11032;11028:11;10999:41;:::i;:::-;10994:2;10987:5;10983:14;10976:65;11073:41;11110:2;11106;11102:11;11073:41;:::i;:::-;11068:2;11061:5;11057:14;11050:65;11147:41;11184:2;11180;11176:11;11147:41;:::i;:::-;11142:2;11135:5;11131:14;11124:65;11236:3;11232:2;11228:12;11222:19;11216:3;11209:5;11205:15;11198:44;11275:42;11312:3;11308:2;11304:12;11275:42;:::i;:::-;11269:3;11262:5;11258:15;11251:67;11351:41;11387:3;11383:2;11379:12;11351:41;:::i;:::-;11345:3;11338:5;11334:15;11327:66;11432:3;11428:2;11424:12;11418:19;11462:2;11452:8;11449:16;11446:2;;;11483:6;11475;11468:22;11446:2;11525:55;11572:7;11561:8;11557:2;11553:17;11525:55;:::i;:::-;11519:3;11512:5;11508:15;11501:80;;11600:3;11635:41;11672:2;11668;11664:11;11635:41;:::i;:::-;11619:14;;;11612:65;11696:3;11730:11;;;11724:18;11754:16;;;11751:2;;;11788:6;11780;11773:22;11751:2;11829:76;11897:7;11886:8;11882:2;11878:17;11829:76;:::i;:::-;11813:14;;;11806:100;;;;-1:-1:-1;11925:3:35;11966:11;;;11960:18;11944:14;;;11937:42;11817:5;-1:-1:-1;12022:46:35;12064:2;12049:18;;12022:46;:::i;:::-;12012:56;;12114:2;12103:9;12099:18;12093:25;12077:41;;12143:2;12133:8;12130:16;12127:2;;;12164:6;12156;12149:22;12127:2;;12192:62;12246:7;12235:8;12224:9;12220:24;12192:62;:::i;:::-;12182:72;;;10558:1702;;;;;:::o;12265:255::-;12323:6;12376:2;12364:9;12355:7;12351:23;12347:32;12344:2;;;12397:6;12389;12382:22;12344:2;12441:9;12428:23;12460:30;12484:5;12460:30;:::i;12525:259::-;12594:6;12647:2;12635:9;12626:7;12622:23;12618:32;12615:2;;;12668:6;12660;12653:22;12615:2;12705:9;12699:16;12724:30;12748:5;12724:30;:::i;12789:323::-;12856:6;12864;12917:2;12905:9;12896:7;12892:23;12888:32;12885:2;;;12938:6;12930;12923:22;12885:2;12982:9;12969:23;13001:30;13025:5;13001:30;:::i;:::-;13050:5;13102:2;13087:18;;;;13074:32;;-1:-1:-1;;;12875:237:35:o;13312:216::-;13381:6;13434:2;13422:9;13413:7;13409:23;13405:32;13402:2;;;13455:6;13447;13440:22;13402:2;13483:39;13512:9;13483:39;:::i;13533:255::-;13591:6;13644:2;13632:9;13623:7;13619:23;13615:32;13612:2;;;13665:6;13657;13650:22;13612:2;13709:9;13696:23;13728:30;13752:5;13728:30;:::i;13793:471::-;13856:3;13894:5;13888:12;13921:6;13916:3;13909:19;13947:4;13976:2;13971:3;13967:12;13960:19;;14013:2;14006:5;14002:14;14034:3;14046:193;14060:6;14057:1;14054:13;14046:193;;;14109:48;14153:3;14144:6;14138:13;14611:12;;14625:6;14607:25;14595:38;;14682:4;14671:16;;;14665:23;14649:14;;14642:47;14585:110;14109:48;14186:4;14177:14;;;;;14214:15;;;;14082:1;14075:9;14046:193;;;-1:-1:-1;14255:3:35;;13864:400;-1:-1:-1;;;;;13864:400:35:o;14269:257::-;14310:3;14348:5;14342:12;14375:6;14370:3;14363:19;14391:63;14447:6;14440:4;14435:3;14431:14;14424:4;14417:5;14413:16;14391:63;:::i;:::-;14508:2;14487:15;-1:-1:-1;;14483:29:35;14474:39;;;;14515:4;14470:50;;14318:208;-1:-1:-1;;14318:208:35:o;14700:326::-;14781:5;14775:12;14770:3;14763:25;14834:4;14827:5;14823:16;14817:23;14849:53;14896:4;14891:3;14887:14;14873:12;15122:5;15116:12;15113:1;15102:27;15097:3;15090:40;-1:-1:-1;;;;;15183:4:35;15176:5;15172:16;15166:23;15162:48;15155:4;15150:3;15146:14;15139:72;15274:4;15267:5;15263:16;15257:23;15254:1;15243:38;15236:4;15231:3;15227:14;15220:62;15331:4;15324:5;15320:16;15314:23;15307:4;15302:3;15298:14;15291:47;15080:264;;;14849:53;-1:-1:-1;14950:4:35;14939:16;;;14933:23;15116:12;;15113:1;15102:27;15014:4;15005:14;;15090:40;15183:4;15172:16;;15166:23;-1:-1:-1;;;;;15162:48:35;15146:14;;;15139:72;15263:16;;;15257:23;15254:1;15243:38;15227:14;;;15220:62;15331:4;15320:16;;15314:23;15298:14;;;15291:47;14965:55;15080:264::o;15349:274::-;15478:3;15516:6;15510:13;15532:53;15578:6;15573:3;15566:4;15558:6;15554:17;15532:53;:::i;:::-;15601:16;;;;;15486:137;-1:-1:-1;;15486:137:35:o;16319:372::-;16533:3;16528;16524:13;16515:6;16510:3;16506:16;16502:36;16497:3;16490:49;16472:3;16568:6;16562:13;16584:61;16638:6;16634:1;16629:3;16625:11;16618:4;16610:6;16606:17;16584:61;:::i;:::-;16665:16;;;;16683:1;16661:24;;16480:211;-1:-1:-1;;;16480:211:35:o;17213:327::-;17448:2;17437:9;17430:21;17411:4;17468:66;17530:2;17519:9;17515:18;17507:6;17468:66;:::i;17545:597::-;17914:2;17903:9;17896:21;17877:4;17940:66;18002:2;17991:9;17987:18;17979:6;17940:66;:::i;:::-;18054:9;18046:6;18042:22;18037:2;18026:9;18022:18;18015:50;18082:54;18129:6;18121;18082:54;:::i;18147:714::-;18372:2;18424:21;;;18494:13;;18397:18;;;18516:22;;;18343:4;;18372:2;18595:15;;;;18569:2;18554:18;;;18343:4;18641:194;18655:6;18652:1;18649:13;18641:194;;;18704:47;18747:3;18738:6;18732:13;18704:47;:::i;:::-;18810:15;;;;18780:6;18771:16;;;;;18677:1;18670:9;18641:194;;;-1:-1:-1;18852:3:35;;18352:509;-1:-1:-1;;;;;;18352:509:35:o;19240:391::-;19397:2;19386:9;19379:21;19436:6;19431:2;19420:9;19416:18;19409:34;19493:6;19485;19480:2;19469:9;19465:18;19452:48;19360:4;19520:22;;;19544:2;19516:31;;;19509:45;;;;19615:2;19594:15;;;-1:-1:-1;;19590:29:35;19575:45;19571:54;;19369:262;-1:-1:-1;19369:262:35:o;19636:217::-;19783:2;19772:9;19765:21;19746:4;19803:44;19843:2;19832:9;19828:18;19820:6;19803:44;:::i;20914:408::-;21116:2;21098:21;;;21155:2;21135:18;;;21128:30;21194:34;21189:2;21174:18;;21167:62;-1:-1:-1;;;21260:2:35;21245:18;;21238:42;21312:3;21297:19;;21088:234::o;21676:408::-;21878:2;21860:21;;;21917:2;21897:18;;;21890:30;21956:34;21951:2;21936:18;;21929:62;-1:-1:-1;;;22022:2:35;22007:18;;22000:42;22074:3;22059:19;;21850:234::o;27022:407::-;27224:2;27206:21;;;27263:2;27243:18;;;27236:30;27302:34;27297:2;27282:18;;27275:62;-1:-1:-1;;;27368:2:35;27353:18;;27346:41;27419:3;27404:19;;27196:233::o;27783:410::-;28036:2;28025:9;28018:21;27999:4;28074:6;28068:13;28117:2;28112;28101:9;28097:18;28090:30;28137:50;28183:2;28172:9;28168:18;28154:12;28137:50;:::i;28198:255::-;14611:12;;14625:6;14607:25;14595:38;;14682:4;14671:16;;;14665:23;14649:14;;;14642:47;28388:2;28373:18;;28400:47;14585:110;28963:739;29170:2;29159:9;29152:21;29133:4;29198:6;29192:13;29231:1;29227:2;29224:9;29214:2;;29237:18;;:::i;:::-;29293:2;29288;29277:9;29273:18;29266:30;;29343:2;29335:6;29331:15;29325:22;29383:1;29369:12;29366:19;29356:2;;29389:18;;:::i;:::-;29445:12;29440:2;29429:9;29425:18;29418:40;;29522:6;29516:2;29508:6;29504:15;29498:22;29494:35;29489:2;29478:9;29474:18;29467:63;29579:2;29571:6;29567:15;29561:22;29621:4;29614;29603:9;29599:20;29592:34;29643:53;29691:3;29680:9;29676:19;29660:14;29643:53;:::i;29707:253::-;29895:3;29880:19;;29908:46;29884:9;29936:6;29908:46;:::i;29965:241::-;15116:12;;15113:1;15102:27;15090:40;;15183:4;15172:16;;;15166:23;-1:-1:-1;;;;;15162:48:35;15146:14;;;15139:72;15274:4;15263:16;;;15257:23;15254:1;15243:38;15227:14;;;15220:62;15331:4;15320:16;;;15314:23;15298:14;;;15291:47;30145:3;30130:19;;30158:42;15080:264;30537:386;30744:2;30733:9;30726:21;30707:4;30782:6;30776:13;30825:2;30820;30809:9;30805:18;30798:30;30845:72;30913:2;30902:9;30898:18;30884:12;30845:72;:::i;33745:533::-;33822:4;33828:6;33888:11;33875:25;33982:2;33978:7;33967:8;33951:14;33947:29;33943:43;33923:18;33919:68;33909:2;;34004:4;33998;33991:18;33909:2;34034:33;;34086:20;;;-1:-1:-1;;;;;;34118:30:35;;34115:2;;;34164:4;34158;34151:18;34115:2;34200:4;34188:17;;-1:-1:-1;34231:14:35;34227:27;;;34217:38;;34214:2;;;34268:1;34265;34258:12;34283:253;34355:2;34349:9;34397:4;34385:17;;-1:-1:-1;;;;;34417:34:35;;34453:22;;;34414:62;34411:2;;;34479:18;;:::i;:::-;34515:2;34508:22;34329:207;:::o;34541:255::-;34613:2;34607:9;34655:6;34643:19;;-1:-1:-1;;;;;34677:34:35;;34713:22;;;34674:62;34671:2;;;34739:18;;:::i;34801:275::-;34872:2;34866:9;34937:2;34918:13;;-1:-1:-1;;34914:27:35;34902:40;;-1:-1:-1;;;;;34957:34:35;;34993:22;;;34954:62;34951:2;;;35019:18;;:::i;:::-;35055:2;35048:22;34846:230;;-1:-1:-1;34846:230:35:o;35081:186::-;35129:4;-1:-1:-1;;;;;35154:6:35;35151:30;35148:2;;;35184:18;;:::i;:::-;-1:-1:-1;35250:2:35;35229:15;-1:-1:-1;;35225:29:35;35256:4;35221:40;;35138:129::o;35272:363::-;35377:9;35388;35430:8;35418:10;35415:24;35412:2;;;35460:9;35449;35442:28;35412:2;35497:6;35487:8;35484:20;35481:2;;;35525:9;35514;35507:28;35481:2;-1:-1:-1;;35559:23:35;;;35604:25;;;;;-1:-1:-1;35402:233:35:o;35640:128::-;35680:3;35711:1;35707:6;35704:1;35701:13;35698:2;;;35717:18;;:::i;:::-;-1:-1:-1;35753:9:35;;35688:80::o;35773:422::-;35862:1;35905:5;35862:1;35919:270;35940:7;35930:8;35927:21;35919:270;;;35999:4;35995:1;35991:6;35987:17;35981:4;35978:27;35975:2;;;36008:18;;:::i;:::-;36058:7;36048:8;36044:22;36041:2;;;36078:16;;;;36041:2;36157:22;;;;36117:15;;;;35919:270;;;35923:3;35837:358;;;;;:::o;36200:131::-;36260:5;36289:36;36316:8;36310:4;36385:5;36415:8;36405:2;;-1:-1:-1;36456:1:35;36470:5;;36405:2;36504:4;36494:2;;-1:-1:-1;36541:1:35;36555:5;;36494:2;36586:4;36604:1;36599:59;;;;36672:1;36667:130;;;;36579:218;;36599:59;36629:1;36620:10;;36643:5;;;36667:130;36704:3;36694:8;36691:17;36688:2;;;36711:18;;:::i;:::-;-1:-1:-1;;36767:1:35;36753:16;;36782:5;;36579:218;;36881:2;36871:8;36868:16;36862:3;36856:4;36853:13;36849:36;36843:2;36833:8;36830:16;36825:2;36819:4;36816:12;36812:35;36809:77;36806:2;;;-1:-1:-1;36918:19:35;;;36950:5;;36806:2;36997:34;37022:8;37016:4;36997:34;:::i;:::-;37067:6;37063:1;37059:6;37055:19;37046:7;37043:32;37040:2;;;37078:18;;:::i;:::-;37116:20;;36395:747;-1:-1:-1;;;36395:747:35:o;37147:168::-;37187:7;37253:1;37249;37245:6;37241:14;37238:1;37235:21;37230:1;37223:9;37216:17;37212:45;37209:2;;;37260:18;;:::i;:::-;-1:-1:-1;37300:9:35;;37199:116::o;37320:125::-;37360:4;37388:1;37385;37382:8;37379:2;;;37393:18;;:::i;:::-;-1:-1:-1;37430:9:35;;37369:76::o;37450:258::-;37522:1;37532:113;37546:6;37543:1;37540:13;37532:113;;;37622:11;;;37616:18;37603:11;;;37596:39;37568:2;37561:10;37532:113;;;37663:6;37660:1;37657:13;37654:2;;;-1:-1:-1;;37698:1:35;37680:16;;37673:27;37503:205::o;37713:135::-;37752:3;-1:-1:-1;;37773:17:35;;37770:2;;;37793:18;;:::i;:::-;-1:-1:-1;37840:1:35;37829:13;;37760:88::o;37853:127::-;37914:10;37909:3;37905:20;37902:1;37895:31;37945:4;37942:1;37935:15;37969:4;37966:1;37959:15;37985:127;38046:10;38041:3;38037:20;38034:1;38027:31;38077:4;38074:1;38067:15;38101:4;38098:1;38091:15;38117:127;38178:10;38173:3;38169:20;38166:1;38159:31;38209:4;38206:1;38199:15;38233:4;38230:1;38223:15;38249:117;38334:6;38327:5;38323:18;38316:5;38313:29;38303:2;;38356:1;38353;38346:12;38371:129;-1:-1:-1;;;;;38449:5:35;38445:30;38438:5;38435:41;38425:2;;38490:1;38487;38480:12
Swarm Source
ipfs://ab7582184ce1397c9a45ad113da76101d50500a9eecd891a38118da7c3ec8d78
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.