Overview
ETH Balance
ETH Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Initialize | 175711 | 898 days ago | IN | 0 ETH | 0.00017504 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 28319644 | 1 hr ago | 0 ETH | ||||
| 28319484 | 1 hr ago | 0 ETH | ||||
| 28318737 | 2 hrs ago | 0 ETH | ||||
| 28316855 | 3 hrs ago | 0 ETH | ||||
| 28316840 | 3 hrs ago | 0 ETH | ||||
| 28316827 | 3 hrs ago | 0 ETH | ||||
| 28316069 | 3 hrs ago | 0 ETH | ||||
| 28315821 | 3 hrs ago | 0 ETH | ||||
| 28315770 | 3 hrs ago | 0 ETH | ||||
| 28315608 | 3 hrs ago | 0 ETH | ||||
| 28315601 | 3 hrs ago | 0 ETH | ||||
| 28315589 | 4 hrs ago | 0 ETH | ||||
| 28315130 | 4 hrs ago | 0 ETH | ||||
| 28314699 | 4 hrs ago | 0 ETH | ||||
| 28308861 | 8 hrs ago | 0 ETH | ||||
| 28308791 | 8 hrs ago | 0 ETH | ||||
| 28308789 | 8 hrs ago | 0 ETH | ||||
| 28308015 | 9 hrs ago | 0 ETH | ||||
| 28308015 | 9 hrs ago | 0 ETH | ||||
| 28308015 | 9 hrs ago | 0 ETH | ||||
| 28308010 | 9 hrs ago | 0 ETH | ||||
| 28308007 | 9 hrs ago | 0 ETH | ||||
| 28308007 | 9 hrs ago | 0 ETH | ||||
| 28308005 | 9 hrs ago | 0 ETH | ||||
| 28307536 | 9 hrs ago | 0 ETH |
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:
PoolOracle
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
import {IERC20Upgradeable} from '@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol';
import {SafeERC20Upgradeable} from '@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol';
import {Initializable} from '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';
import {UUPSUpgradeable} from '@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol';
import {OwnableUpgradeable} from '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol';
import {IPoolOracle} from './../interfaces/oracle/IPoolOracle.sol';
import {IPoolStorage} from './../interfaces/pool/IPoolStorage.sol';
import {Oracle} from './../libraries/Oracle.sol';
/// @title KyberSwap v2 Pool Oracle
contract PoolOracle is
IPoolOracle,
Initializable,
UUPSUpgradeable,
OwnableUpgradeable
{
using SafeERC20Upgradeable for IERC20Upgradeable;
using Oracle for Oracle.Observation[65535];
struct ObservationData {
bool initialized;
// the most-recently updated index of the observations array
uint16 index;
// the current maximum number of observations that are being stored
uint16 cardinality;
// the next maximum number of observations to store, triggered in observations.write
uint16 cardinalityNext;
}
mapping(address => Oracle.Observation[65535]) internal poolOracle;
mapping(address => ObservationData) internal poolObservation;
function initialize() public initializer {
__Ownable_init();
}
function _authorizeUpgrade(address) internal override onlyOwner {}
/// @notice Owner's function to rescue any funds stuck in the contract.
function rescueFund(address token, uint256 amount) external onlyOwner {
if (token == address(0)) {
(bool success, ) = payable(owner()).call{value: amount}('');
require(success, "failed to collect native");
} else {
IERC20Upgradeable(token).safeTransfer(owner(), amount);
}
emit OwnerWithdrew(owner(), token, amount);
}
/// @inheritdoc IPoolOracle
function initializeOracle(uint32 time)
external override
returns (uint16 cardinality, uint16 cardinalityNext)
{
(cardinality, cardinalityNext) = poolOracle[msg.sender].initialize(time);
poolObservation[msg.sender] = ObservationData({
initialized: true,
index: 0,
cardinality: cardinality,
cardinalityNext: cardinalityNext
});
}
/// @inheritdoc IPoolOracle
function write(
uint32 blockTimestamp,
int24 tick,
uint128 liquidity
)
external override
returns (uint16 indexUpdated, uint16 cardinalityUpdated)
{
return writeNewEntry(
poolObservation[msg.sender].index,
blockTimestamp,
tick,
liquidity,
poolObservation[msg.sender].cardinality,
poolObservation[msg.sender].cardinalityNext
);
}
/// @inheritdoc IPoolOracle
function increaseObservationCardinalityNext(
address pool,
uint16 observationCardinalityNext
)
external
override
{
uint16 observationCardinalityNextOld = poolObservation[pool].cardinalityNext;
uint16 observationCardinalityNextNew = poolOracle[pool].grow(
observationCardinalityNextOld,
observationCardinalityNext
);
poolObservation[pool].cardinalityNext = observationCardinalityNextNew;
if (observationCardinalityNextOld != observationCardinalityNextNew)
emit IncreaseObservationCardinalityNext(
pool,
observationCardinalityNextOld,
observationCardinalityNextNew
);
}
/// @inheritdoc IPoolOracle
function writeNewEntry(
uint16 index,
uint32 blockTimestamp,
int24 tick,
uint128 liquidity,
uint16 cardinality,
uint16 cardinalityNext
)
public override
returns (uint16 indexUpdated, uint16 cardinalityUpdated)
{
liquidity; // unused for now
address pool = msg.sender;
(indexUpdated, cardinalityUpdated) = poolOracle[pool].write(
index,
blockTimestamp,
tick,
cardinality,
cardinalityNext
);
poolObservation[pool].index = indexUpdated;
poolObservation[pool].cardinality = cardinalityUpdated;
}
/// @inheritdoc IPoolOracle
function observeFromPool(
address pool,
uint32[] memory secondsAgos
)
external view override
returns (int56[] memory tickCumulatives)
{
(, int24 tick, ,) = IPoolStorage(pool).getPoolState();
return poolOracle[pool].observe(
_blockTimestamp(),
secondsAgos,
tick,
poolObservation[pool].index,
poolObservation[pool].cardinality
);
}
/// @inheritdoc IPoolOracle
function observeSingleFromPool(
address pool,
uint32 secondsAgo
)
external view override
returns (int56 tickCumulative)
{
(, int24 tick, ,) = IPoolStorage(pool).getPoolState();
return poolOracle[pool].observeSingle(
_blockTimestamp(),
secondsAgo,
tick,
poolObservation[pool].index,
poolObservation[pool].cardinality
);
}
/// @inheritdoc IPoolOracle
function getPoolObservation(address pool)
external view override
returns (bool initialized, uint16 index, uint16 cardinality, uint16 cardinalityNext)
{
(initialized, index, cardinality, cardinalityNext) = (
poolObservation[pool].initialized,
poolObservation[pool].index,
poolObservation[pool].cardinality,
poolObservation[pool].cardinalityNext
);
}
/// @inheritdoc IPoolOracle
function getObservationAt(address pool, uint256 index)
external view override
returns (
uint32 blockTimestamp,
int56 tickCumulative,
bool initialized
)
{
Oracle.Observation memory obsData = poolOracle[pool][index];
(blockTimestamp, tickCumulative, initialized) = (
obsData.blockTimestamp,
obsData.tickCumulative,
obsData.initialized
);
}
/// @dev For overriding in tests
function _blockTimestamp() internal view virtual returns (uint32) {
return uint32(block.timestamp);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
import "../../../utils/AddressUpgradeable.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20Upgradeable {
using AddressUpgradeable for address;
function safeTransfer(
IERC20Upgradeable token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20Upgradeable token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20Upgradeable token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @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 a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
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, ERC1967UpgradeUpgradeable {
function __UUPSUpgradeable_init() internal initializer {
__ERC1967Upgrade_init_unchained();
__UUPSUpgradeable_init_unchained();
}
function __UUPSUpgradeable_init_unchained() internal initializer {
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*/
function upgradeTo(address newImplementation) external virtual {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallSecure(newImplementation, bytes(""), 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 {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallSecure(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;
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
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 initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
_setOwner(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_setOwner(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");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IPoolOracle {
/// @notice Owner withdrew funds in the pool oracle in case some funds are stuck there
event OwnerWithdrew(
address indexed owner,
address indexed token,
uint256 indexed amount
);
/// @notice Emitted by the Pool Oracle for increases to the number of observations that can be stored
/// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index
/// just before a mint/swap/burn.
/// @param pool The pool address to update
/// @param observationCardinalityNextOld The previous value of the next observation cardinality
/// @param observationCardinalityNextNew The updated value of the next observation cardinality
event IncreaseObservationCardinalityNext(
address pool,
uint16 observationCardinalityNextOld,
uint16 observationCardinalityNextNew
);
/// @notice Initalize observation data for the caller.
function initializeOracle(uint32 time)
external
returns (uint16 cardinality, uint16 cardinalityNext);
/// @notice Write a new oracle entry into the array
/// and update the observation index and cardinality
/// Read the Oralce.write function for more details
function writeNewEntry(
uint16 index,
uint32 blockTimestamp,
int24 tick,
uint128 liquidity,
uint16 cardinality,
uint16 cardinalityNext
)
external
returns (uint16 indexUpdated, uint16 cardinalityUpdated);
/// @notice Write a new oracle entry into the array, take the latest observaion data as inputs
/// and update the observation index and cardinality
/// Read the Oralce.write function for more details
function write(
uint32 blockTimestamp,
int24 tick,
uint128 liquidity
)
external
returns (uint16 indexUpdated, uint16 cardinalityUpdated);
/// @notice Increase the maximum number of price observations that this pool will store
/// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to
/// the input observationCardinalityNext.
/// @param pool The pool address to be updated
/// @param observationCardinalityNext The desired minimum number of observations for the pool to store
function increaseObservationCardinalityNext(
address pool,
uint16 observationCardinalityNext
)
external;
/// @notice Returns the accumulator values as of each time seconds ago from the latest block time in the array of `secondsAgos`
/// @dev Reverts if `secondsAgos` > oldest observation
/// @dev It fetches the latest current tick data from the pool
/// Read the Oracle.observe function for more details
function observeFromPool(
address pool,
uint32[] memory secondsAgos
)
external view
returns (int56[] memory tickCumulatives);
/// @notice Returns the accumulator values as the time seconds ago from the latest block time of secondsAgo
/// @dev Reverts if `secondsAgo` > oldest observation
/// @dev It fetches the latest current tick data from the pool
/// Read the Oracle.observeSingle function for more details
function observeSingleFromPool(
address pool,
uint32 secondsAgo
)
external view
returns (int56 tickCumulative);
/// @notice Return the latest pool observation data given the pool address
function getPoolObservation(address pool)
external view
returns (bool initialized, uint16 index, uint16 cardinality, uint16 cardinalityNext);
/// @notice Returns data about a specific observation index
/// @param pool The pool address of the observations array to fetch
/// @param index The element of the observations array to fetch
/// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time
/// ago, rather than at a specific index in the array.
/// @return blockTimestamp The timestamp of the observation,
/// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,
/// Returns initialized whether the observation has been initialized and the values are safe to use
function getObservationAt(address pool, uint256 index)
external view
returns (
uint32 blockTimestamp,
int56 tickCumulative,
bool initialized
);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {IFactory} from '../IFactory.sol';
import {IPoolOracle} from '../oracle/IPoolOracle.sol';
interface IPoolStorage {
/// @notice The contract that deployed the pool, which must adhere to the IFactory interface
/// @return The contract address
function factory() external view returns (IFactory);
/// @notice The oracle contract that stores necessary data for price oracle
/// @return The contract address
function poolOracle() external view returns (IPoolOracle);
/// @notice The first of the two tokens of the pool, sorted by address
/// @return The token contract address
function token0() external view returns (IERC20);
/// @notice The second of the two tokens of the pool, sorted by address
/// @return The token contract address
function token1() external view returns (IERC20);
/// @notice The fee to be charged for a swap in basis points
/// @return The swap fee in basis points
function swapFeeUnits() external view returns (uint24);
/// @notice The pool tick distance
/// @dev Ticks can only be initialized and used at multiples of this value
/// It remains an int24 to avoid casting even though it is >= 1.
/// e.g: a tickDistance of 5 means ticks can be initialized every 5th tick, i.e., ..., -10, -5, 0, 5, 10, ...
/// @return The tick distance
function tickDistance() external view returns (int24);
/// @notice Maximum gross liquidity that an initialized tick can have
/// @dev This is to prevent overflow the pool's active base liquidity (uint128)
/// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool
/// @return The max amount of liquidity per tick
function maxTickLiquidity() external view returns (uint128);
/// @notice Look up information about a specific tick in the pool
/// @param tick The tick to look up
/// @return liquidityGross total liquidity amount from positions that uses this tick as a lower or upper tick
/// liquidityNet how much liquidity changes when the pool tick crosses above the tick
/// feeGrowthOutside the fee growth on the other side of the tick relative to the current tick
/// secondsPerLiquidityOutside the seconds per unit of liquidity spent on the other side of the tick relative to the current tick
function ticks(int24 tick)
external
view
returns (
uint128 liquidityGross,
int128 liquidityNet,
uint256 feeGrowthOutside,
uint128 secondsPerLiquidityOutside
);
/// @notice Returns the previous and next initialized ticks of a specific tick
/// @dev If specified tick is uninitialized, the returned values are zero.
/// @param tick The tick to look up
function initializedTicks(int24 tick) external view returns (int24 previous, int24 next);
/// @notice Returns the information about a position by the position's key
/// @return liquidity the liquidity quantity of the position
/// @return feeGrowthInsideLast fee growth inside the tick range as of the last mint / burn action performed
function getPositions(
address owner,
int24 tickLower,
int24 tickUpper
) external view returns (uint128 liquidity, uint256 feeGrowthInsideLast);
/// @notice Fetches the pool's prices, ticks and lock status
/// @return sqrtP sqrt of current price: sqrt(token1/token0)
/// @return currentTick pool's current tick
/// @return nearestCurrentTick pool's nearest initialized tick that is <= currentTick
/// @return locked true if pool is locked, false otherwise
function getPoolState()
external
view
returns (
uint160 sqrtP,
int24 currentTick,
int24 nearestCurrentTick,
bool locked
);
/// @notice Fetches the pool's liquidity values
/// @return baseL pool's base liquidity without reinvest liqudity
/// @return reinvestL the liquidity is reinvested into the pool
/// @return reinvestLLast last cached value of reinvestL, used for calculating reinvestment token qty
function getLiquidityState()
external
view
returns (
uint128 baseL,
uint128 reinvestL,
uint128 reinvestLLast
);
/// @return feeGrowthGlobal All-time fee growth per unit of liquidity of the pool
function getFeeGrowthGlobal() external view returns (uint256);
/// @return secondsPerLiquidityGlobal All-time seconds per unit of liquidity of the pool
/// @return lastUpdateTime The timestamp in which secondsPerLiquidityGlobal was last updated
function getSecondsPerLiquidityData()
external
view
returns (uint128 secondsPerLiquidityGlobal, uint32 lastUpdateTime);
/// @notice Calculates and returns the active time per unit of liquidity until current block.timestamp
/// @param tickLower The lower tick (of a position)
/// @param tickUpper The upper tick (of a position)
/// @return secondsPerLiquidityInside active time (multiplied by 2^96)
/// between the 2 ticks, per unit of liquidity.
function getSecondsPerLiquidityInside(int24 tickLower, int24 tickUpper)
external
view
returns (uint128 secondsPerLiquidityInside);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.9;
/// @title Oracle
/// @notice Provides price data useful for a wide variety of system designs
/// @dev Instances of stored oracle data, "observations", are collected in the oracle array
/// Every pool is initialized with an oracle array length of 1. Anyone can pay the SSTOREs to increase the
/// maximum length of the oracle array. New slots will be added when the array is fully populated.
/// Observations are overwritten when the full length of the oracle array is populated.
/// The most recent observation is available, independent of the length of the oracle array, by passing 0 to observe()
library Oracle {
struct Observation {
// the block timestamp of the observation
uint32 blockTimestamp;
// the tick accumulator, i.e. tick * time elapsed since the pool was first initialized
int56 tickCumulative;
// whether or not the observation is initialized
bool initialized;
}
/// @notice Transforms a previous observation into a new observation, given the passage of time and the current tick
/// @dev blockTimestamp _must_ be chronologically equal to or greater than last.blockTimestamp, safe for 0 or 1 overflows
/// @param last The specified observation to be transformed
/// @param blockTimestamp The timestamp of the new observation
/// @param tick The active tick at the time of the new observation
/// @return Observation The newly populated observation
function transform(
Observation memory last,
uint32 blockTimestamp,
int24 tick
) private pure returns (Observation memory) {
unchecked {
uint32 delta = blockTimestamp - last.blockTimestamp;
return
Observation({
blockTimestamp: blockTimestamp,
tickCumulative: last.tickCumulative + int56(tick) * int32(delta),
initialized: true
});
}
}
/// @notice Initialize the oracle array by writing the first slot. Called once for the lifecycle of the observations array
/// @param self The stored oracle array
/// @param time The time of the oracle initialization, via block.timestamp truncated to uint32
/// @return cardinality The number of populated elements in the oracle array
/// @return cardinalityNext The new length of the oracle array, independent of population
function initialize(Observation[65535] storage self, uint32 time)
internal
returns (uint16 cardinality, uint16 cardinalityNext)
{
self[0] = Observation({
blockTimestamp: time,
tickCumulative: 0,
initialized: true
});
return (1, 1);
}
/// @notice Writes an oracle observation to the array
/// @dev Writable at most once per block. Index represents the most recently written element. cardinality and index must be tracked externally.
/// If the index is at the end of the allowable array length (according to cardinality), and the next cardinality
/// is greater than the current one, cardinality may be increased. This restriction is created to preserve ordering.
/// @param self The stored oracle array
/// @param index The index of the observation that was most recently written to the observations array
/// @param blockTimestamp The timestamp of the new observation
/// @param tick The active tick at the time of the new observation
/// @param cardinality The number of populated elements in the oracle array
/// @param cardinalityNext The new length of the oracle array, independent of population
/// @return indexUpdated The new index of the most recently written element in the oracle array
/// @return cardinalityUpdated The new cardinality of the oracle array
function write(
Observation[65535] storage self,
uint16 index,
uint32 blockTimestamp,
int24 tick,
uint16 cardinality,
uint16 cardinalityNext
) internal returns (uint16 indexUpdated, uint16 cardinalityUpdated) {
Observation memory last = self[index];
// early return if we've already written an observation this block
if (last.blockTimestamp == blockTimestamp) return (index, cardinality);
unchecked {
// if the conditions are right, we can bump the cardinality
if (cardinalityNext > cardinality && index == (cardinality - 1)) {
cardinalityUpdated = cardinalityNext;
} else {
cardinalityUpdated = cardinality;
}
indexUpdated = (index + 1) % cardinalityUpdated;
}
self[indexUpdated] = transform(last, blockTimestamp, tick);
}
/// @notice Prepares the oracle array to store up to `next` observations
/// @param self The stored oracle array
/// @param current The current next cardinality of the oracle array
/// @param next The proposed next cardinality which will be populated in the oracle array
/// @return next The next cardinality which will be populated in the oracle array
function grow(
Observation[65535] storage self,
uint16 current,
uint16 next
) internal returns (uint16) {
require(current > 0, 'I');
// no-op if the passed next value isn't greater than the current next value
if (next <= current) return current;
// store in each slot to prevent fresh SSTOREs in swaps
// this data will not be used because the initialized boolean is still false
for (uint16 i = current; i < next; i++) self[i].blockTimestamp = 1;
return next;
}
/// @notice comparator for 32-bit timestamps
/// @dev safe for 0 or 1 overflows, a and b _must_ be chronologically before or equal to time
/// @param time A timestamp truncated to 32 bits
/// @param a A comparison timestamp from which to determine the relative position of `time`
/// @param b From which to determine the relative position of `time`
/// @return bool Whether `a` is chronologically <= `b`
function lte(
uint32 time,
uint32 a,
uint32 b
) private pure returns (bool) {
unchecked {
// if there hasn't been overflow, no need to adjust
if (a <= time && b <= time) return a <= b;
uint256 aAdjusted = a > time ? a : a + 2**32;
uint256 bAdjusted = b > time ? b : b + 2**32;
return aAdjusted <= bAdjusted;
}
}
/// @notice Fetches the observations beforeOrAt and atOrAfter a target, i.e. where [beforeOrAt, atOrAfter] is satisfied.
/// The result may be the same observation, or adjacent observations.
/// @dev The answer must be contained in the array, used when the target is located within the stored observation
/// boundaries: older than the most recent observation and younger, or the same age as, the oldest observation
/// @param self The stored oracle array
/// @param time The current block.timestamp
/// @param target The timestamp at which the reserved observation should be for
/// @param index The index of the observation that was most recently written to the observations array
/// @param cardinality The number of populated elements in the oracle array
/// @return beforeOrAt The observation recorded before, or at, the target
/// @return atOrAfter The observation recorded at, or after, the target
function binarySearch(
Observation[65535] storage self,
uint32 time,
uint32 target,
uint16 index,
uint16 cardinality
) private view returns (Observation memory beforeOrAt, Observation memory atOrAfter) {
unchecked {
uint256 l = (index + 1) % cardinality; // oldest observation
uint256 r = l + cardinality - 1; // newest observation
uint256 i;
while (true) {
i = (l + r) / 2;
beforeOrAt = self[i % cardinality];
// we've landed on an uninitialized tick, keep searching higher (more recently)
if (!beforeOrAt.initialized) {
l = i + 1;
continue;
}
atOrAfter = self[(i + 1) % cardinality];
bool targetAtOrAfter = lte(time, beforeOrAt.blockTimestamp, target);
// check if we've found the answer!
if (targetAtOrAfter && lte(time, target, atOrAfter.blockTimestamp)) break;
if (!targetAtOrAfter) r = i - 1;
else l = i + 1;
}
}
}
/// @notice Fetches the observations beforeOrAt and atOrAfter a given target, i.e. where [beforeOrAt, atOrAfter] is satisfied
/// @dev Assumes there is at least 1 initialized observation.
/// Used by observeSingle() to compute the counterfactual accumulator values as of a given block timestamp.
/// @param self The stored oracle array
/// @param time The current block.timestamp
/// @param target The timestamp at which the reserved observation should be for
/// @param tick The active tick at the time of the returned or simulated observation
/// @param index The index of the observation that was most recently written to the observations array
/// @param cardinality The number of populated elements in the oracle array
/// @return beforeOrAt The observation which occurred at, or before, the given timestamp
/// @return atOrAfter The observation which occurred at, or after, the given timestamp
function getSurroundingObservations(
Observation[65535] storage self,
uint32 time,
uint32 target,
int24 tick,
uint16 index,
uint16 cardinality
) private view returns (Observation memory beforeOrAt, Observation memory atOrAfter) {
// optimistically set before to the newest observation
beforeOrAt = self[index];
// if the target is chronologically at or after the newest observation, we can early return
if (lte(time, beforeOrAt.blockTimestamp, target)) {
if (beforeOrAt.blockTimestamp == target) {
// if newest observation equals target, we're in the same block, so we can ignore atOrAfter
return (beforeOrAt, atOrAfter);
} else {
// otherwise, we need to transform
return (beforeOrAt, transform(beforeOrAt, target, tick));
}
}
unchecked {
// now, set before to the oldest observation
beforeOrAt = self[(index + 1) % cardinality];
}
if (!beforeOrAt.initialized) beforeOrAt = self[0];
// ensure that the target is chronologically at or after the oldest observation
require(lte(time, beforeOrAt.blockTimestamp, target), 'OLD');
// if we've reached this point, we have to binary search
return binarySearch(self, time, target, index, cardinality);
}
/// @dev Reverts if an observation at or before the desired observation timestamp does not exist.
/// 0 may be passed as `secondsAgo' to return the current cumulative values.
/// If called with a timestamp falling between two observations, returns the counterfactual accumulator values
/// at exactly the timestamp between the two observations.
/// @param self The stored oracle array
/// @param time The current block timestamp
/// @param secondsAgo The amount of time to look back, in seconds, at which point to return an observation
/// @param tick The current tick
/// @param index The index of the observation that was most recently written to the observations array
/// @param cardinality The number of populated elements in the oracle array
/// @return tickCumulative The tick * time elapsed since the pool was first initialized, as of `secondsAgo`
function observeSingle(
Observation[65535] storage self,
uint32 time,
uint32 secondsAgo,
int24 tick,
uint16 index,
uint16 cardinality
) internal view returns (int56 tickCumulative) {
unchecked {
if (secondsAgo == 0) {
Observation memory last = self[index];
if (last.blockTimestamp != time) last = transform(last, time, tick);
return last.tickCumulative;
}
uint32 target = time - secondsAgo;
(Observation memory beforeOrAt, Observation memory atOrAfter) =
getSurroundingObservations(self, time, target, tick, index, cardinality);
if (target == beforeOrAt.blockTimestamp) {
// we're at the left boundary
return beforeOrAt.tickCumulative;
} else if (target == atOrAfter.blockTimestamp) {
// we're at the right boundary
return atOrAfter.tickCumulative;
} else {
// we're in the middle
uint32 observationTimeDelta = atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp;
uint32 targetDelta = target - beforeOrAt.blockTimestamp;
return beforeOrAt.tickCumulative +
((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / int32(observationTimeDelta)) *
int32(targetDelta);
}
}
}
/// @notice Returns the accumulator values as of each time seconds ago from the given time in the array of `secondsAgos`
/// @dev Reverts if `secondsAgos` > oldest observation
/// @param self The stored oracle array
/// @param time The current block.timestamp
/// @param secondsAgos Each amount of time to look back, in seconds, at which point to return an observation
/// @param tick The current tick
/// @param index The index of the observation that was most recently written to the observations array
/// @param cardinality The number of populated elements in the oracle array
/// @return tickCumulatives The tick * time elapsed since the pool was first initialized, as of each `secondsAgo`
function observe(
Observation[65535] storage self,
uint32 time,
uint32[] memory secondsAgos,
int24 tick,
uint16 index,
uint16 cardinality
) internal view returns (int56[] memory tickCumulatives) {
require(cardinality > 0, 'I');
tickCumulatives = new int56[](secondsAgos.length);
for (uint256 i = 0; i < secondsAgos.length; i++) {
tickCumulatives[i] = observeSingle(
self,
time,
secondsAgos[i],
tick,
index,
cardinality
);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;
import "../beacon/IBeaconUpgradeable.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 initializer {
__ERC1967Upgrade_init_unchained();
}
function __ERC1967Upgrade_init_unchained() internal initializer {
}
// 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 _upgradeToAndCallSecure(
address newImplementation,
bytes memory data,
bool forceCall
) internal {
address oldImplementation = _getImplementation();
// Initial upgrade and setup call
_setImplementation(newImplementation);
if (data.length > 0 || forceCall) {
_functionDelegateCall(newImplementation, data);
}
// Perform rollback test if not already in progress
StorageSlotUpgradeable.BooleanSlot storage rollbackTesting = StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT);
if (!rollbackTesting.value) {
// Trigger rollback using upgradeTo from the new implementation
rollbackTesting.value = true;
_functionDelegateCall(
newImplementation,
abi.encodeWithSignature("upgradeTo(address)", oldImplementation)
);
rollbackTesting.value = false;
// Check rollback was effective
require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades");
// Finally reset to the new implementation and log the upgrade
_upgradeTo(newImplementation);
}
}
/**
* @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");
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
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
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) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
}// SPDX-License-Identifier: MIT
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 initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
/// @title KyberSwap v2 factory
/// @notice Deploys KyberSwap v2 pools and manages control over government fees
interface IFactory {
/// @notice Emitted when a pool is created
/// @param token0 First pool token by address sort order
/// @param token1 Second pool token by address sort order
/// @param swapFeeUnits Fee to be collected upon every swap in the pool, in fee units
/// @param tickDistance Minimum number of ticks between initialized ticks
/// @param pool The address of the created pool
event PoolCreated(
address indexed token0,
address indexed token1,
uint24 indexed swapFeeUnits,
int24 tickDistance,
address pool
);
/// @notice Emitted when a new fee is enabled for pool creation via the factory
/// @param swapFeeUnits Fee to be collected upon every swap in the pool, in fee units
/// @param tickDistance Minimum number of ticks between initialized ticks for pools created with the given fee
event SwapFeeEnabled(uint24 indexed swapFeeUnits, int24 indexed tickDistance);
/// @notice Emitted when vesting period changes
/// @param vestingPeriod The maximum time duration for which LP fees
/// are proportionally burnt upon LP removals
event VestingPeriodUpdated(uint32 vestingPeriod);
/// @notice Emitted when configMaster changes
/// @param oldConfigMaster configMaster before the update
/// @param newConfigMaster configMaster after the update
event ConfigMasterUpdated(address oldConfigMaster, address newConfigMaster);
/// @notice Emitted when fee configuration changes
/// @param feeTo Recipient of government fees
/// @param governmentFeeUnits Fee amount, in fee units,
/// to be collected out of the fee charged for a pool swap
event FeeConfigurationUpdated(address feeTo, uint24 governmentFeeUnits);
/// @notice Emitted when whitelist feature is enabled
event WhitelistEnabled();
/// @notice Emitted when whitelist feature is disabled
event WhitelistDisabled();
/// @notice Returns the maximum time duration for which LP fees
/// are proportionally burnt upon LP removals
function vestingPeriod() external view returns (uint32);
/// @notice Returns the tick distance for a specified fee.
/// @dev Once added, cannot be updated or removed.
/// @param swapFeeUnits Swap fee, in fee units.
/// @return The tick distance. Returns 0 if fee has not been added.
function feeAmountTickDistance(uint24 swapFeeUnits) external view returns (int24);
/// @notice Returns the address which can update the fee configuration
function configMaster() external view returns (address);
/// @notice Returns the keccak256 hash of the Pool creation code
/// This is used for pre-computation of pool addresses
function poolInitHash() external view returns (bytes32);
/// @notice Returns the pool oracle contract for twap
function poolOracle() external view returns (address);
/// @notice Fetches the recipient of government fees
/// and current government fee charged in fee units
function feeConfiguration() external view returns (address _feeTo, uint24 _governmentFeeUnits);
/// @notice Returns the status of whitelisting feature of NFT managers
/// If true, anyone can mint liquidity tokens
/// Otherwise, only whitelisted NFT manager(s) are allowed to mint liquidity tokens
function whitelistDisabled() external view returns (bool);
//// @notice Returns all whitelisted NFT managers
/// If the whitelisting feature is turned on,
/// only whitelisted NFT manager(s) are allowed to mint liquidity tokens
function getWhitelistedNFTManagers() external view returns (address[] memory);
/// @notice Checks if sender is a whitelisted NFT manager
/// If the whitelisting feature is turned on,
/// only whitelisted NFT manager(s) are allowed to mint liquidity tokens
/// @param sender address to be checked
/// @return true if sender is a whistelisted NFT manager, false otherwise
function isWhitelistedNFTManager(address sender) external view returns (bool);
/// @notice Returns the pool address for a given pair of tokens and a swap fee
/// @dev Token order does not matter
/// @param tokenA Contract address of either token0 or token1
/// @param tokenB Contract address of the other token
/// @param swapFeeUnits Fee to be collected upon every swap in the pool, in fee units
/// @return pool The pool address. Returns null address if it does not exist
function getPool(
address tokenA,
address tokenB,
uint24 swapFeeUnits
) external view returns (address pool);
/// @notice Fetch parameters to be used for pool creation
/// @dev Called by the pool constructor to fetch the parameters of the pool
/// @return factory The factory address
/// @return poolOracle The pool oracle for twap
/// @return token0 First pool token by address sort order
/// @return token1 Second pool token by address sort order
/// @return swapFeeUnits Fee to be collected upon every swap in the pool, in fee units
/// @return tickDistance Minimum number of ticks between initialized ticks
function parameters()
external
view
returns (
address factory,
address poolOracle,
address token0,
address token1,
uint24 swapFeeUnits,
int24 tickDistance
);
/// @notice Creates a pool for the given two tokens and fee
/// @param tokenA One of the two tokens in the desired pool
/// @param tokenB The other of the two tokens in the desired pool
/// @param swapFeeUnits Desired swap fee for the pool, in fee units
/// @dev Token order does not matter. tickDistance is determined from the fee.
/// Call will revert under any of these conditions:
/// 1) pool already exists
/// 2) invalid swap fee
/// 3) invalid token arguments
/// @return pool The address of the newly created pool
function createPool(
address tokenA,
address tokenB,
uint24 swapFeeUnits
) external returns (address pool);
/// @notice Enables a fee amount with the given tickDistance
/// @dev Fee amounts may never be removed once enabled
/// @param swapFeeUnits The fee amount to enable, in fee units
/// @param tickDistance The distance between ticks to be enforced for all pools created with the given fee amount
function enableSwapFee(uint24 swapFeeUnits, int24 tickDistance) external;
/// @notice Updates the address which can update the fee configuration
/// @dev Must be called by the current configMaster
function updateConfigMaster(address) external;
/// @notice Updates the vesting period
/// @dev Must be called by the current configMaster
function updateVestingPeriod(uint32) external;
/// @notice Updates the address receiving government fees and fee quantity
/// @dev Only configMaster is able to perform the update
/// @param feeTo Address to receive government fees collected from pools
/// @param governmentFeeUnits Fee amount, in fee units,
/// to be collected out of the fee charged for a pool swap
function updateFeeConfiguration(address feeTo, uint24 governmentFeeUnits) external;
/// @notice Enables the whitelisting feature
/// @dev Only configMaster is able to perform the update
function enableWhitelist() external;
/// @notice Disables the whitelisting feature
/// @dev Only configMaster is able to perform the update
function disableWhitelist() external;
}{
"metadata": {
"bytecodeHash": "none"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"optimizer": {
"enabled": false,
"runs": 200
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint16","name":"observationCardinalityNextOld","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"observationCardinalityNextNew","type":"uint16"}],"name":"IncreaseObservationCardinalityNext","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"OwnerWithdrew","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":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getObservationAt","outputs":[{"internalType":"uint32","name":"blockTimestamp","type":"uint32"},{"internalType":"int56","name":"tickCumulative","type":"int56"},{"internalType":"bool","name":"initialized","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"getPoolObservation","outputs":[{"internalType":"bool","name":"initialized","type":"bool"},{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"uint16","name":"cardinality","type":"uint16"},{"internalType":"uint16","name":"cardinalityNext","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint16","name":"observationCardinalityNext","type":"uint16"}],"name":"increaseObservationCardinalityNext","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"time","type":"uint32"}],"name":"initializeOracle","outputs":[{"internalType":"uint16","name":"cardinality","type":"uint16"},{"internalType":"uint16","name":"cardinalityNext","type":"uint16"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint32[]","name":"secondsAgos","type":"uint32[]"}],"name":"observeFromPool","outputs":[{"internalType":"int56[]","name":"tickCumulatives","type":"int56[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint32","name":"secondsAgo","type":"uint32"}],"name":"observeSingleFromPool","outputs":[{"internalType":"int56","name":"tickCumulative","type":"int56"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueFund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint32","name":"blockTimestamp","type":"uint32"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint128","name":"liquidity","type":"uint128"}],"name":"write","outputs":[{"internalType":"uint16","name":"indexUpdated","type":"uint16"},{"internalType":"uint16","name":"cardinalityUpdated","type":"uint16"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"index","type":"uint16"},{"internalType":"uint32","name":"blockTimestamp","type":"uint32"},{"internalType":"int24","name":"tick","type":"int24"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint16","name":"cardinality","type":"uint16"},{"internalType":"uint16","name":"cardinalityNext","type":"uint16"}],"name":"writeNewEntry","outputs":[{"internalType":"uint16","name":"indexUpdated","type":"uint16"},{"internalType":"uint16","name":"cardinalityUpdated","type":"uint16"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50613c0a806100206000396000f3fe6080604052600436106100e85760003560e01c80638129fc1c1161008a5780639fc40df3116100595780639fc40df3146102d6578063e3e717e914610313578063f2fde38b14610352578063ff11275e1461037b576100e8565b80638129fc1c146102175780638934fade1461022e5780638da5cb5b1461026e5780639ef64c4914610299576100e8565b80634d650b7e116100c65780634d650b7e1461017d5780634f1ef286146101bb5780636e261df1146101d7578063715018a614610200576100e8565b80633440fba7146100ed5780633659cfe61461012b5780634c7a539b14610154575b600080fd5b3480156100f957600080fd5b50610114600480360381019061010f91906129da565b6103b9565b604051610122929190612a24565b60405180910390f35b34801561013757600080fd5b50610152600480360381019061014d9190612aab565b610516565b005b34801561016057600080fd5b5061017b60048036038101906101769190612b04565b61053d565b005b34801561018957600080fd5b506101a4600480360381019061019f9190612bc5565b610697565b6040516101b2929190612a24565b60405180910390f35b6101d560048036038101906101d09190612d98565b6107c6565b005b3480156101e357600080fd5b506101fe60048036038101906101f99190612e2a565b6107df565b005b34801561020c57600080fd5b506102156109e2565b005b34801561022357600080fd5b5061022c610a6a565b005b34801561023a57600080fd5b5061025560048036038101906102509190612aab565b610b4b565b6040516102659493929190612e85565b60405180910390f35b34801561027a57600080fd5b50610283610cab565b6040516102909190612ed9565b60405180910390f35b3480156102a557600080fd5b506102c060048036038101906102bb9190612fbc565b610cd5565b6040516102cd91906130e3565b60405180910390f35b3480156102e257600080fd5b506102fd60048036038101906102f89190613105565b610e65565b60405161030a9190613154565b60405180910390f35b34801561031f57600080fd5b5061033a60048036038101906103359190612e2a565b610ff4565b6040516103499392919061317e565b60405180910390f35b34801561035e57600080fd5b5061037960048036038101906103749190612aab565b6110db565b005b34801561038757600080fd5b506103a2600480360381019061039d91906131b5565b6111d3565b6040516103b0929190612a24565b60405180910390f35b60008061040d8360c960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206112e090919063ffffffff16565b80925081935050506040518060800160405280600115158152602001600061ffff1681526020018361ffff1681526020018261ffff1681525060ca60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548161ffff021916908361ffff16021790555060608201518160000160056101000a81548161ffff021916908361ffff160217905550905050915091565b61051f816113a9565b61053a81604051806020016040528060008152506000611428565b50565b600060ca60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160059054906101000a900461ffff16905060006105e7828460c960008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206115f99092919063ffffffff16565b90508060ca60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160056101000a81548161ffff021916908361ffff1602179055508061ffff168261ffff1614610691577ff0b7b7d1cdf542f5660a7879f0cac17375fdcf984af4a6d499a9daedacb24c5884838360405161068893929190613208565b60405180910390a15b50505050565b60008060003390506106f8898989888860c960008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206116c99095949392919063ffffffff16565b80935081945050508260ca60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160016101000a81548161ffff021916908361ffff1602179055508160ca60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160036101000a81548161ffff021916908361ffff16021790555050965096945050505050565b6107cf826113a9565b6107db82826001611428565b5050565b6107e7611871565b73ffffffffffffffffffffffffffffffffffffffff16610805610cab565b73ffffffffffffffffffffffffffffffffffffffff161461085b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108529061329c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561094957600061089a610cab565b73ffffffffffffffffffffffffffffffffffffffff16826040516108bd906132ed565b60006040518083038185875af1925050503d80600081146108fa576040519150601f19603f3d011682016040523d82523d6000602084013e6108ff565b606091505b5050905080610943576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093a9061334e565b60405180910390fd5b5061097c565b61097b610954610cab565b828473ffffffffffffffffffffffffffffffffffffffff166118799092919063ffffffff16565b5b808273ffffffffffffffffffffffffffffffffffffffff1661099c610cab565b73ffffffffffffffffffffffffffffffffffffffff167f0c2fa44dc1337dc4fb1c635f4a2a6223e69d8ac9796ca134d0380225d4b1cd0560405160405180910390a45050565b6109ea611871565b73ffffffffffffffffffffffffffffffffffffffff16610a08610cab565b73ffffffffffffffffffffffffffffffffffffffff1614610a5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a559061329c565b60405180910390fd5b610a6860006118ff565b565b600060019054906101000a900460ff1680610a90575060008054906101000a900460ff16155b610acf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ac6906133e0565b60405180910390fd5b60008060019054906101000a900460ff161590508015610b1f576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b610b276119c5565b8015610b485760008060016101000a81548160ff0219169083151502179055505b50565b60008060008060ca60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1660ca60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900461ffff1660ca60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160039054906101000a900461ffff1660ca60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160059054906101000a900461ffff16809450819550829650839750505050509193509193565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060008373ffffffffffffffffffffffffffffffffffffffff1663217ac2376040518163ffffffff1660e01b815260040160806040518083038186803b158015610d1f57600080fd5b505afa158015610d33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d57919061346d565b5050915050610e5c610d67611aae565b848360ca60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900461ffff1660ca60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160039054906101000a900461ffff1660c960008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611ab69095949392919063ffffffff16565b91505092915050565b6000808373ffffffffffffffffffffffffffffffffffffffff1663217ac2376040518163ffffffff1660e01b815260040160806040518083038186803b158015610eae57600080fd5b505afa158015610ec2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee6919061346d565b5050915050610feb610ef6611aae565b848360ca60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900461ffff1660ca60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160039054906101000a900461ffff1660c960008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611bc49095949392919063ffffffff16565b91505092915050565b60008060008060c960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208561ffff811061104c5761104b6134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff1615151515815250509050806000015181602001518260400151809450819550829650505050509250925092565b6110e3611871565b73ffffffffffffffffffffffffffffffffffffffff16611101610cab565b73ffffffffffffffffffffffffffffffffffffffff1614611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114e9061329c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156111c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111be90613575565b60405180910390fd5b6111d0816118ff565b50565b6000806112d460ca60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900461ffff1686868660ca60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160039054906101000a900461ffff1660ca60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160059054906101000a900461ffff16610697565b91509150935093915050565b60008060405180606001604052808463ffffffff168152602001600060060b81526020016001151581525084600061ffff81106113205761131f6134d4565b5b0160008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548166ffffffffffffff021916908360060b66ffffffffffffff160217905550604082015181600001600b6101000a81548160ff021916908315150217905550905050600180915091509250929050565b6113b1611871565b73ffffffffffffffffffffffffffffffffffffffff166113cf610cab565b73ffffffffffffffffffffffffffffffffffffffff1614611425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141c9061329c565b60405180910390fd5b50565b6000611432611d4e565b905061143d84611da5565b60008351118061144a5750815b1561145b576114598484611e5e565b505b60006114897f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914360001b611f42565b90508060000160009054906101000a900460ff166115f25760018160000160006101000a81548160ff02191690831515021790555061155585836040516024016114d39190612ed9565b6040516020818303038152906040527f3659cfe6000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611e5e565b5060008160000160006101000a81548160ff02191690831515021790555061157b611d4e565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115df90613607565b60405180910390fd5b6115f185611f4c565b5b5050505050565b6000808361ffff1611611641576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161163890613673565b60405180910390fd5b8261ffff168261ffff1611611658578290506116c2565b60008390505b8261ffff168161ffff1610156116bd576001858261ffff1661ffff8110611688576116876134d4565b5b0160000160006101000a81548163ffffffff021916908363ffffffff16021790555080806116b5906136c2565b91505061165e565b508190505b9392505050565b6000806000888861ffff1661ffff81106116e6576116e56134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff16151515158152505090508663ffffffff16816000015163ffffffff1614156117765787859250925050611866565b8461ffff168461ffff1611801561179757506001850361ffff168861ffff16145b156117a4578391506117a8565b8491505b8161ffff166001890161ffff16816117c3576117c26136ed565b5b0692506117d1818888611f9b565b898461ffff1661ffff81106117e9576117e86134d4565b5b0160008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548166ffffffffffffff021916908360060b66ffffffffffffff160217905550604082015181600001600b6101000a81548160ff021916908315150217905550905050505b965096945050505050565b600033905090565b6118fa8363a9059cbb60e01b848460405160240161189892919061372b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611fed565b505050565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081609760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600060019054906101000a900460ff16806119eb575060008054906101000a900460ff16155b611a2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a21906133e0565b60405180910390fd5b60008060019054906101000a900460ff161590508015611a7a576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b611a826120b4565b611a8a61218d565b8015611aab5760008060016101000a81548160ff0219169083151502179055505b50565b600042905090565b606060008261ffff1611611aff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611af690613673565b60405180910390fd5b845167ffffffffffffffff811115611b1a57611b19612c6d565b5b604051908082528060200260200182016040528015611b485781602001602082028036833780820191505090505b50905060005b8551811015611bb957611b7f8888888481518110611b6f57611b6e6134d4565b5b6020026020010151888888611bc4565b828281518110611b9257611b916134d4565b5b602002602001019060060b908160060b815250508080611bb190613754565b915050611b4e565b509695505050505050565b6000808563ffffffff161415611c8c576000878461ffff1661ffff8110611bee57611bed6134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff16151515158152505090508663ffffffff16816000015163ffffffff1614611c7f57611c7c818887611f9b565b90505b8060200151915050611d44565b60008587039050600080611ca48a8a858a8a8a612276565b91509150816000015163ffffffff168363ffffffff161415611ccf5781602001519350505050611d44565b806000015163ffffffff168363ffffffff161415611cf65780602001519350505050611d44565b60008260000151826000015103905060008360000151850390508060030b8260030b856020015185602001510360060b81611d3457611d336136ed565b5b0502846020015101955050505050505b9695505050505050565b6000611d7c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6124e5565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611dae816124ef565b611ded576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de49061380f565b60405180910390fd5b80611e1a7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6124e5565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6060611e69836124ef565b611ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9f906138a1565b60405180910390fd5b6000808473ffffffffffffffffffffffffffffffffffffffff1684604051611ed09190613930565b600060405180830381855af49150503d8060008114611f0b576040519150601f19603f3d011682016040523d82523d6000602084013e611f10565b606091505b5091509150611f388282604051806060016040528060278152602001613bd760279139612502565b9250505092915050565b6000819050919050565b611f5581611da5565b8073ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a250565b611fa361295e565b600084600001518403905060405180606001604052808563ffffffff1681526020018260030b8560020b0287602001510160060b8152602001600115158152509150509392505050565b600061204f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125699092919063ffffffff16565b90506000815111156120af578080602001905181019061206f9190613947565b6120ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120a5906139e6565b60405180910390fd5b5b505050565b600060019054906101000a900460ff16806120da575060008054906101000a900460ff16155b612119576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612110906133e0565b60405180910390fd5b60008060019054906101000a900460ff161590508015612169576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b801561218a5760008060016101000a81548160ff0219169083151502179055505b50565b600060019054906101000a900460ff16806121b3575060008054906101000a900460ff16155b6121f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e9906133e0565b60405180910390fd5b60008060019054906101000a900460ff161590508015612242576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b61225261224d611871565b6118ff565b80156122735760008060016101000a81548160ff0219169083151502179055505b50565b61227e61295e565b61228661295e565b878461ffff1661ffff811061229e5761229d6134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff161515151581525050915061231987836000015188612581565b15612350578563ffffffff16826000015163ffffffff16141561233b576124da565b81612347838888611f9b565b915091506124da565b878361ffff166001860161ffff168161236c5761236b6136ed565b5b0661ffff1661ffff8110612383576123826134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff1615151515815250509150816040015161247a5787600061ffff811061240d5761240c6134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff16151515158152505091505b61248987836000015188612581565b6124c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124bf90613a52565b60405180910390fd5b6124d58888888787612649565b915091505b965096945050505050565b6000819050919050565b600080823b905060008111915050919050565b6060831561251257829050612562565b6000835111156125255782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125599190613ab6565b60405180910390fd5b9392505050565b6060612578848460008561284a565b90509392505050565b60008363ffffffff168363ffffffff16111580156125ab57508363ffffffff168263ffffffff1611155b156125c7578163ffffffff168363ffffffff1611159050612642565b60008463ffffffff168463ffffffff16116125ef576401000000008463ffffffff16016125f7565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611612628576401000000008463ffffffff1601612630565b8363ffffffff165b64ffffffffff16905080821115925050505b9392505050565b61265161295e565b61265961295e565b60008361ffff166001860161ffff1681612676576126756136ed565b5b0661ffff169050600060018561ffff16830103905060005b60011561283d576002828401816126a8576126a76136ed565b5b049050898661ffff1682816126c0576126bf6136ed565b5b0661ffff81106126d3576126d26134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff161515151581525050945084604001516127535760018101925061268e565b898661ffff16600183018161276b5761276a6136ed565b5b0661ffff811061277e5761277d6134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff161515151581525050935060006127fb8a87600001518b612581565b905080801561281557506128148a8a8760000151612581565b5b15612820575061283d565b8061283057600182039250612837565b6001820193505b5061268e565b5050509550959350505050565b60608247101561288f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161288690613b4a565b60405180910390fd5b612898856124ef565b6128d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128ce90613bb6565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516129009190613930565b60006040518083038185875af1925050503d806000811461293d576040519150601f19603f3d011682016040523d82523d6000602084013e612942565b606091505b5091509150612952828286612502565b92505050949350505050565b6040518060600160405280600063ffffffff168152602001600060060b81526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b600063ffffffff82169050919050565b6129b78161299e565b81146129c257600080fd5b50565b6000813590506129d4816129ae565b92915050565b6000602082840312156129f0576129ef612994565b5b60006129fe848285016129c5565b91505092915050565b600061ffff82169050919050565b612a1e81612a07565b82525050565b6000604082019050612a396000830185612a15565b612a466020830184612a15565b9392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612a7882612a4d565b9050919050565b612a8881612a6d565b8114612a9357600080fd5b50565b600081359050612aa581612a7f565b92915050565b600060208284031215612ac157612ac0612994565b5b6000612acf84828501612a96565b91505092915050565b612ae181612a07565b8114612aec57600080fd5b50565b600081359050612afe81612ad8565b92915050565b60008060408385031215612b1b57612b1a612994565b5b6000612b2985828601612a96565b9250506020612b3a85828601612aef565b9150509250929050565b60008160020b9050919050565b612b5a81612b44565b8114612b6557600080fd5b50565b600081359050612b7781612b51565b92915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b612ba281612b7d565b8114612bad57600080fd5b50565b600081359050612bbf81612b99565b92915050565b60008060008060008060c08789031215612be257612be1612994565b5b6000612bf089828a01612aef565b9650506020612c0189828a016129c5565b9550506040612c1289828a01612b68565b9450506060612c2389828a01612bb0565b9350506080612c3489828a01612aef565b92505060a0612c4589828a01612aef565b9150509295509295509295565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612ca582612c5c565b810181811067ffffffffffffffff82111715612cc457612cc3612c6d565b5b80604052505050565b6000612cd761298a565b9050612ce38282612c9c565b919050565b600067ffffffffffffffff821115612d0357612d02612c6d565b5b612d0c82612c5c565b9050602081019050919050565b82818337600083830152505050565b6000612d3b612d3684612ce8565b612ccd565b905082815260208101848484011115612d5757612d56612c57565b5b612d62848285612d19565b509392505050565b600082601f830112612d7f57612d7e612c52565b5b8135612d8f848260208601612d28565b91505092915050565b60008060408385031215612daf57612dae612994565b5b6000612dbd85828601612a96565b925050602083013567ffffffffffffffff811115612dde57612ddd612999565b5b612dea85828601612d6a565b9150509250929050565b6000819050919050565b612e0781612df4565b8114612e1257600080fd5b50565b600081359050612e2481612dfe565b92915050565b60008060408385031215612e4157612e40612994565b5b6000612e4f85828601612a96565b9250506020612e6085828601612e15565b9150509250929050565b60008115159050919050565b612e7f81612e6a565b82525050565b6000608082019050612e9a6000830187612e76565b612ea76020830186612a15565b612eb46040830185612a15565b612ec16060830184612a15565b95945050505050565b612ed381612a6d565b82525050565b6000602082019050612eee6000830184612eca565b92915050565b600067ffffffffffffffff821115612f0f57612f0e612c6d565b5b602082029050602081019050919050565b600080fd5b6000612f38612f3384612ef4565b612ccd565b90508083825260208201905060208402830185811115612f5b57612f5a612f20565b5b835b81811015612f845780612f7088826129c5565b845260208401935050602081019050612f5d565b5050509392505050565b600082601f830112612fa357612fa2612c52565b5b8135612fb3848260208601612f25565b91505092915050565b60008060408385031215612fd357612fd2612994565b5b6000612fe185828601612a96565b925050602083013567ffffffffffffffff81111561300257613001612999565b5b61300e85828601612f8e565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008160060b9050919050565b61305a81613044565b82525050565b600061306c8383613051565b60208301905092915050565b6000602082019050919050565b600061309082613018565b61309a8185613023565b93506130a583613034565b8060005b838110156130d65781516130bd8882613060565b97506130c883613078565b9250506001810190506130a9565b5085935050505092915050565b600060208201905081810360008301526130fd8184613085565b905092915050565b6000806040838503121561311c5761311b612994565b5b600061312a85828601612a96565b925050602061313b858286016129c5565b9150509250929050565b61314e81613044565b82525050565b60006020820190506131696000830184613145565b92915050565b6131788161299e565b82525050565b6000606082019050613193600083018661316f565b6131a06020830185613145565b6131ad6040830184612e76565b949350505050565b6000806000606084860312156131ce576131cd612994565b5b60006131dc868287016129c5565b93505060206131ed86828701612b68565b92505060406131fe86828701612bb0565b9150509250925092565b600060608201905061321d6000830186612eca565b61322a6020830185612a15565b6132376040830184612a15565b949350505050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061328660208361323f565b915061329182613250565b602082019050919050565b600060208201905081810360008301526132b581613279565b9050919050565b600081905092915050565b50565b60006132d76000836132bc565b91506132e2826132c7565b600082019050919050565b60006132f8826132ca565b9150819050919050565b7f6661696c656420746f20636f6c6c656374206e61746976650000000000000000600082015250565b600061333860188361323f565b915061334382613302565b602082019050919050565b600060208201905081810360008301526133678161332b565b9050919050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b60006133ca602e8361323f565b91506133d58261336e565b604082019050919050565b600060208201905081810360008301526133f9816133bd565b9050919050565b61340981612a4d565b811461341457600080fd5b50565b60008151905061342681613400565b92915050565b60008151905061343b81612b51565b92915050565b61344a81612e6a565b811461345557600080fd5b50565b60008151905061346781613441565b92915050565b6000806000806080858703121561348757613486612994565b5b600061349587828801613417565b94505060206134a68782880161342c565b93505060406134b78782880161342c565b92505060606134c887828801613458565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061355f60268361323f565b915061356a82613503565b604082019050919050565b6000602082019050818103600083015261358e81613552565b9050919050565b7f45524331393637557067726164653a207570677261646520627265616b73206660008201527f7572746865722075706772616465730000000000000000000000000000000000602082015250565b60006135f1602f8361323f565b91506135fc82613595565b604082019050919050565b60006020820190508181036000830152613620816135e4565b9050919050565b7f4900000000000000000000000000000000000000000000000000000000000000600082015250565b600061365d60018361323f565b915061366882613627565b602082019050919050565b6000602082019050818103600083015261368c81613650565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006136cd82612a07565b915061ffff8214156136e2576136e1613693565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b61372581612df4565b82525050565b60006040820190506137406000830185612eca565b61374d602083018461371c565b9392505050565b600061375f82612df4565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561379257613791613693565b5b600182019050919050565b7f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60008201527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015250565b60006137f9602d8361323f565b91506138048261379d565b604082019050919050565b60006020820190508181036000830152613828816137ec565b9050919050565b7f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60008201527f6e74726163740000000000000000000000000000000000000000000000000000602082015250565b600061388b60268361323f565b91506138968261382f565b604082019050919050565b600060208201905081810360008301526138ba8161387e565b9050919050565b600081519050919050565b60005b838110156138ea5780820151818401526020810190506138cf565b838111156138f9576000848401525b50505050565b600061390a826138c1565b61391481856132bc565b93506139248185602086016138cc565b80840191505092915050565b600061393c82846138ff565b915081905092915050565b60006020828403121561395d5761395c612994565b5b600061396b84828501613458565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b60006139d0602a8361323f565b91506139db82613974565b604082019050919050565b600060208201905081810360008301526139ff816139c3565b9050919050565b7f4f4c440000000000000000000000000000000000000000000000000000000000600082015250565b6000613a3c60038361323f565b9150613a4782613a06565b602082019050919050565b60006020820190508181036000830152613a6b81613a2f565b9050919050565b600081519050919050565b6000613a8882613a72565b613a92818561323f565b9350613aa28185602086016138cc565b613aab81612c5c565b840191505092915050565b60006020820190508181036000830152613ad08184613a7d565b905092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000613b3460268361323f565b9150613b3f82613ad8565b604082019050919050565b60006020820190508181036000830152613b6381613b27565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000613ba0601d8361323f565b9150613bab82613b6a565b602082019050919050565b60006020820190508181036000830152613bcf81613b93565b905091905056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000809000a
Deployed Bytecode
0x6080604052600436106100e85760003560e01c80638129fc1c1161008a5780639fc40df3116100595780639fc40df3146102d6578063e3e717e914610313578063f2fde38b14610352578063ff11275e1461037b576100e8565b80638129fc1c146102175780638934fade1461022e5780638da5cb5b1461026e5780639ef64c4914610299576100e8565b80634d650b7e116100c65780634d650b7e1461017d5780634f1ef286146101bb5780636e261df1146101d7578063715018a614610200576100e8565b80633440fba7146100ed5780633659cfe61461012b5780634c7a539b14610154575b600080fd5b3480156100f957600080fd5b50610114600480360381019061010f91906129da565b6103b9565b604051610122929190612a24565b60405180910390f35b34801561013757600080fd5b50610152600480360381019061014d9190612aab565b610516565b005b34801561016057600080fd5b5061017b60048036038101906101769190612b04565b61053d565b005b34801561018957600080fd5b506101a4600480360381019061019f9190612bc5565b610697565b6040516101b2929190612a24565b60405180910390f35b6101d560048036038101906101d09190612d98565b6107c6565b005b3480156101e357600080fd5b506101fe60048036038101906101f99190612e2a565b6107df565b005b34801561020c57600080fd5b506102156109e2565b005b34801561022357600080fd5b5061022c610a6a565b005b34801561023a57600080fd5b5061025560048036038101906102509190612aab565b610b4b565b6040516102659493929190612e85565b60405180910390f35b34801561027a57600080fd5b50610283610cab565b6040516102909190612ed9565b60405180910390f35b3480156102a557600080fd5b506102c060048036038101906102bb9190612fbc565b610cd5565b6040516102cd91906130e3565b60405180910390f35b3480156102e257600080fd5b506102fd60048036038101906102f89190613105565b610e65565b60405161030a9190613154565b60405180910390f35b34801561031f57600080fd5b5061033a60048036038101906103359190612e2a565b610ff4565b6040516103499392919061317e565b60405180910390f35b34801561035e57600080fd5b5061037960048036038101906103749190612aab565b6110db565b005b34801561038757600080fd5b506103a2600480360381019061039d91906131b5565b6111d3565b6040516103b0929190612a24565b60405180910390f35b60008061040d8360c960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206112e090919063ffffffff16565b80925081935050506040518060800160405280600115158152602001600061ffff1681526020018361ffff1681526020018261ffff1681525060ca60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548161ffff021916908361ffff16021790555060608201518160000160056101000a81548161ffff021916908361ffff160217905550905050915091565b61051f816113a9565b61053a81604051806020016040528060008152506000611428565b50565b600060ca60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160059054906101000a900461ffff16905060006105e7828460c960008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206115f99092919063ffffffff16565b90508060ca60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160056101000a81548161ffff021916908361ffff1602179055508061ffff168261ffff1614610691577ff0b7b7d1cdf542f5660a7879f0cac17375fdcf984af4a6d499a9daedacb24c5884838360405161068893929190613208565b60405180910390a15b50505050565b60008060003390506106f8898989888860c960008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206116c99095949392919063ffffffff16565b80935081945050508260ca60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160016101000a81548161ffff021916908361ffff1602179055508160ca60008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160036101000a81548161ffff021916908361ffff16021790555050965096945050505050565b6107cf826113a9565b6107db82826001611428565b5050565b6107e7611871565b73ffffffffffffffffffffffffffffffffffffffff16610805610cab565b73ffffffffffffffffffffffffffffffffffffffff161461085b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108529061329c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561094957600061089a610cab565b73ffffffffffffffffffffffffffffffffffffffff16826040516108bd906132ed565b60006040518083038185875af1925050503d80600081146108fa576040519150601f19603f3d011682016040523d82523d6000602084013e6108ff565b606091505b5050905080610943576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093a9061334e565b60405180910390fd5b5061097c565b61097b610954610cab565b828473ffffffffffffffffffffffffffffffffffffffff166118799092919063ffffffff16565b5b808273ffffffffffffffffffffffffffffffffffffffff1661099c610cab565b73ffffffffffffffffffffffffffffffffffffffff167f0c2fa44dc1337dc4fb1c635f4a2a6223e69d8ac9796ca134d0380225d4b1cd0560405160405180910390a45050565b6109ea611871565b73ffffffffffffffffffffffffffffffffffffffff16610a08610cab565b73ffffffffffffffffffffffffffffffffffffffff1614610a5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a559061329c565b60405180910390fd5b610a6860006118ff565b565b600060019054906101000a900460ff1680610a90575060008054906101000a900460ff16155b610acf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ac6906133e0565b60405180910390fd5b60008060019054906101000a900460ff161590508015610b1f576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b610b276119c5565b8015610b485760008060016101000a81548160ff0219169083151502179055505b50565b60008060008060ca60008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff1660ca60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900461ffff1660ca60008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160039054906101000a900461ffff1660ca60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160059054906101000a900461ffff16809450819550829650839750505050509193509193565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060008373ffffffffffffffffffffffffffffffffffffffff1663217ac2376040518163ffffffff1660e01b815260040160806040518083038186803b158015610d1f57600080fd5b505afa158015610d33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d57919061346d565b5050915050610e5c610d67611aae565b848360ca60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900461ffff1660ca60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160039054906101000a900461ffff1660c960008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611ab69095949392919063ffffffff16565b91505092915050565b6000808373ffffffffffffffffffffffffffffffffffffffff1663217ac2376040518163ffffffff1660e01b815260040160806040518083038186803b158015610eae57600080fd5b505afa158015610ec2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee6919061346d565b5050915050610feb610ef6611aae565b848360ca60008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900461ffff1660ca60008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160039054906101000a900461ffff1660c960008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611bc49095949392919063ffffffff16565b91505092915050565b60008060008060c960008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208561ffff811061104c5761104b6134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff1615151515815250509050806000015181602001518260400151809450819550829650505050509250925092565b6110e3611871565b73ffffffffffffffffffffffffffffffffffffffff16611101610cab565b73ffffffffffffffffffffffffffffffffffffffff1614611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114e9061329c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156111c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111be90613575565b60405180910390fd5b6111d0816118ff565b50565b6000806112d460ca60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900461ffff1686868660ca60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160039054906101000a900461ffff1660ca60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160059054906101000a900461ffff16610697565b91509150935093915050565b60008060405180606001604052808463ffffffff168152602001600060060b81526020016001151581525084600061ffff81106113205761131f6134d4565b5b0160008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548166ffffffffffffff021916908360060b66ffffffffffffff160217905550604082015181600001600b6101000a81548160ff021916908315150217905550905050600180915091509250929050565b6113b1611871565b73ffffffffffffffffffffffffffffffffffffffff166113cf610cab565b73ffffffffffffffffffffffffffffffffffffffff1614611425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161141c9061329c565b60405180910390fd5b50565b6000611432611d4e565b905061143d84611da5565b60008351118061144a5750815b1561145b576114598484611e5e565b505b60006114897f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914360001b611f42565b90508060000160009054906101000a900460ff166115f25760018160000160006101000a81548160ff02191690831515021790555061155585836040516024016114d39190612ed9565b6040516020818303038152906040527f3659cfe6000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611e5e565b5060008160000160006101000a81548160ff02191690831515021790555061157b611d4e565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115df90613607565b60405180910390fd5b6115f185611f4c565b5b5050505050565b6000808361ffff1611611641576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161163890613673565b60405180910390fd5b8261ffff168261ffff1611611658578290506116c2565b60008390505b8261ffff168161ffff1610156116bd576001858261ffff1661ffff8110611688576116876134d4565b5b0160000160006101000a81548163ffffffff021916908363ffffffff16021790555080806116b5906136c2565b91505061165e565b508190505b9392505050565b6000806000888861ffff1661ffff81106116e6576116e56134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff16151515158152505090508663ffffffff16816000015163ffffffff1614156117765787859250925050611866565b8461ffff168461ffff1611801561179757506001850361ffff168861ffff16145b156117a4578391506117a8565b8491505b8161ffff166001890161ffff16816117c3576117c26136ed565b5b0692506117d1818888611f9b565b898461ffff1661ffff81106117e9576117e86134d4565b5b0160008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548166ffffffffffffff021916908360060b66ffffffffffffff160217905550604082015181600001600b6101000a81548160ff021916908315150217905550905050505b965096945050505050565b600033905090565b6118fa8363a9059cbb60e01b848460405160240161189892919061372b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611fed565b505050565b6000609760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081609760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600060019054906101000a900460ff16806119eb575060008054906101000a900460ff16155b611a2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a21906133e0565b60405180910390fd5b60008060019054906101000a900460ff161590508015611a7a576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b611a826120b4565b611a8a61218d565b8015611aab5760008060016101000a81548160ff0219169083151502179055505b50565b600042905090565b606060008261ffff1611611aff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611af690613673565b60405180910390fd5b845167ffffffffffffffff811115611b1a57611b19612c6d565b5b604051908082528060200260200182016040528015611b485781602001602082028036833780820191505090505b50905060005b8551811015611bb957611b7f8888888481518110611b6f57611b6e6134d4565b5b6020026020010151888888611bc4565b828281518110611b9257611b916134d4565b5b602002602001019060060b908160060b815250508080611bb190613754565b915050611b4e565b509695505050505050565b6000808563ffffffff161415611c8c576000878461ffff1661ffff8110611bee57611bed6134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff16151515158152505090508663ffffffff16816000015163ffffffff1614611c7f57611c7c818887611f9b565b90505b8060200151915050611d44565b60008587039050600080611ca48a8a858a8a8a612276565b91509150816000015163ffffffff168363ffffffff161415611ccf5781602001519350505050611d44565b806000015163ffffffff168363ffffffff161415611cf65780602001519350505050611d44565b60008260000151826000015103905060008360000151850390508060030b8260030b856020015185602001510360060b81611d3457611d336136ed565b5b0502846020015101955050505050505b9695505050505050565b6000611d7c7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6124e5565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b611dae816124ef565b611ded576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de49061380f565b60405180910390fd5b80611e1a7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6124e5565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6060611e69836124ef565b611ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9f906138a1565b60405180910390fd5b6000808473ffffffffffffffffffffffffffffffffffffffff1684604051611ed09190613930565b600060405180830381855af49150503d8060008114611f0b576040519150601f19603f3d011682016040523d82523d6000602084013e611f10565b606091505b5091509150611f388282604051806060016040528060278152602001613bd760279139612502565b9250505092915050565b6000819050919050565b611f5581611da5565b8073ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a250565b611fa361295e565b600084600001518403905060405180606001604052808563ffffffff1681526020018260030b8560020b0287602001510160060b8152602001600115158152509150509392505050565b600061204f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125699092919063ffffffff16565b90506000815111156120af578080602001905181019061206f9190613947565b6120ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120a5906139e6565b60405180910390fd5b5b505050565b600060019054906101000a900460ff16806120da575060008054906101000a900460ff16155b612119576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612110906133e0565b60405180910390fd5b60008060019054906101000a900460ff161590508015612169576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b801561218a5760008060016101000a81548160ff0219169083151502179055505b50565b600060019054906101000a900460ff16806121b3575060008054906101000a900460ff16155b6121f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e9906133e0565b60405180910390fd5b60008060019054906101000a900460ff161590508015612242576001600060016101000a81548160ff02191690831515021790555060016000806101000a81548160ff0219169083151502179055505b61225261224d611871565b6118ff565b80156122735760008060016101000a81548160ff0219169083151502179055505b50565b61227e61295e565b61228661295e565b878461ffff1661ffff811061229e5761229d6134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff161515151581525050915061231987836000015188612581565b15612350578563ffffffff16826000015163ffffffff16141561233b576124da565b81612347838888611f9b565b915091506124da565b878361ffff166001860161ffff168161236c5761236b6136ed565b5b0661ffff1661ffff8110612383576123826134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff1615151515815250509150816040015161247a5787600061ffff811061240d5761240c6134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff16151515158152505091505b61248987836000015188612581565b6124c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124bf90613a52565b60405180910390fd5b6124d58888888787612649565b915091505b965096945050505050565b6000819050919050565b600080823b905060008111915050919050565b6060831561251257829050612562565b6000835111156125255782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125599190613ab6565b60405180910390fd5b9392505050565b6060612578848460008561284a565b90509392505050565b60008363ffffffff168363ffffffff16111580156125ab57508363ffffffff168263ffffffff1611155b156125c7578163ffffffff168363ffffffff1611159050612642565b60008463ffffffff168463ffffffff16116125ef576401000000008463ffffffff16016125f7565b8363ffffffff165b64ffffffffff16905060008563ffffffff168463ffffffff1611612628576401000000008463ffffffff1601612630565b8363ffffffff165b64ffffffffff16905080821115925050505b9392505050565b61265161295e565b61265961295e565b60008361ffff166001860161ffff1681612676576126756136ed565b5b0661ffff169050600060018561ffff16830103905060005b60011561283d576002828401816126a8576126a76136ed565b5b049050898661ffff1682816126c0576126bf6136ed565b5b0661ffff81106126d3576126d26134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff161515151581525050945084604001516127535760018101925061268e565b898661ffff16600183018161276b5761276a6136ed565b5b0661ffff811061277e5761277d6134d4565b5b016040518060600160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900460060b60060b60060b815260200160008201600b9054906101000a900460ff161515151581525050935060006127fb8a87600001518b612581565b905080801561281557506128148a8a8760000151612581565b5b15612820575061283d565b8061283057600182039250612837565b6001820193505b5061268e565b5050509550959350505050565b60608247101561288f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161288690613b4a565b60405180910390fd5b612898856124ef565b6128d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128ce90613bb6565b60405180910390fd5b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516129009190613930565b60006040518083038185875af1925050503d806000811461293d576040519150601f19603f3d011682016040523d82523d6000602084013e612942565b606091505b5091509150612952828286612502565b92505050949350505050565b6040518060600160405280600063ffffffff168152602001600060060b81526020016000151581525090565b6000604051905090565b600080fd5b600080fd5b600063ffffffff82169050919050565b6129b78161299e565b81146129c257600080fd5b50565b6000813590506129d4816129ae565b92915050565b6000602082840312156129f0576129ef612994565b5b60006129fe848285016129c5565b91505092915050565b600061ffff82169050919050565b612a1e81612a07565b82525050565b6000604082019050612a396000830185612a15565b612a466020830184612a15565b9392505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612a7882612a4d565b9050919050565b612a8881612a6d565b8114612a9357600080fd5b50565b600081359050612aa581612a7f565b92915050565b600060208284031215612ac157612ac0612994565b5b6000612acf84828501612a96565b91505092915050565b612ae181612a07565b8114612aec57600080fd5b50565b600081359050612afe81612ad8565b92915050565b60008060408385031215612b1b57612b1a612994565b5b6000612b2985828601612a96565b9250506020612b3a85828601612aef565b9150509250929050565b60008160020b9050919050565b612b5a81612b44565b8114612b6557600080fd5b50565b600081359050612b7781612b51565b92915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b612ba281612b7d565b8114612bad57600080fd5b50565b600081359050612bbf81612b99565b92915050565b60008060008060008060c08789031215612be257612be1612994565b5b6000612bf089828a01612aef565b9650506020612c0189828a016129c5565b9550506040612c1289828a01612b68565b9450506060612c2389828a01612bb0565b9350506080612c3489828a01612aef565b92505060a0612c4589828a01612aef565b9150509295509295509295565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612ca582612c5c565b810181811067ffffffffffffffff82111715612cc457612cc3612c6d565b5b80604052505050565b6000612cd761298a565b9050612ce38282612c9c565b919050565b600067ffffffffffffffff821115612d0357612d02612c6d565b5b612d0c82612c5c565b9050602081019050919050565b82818337600083830152505050565b6000612d3b612d3684612ce8565b612ccd565b905082815260208101848484011115612d5757612d56612c57565b5b612d62848285612d19565b509392505050565b600082601f830112612d7f57612d7e612c52565b5b8135612d8f848260208601612d28565b91505092915050565b60008060408385031215612daf57612dae612994565b5b6000612dbd85828601612a96565b925050602083013567ffffffffffffffff811115612dde57612ddd612999565b5b612dea85828601612d6a565b9150509250929050565b6000819050919050565b612e0781612df4565b8114612e1257600080fd5b50565b600081359050612e2481612dfe565b92915050565b60008060408385031215612e4157612e40612994565b5b6000612e4f85828601612a96565b9250506020612e6085828601612e15565b9150509250929050565b60008115159050919050565b612e7f81612e6a565b82525050565b6000608082019050612e9a6000830187612e76565b612ea76020830186612a15565b612eb46040830185612a15565b612ec16060830184612a15565b95945050505050565b612ed381612a6d565b82525050565b6000602082019050612eee6000830184612eca565b92915050565b600067ffffffffffffffff821115612f0f57612f0e612c6d565b5b602082029050602081019050919050565b600080fd5b6000612f38612f3384612ef4565b612ccd565b90508083825260208201905060208402830185811115612f5b57612f5a612f20565b5b835b81811015612f845780612f7088826129c5565b845260208401935050602081019050612f5d565b5050509392505050565b600082601f830112612fa357612fa2612c52565b5b8135612fb3848260208601612f25565b91505092915050565b60008060408385031215612fd357612fd2612994565b5b6000612fe185828601612a96565b925050602083013567ffffffffffffffff81111561300257613001612999565b5b61300e85828601612f8e565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60008160060b9050919050565b61305a81613044565b82525050565b600061306c8383613051565b60208301905092915050565b6000602082019050919050565b600061309082613018565b61309a8185613023565b93506130a583613034565b8060005b838110156130d65781516130bd8882613060565b97506130c883613078565b9250506001810190506130a9565b5085935050505092915050565b600060208201905081810360008301526130fd8184613085565b905092915050565b6000806040838503121561311c5761311b612994565b5b600061312a85828601612a96565b925050602061313b858286016129c5565b9150509250929050565b61314e81613044565b82525050565b60006020820190506131696000830184613145565b92915050565b6131788161299e565b82525050565b6000606082019050613193600083018661316f565b6131a06020830185613145565b6131ad6040830184612e76565b949350505050565b6000806000606084860312156131ce576131cd612994565b5b60006131dc868287016129c5565b93505060206131ed86828701612b68565b92505060406131fe86828701612bb0565b9150509250925092565b600060608201905061321d6000830186612eca565b61322a6020830185612a15565b6132376040830184612a15565b949350505050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061328660208361323f565b915061329182613250565b602082019050919050565b600060208201905081810360008301526132b581613279565b9050919050565b600081905092915050565b50565b60006132d76000836132bc565b91506132e2826132c7565b600082019050919050565b60006132f8826132ca565b9150819050919050565b7f6661696c656420746f20636f6c6c656374206e61746976650000000000000000600082015250565b600061333860188361323f565b915061334382613302565b602082019050919050565b600060208201905081810360008301526133678161332b565b9050919050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b60006133ca602e8361323f565b91506133d58261336e565b604082019050919050565b600060208201905081810360008301526133f9816133bd565b9050919050565b61340981612a4d565b811461341457600080fd5b50565b60008151905061342681613400565b92915050565b60008151905061343b81612b51565b92915050565b61344a81612e6a565b811461345557600080fd5b50565b60008151905061346781613441565b92915050565b6000806000806080858703121561348757613486612994565b5b600061349587828801613417565b94505060206134a68782880161342c565b93505060406134b78782880161342c565b92505060606134c887828801613458565b91505092959194509250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061355f60268361323f565b915061356a82613503565b604082019050919050565b6000602082019050818103600083015261358e81613552565b9050919050565b7f45524331393637557067726164653a207570677261646520627265616b73206660008201527f7572746865722075706772616465730000000000000000000000000000000000602082015250565b60006135f1602f8361323f565b91506135fc82613595565b604082019050919050565b60006020820190508181036000830152613620816135e4565b9050919050565b7f4900000000000000000000000000000000000000000000000000000000000000600082015250565b600061365d60018361323f565b915061366882613627565b602082019050919050565b6000602082019050818103600083015261368c81613650565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006136cd82612a07565b915061ffff8214156136e2576136e1613693565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b61372581612df4565b82525050565b60006040820190506137406000830185612eca565b61374d602083018461371c565b9392505050565b600061375f82612df4565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561379257613791613693565b5b600182019050919050565b7f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60008201527f6f74206120636f6e747261637400000000000000000000000000000000000000602082015250565b60006137f9602d8361323f565b91506138048261379d565b604082019050919050565b60006020820190508181036000830152613828816137ec565b9050919050565b7f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60008201527f6e74726163740000000000000000000000000000000000000000000000000000602082015250565b600061388b60268361323f565b91506138968261382f565b604082019050919050565b600060208201905081810360008301526138ba8161387e565b9050919050565b600081519050919050565b60005b838110156138ea5780820151818401526020810190506138cf565b838111156138f9576000848401525b50505050565b600061390a826138c1565b61391481856132bc565b93506139248185602086016138cc565b80840191505092915050565b600061393c82846138ff565b915081905092915050565b60006020828403121561395d5761395c612994565b5b600061396b84828501613458565b91505092915050565b7f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201527f6f74207375636365656400000000000000000000000000000000000000000000602082015250565b60006139d0602a8361323f565b91506139db82613974565b604082019050919050565b600060208201905081810360008301526139ff816139c3565b9050919050565b7f4f4c440000000000000000000000000000000000000000000000000000000000600082015250565b6000613a3c60038361323f565b9150613a4782613a06565b602082019050919050565b60006020820190508181036000830152613a6b81613a2f565b9050919050565b600081519050919050565b6000613a8882613a72565b613a92818561323f565b9350613aa28185602086016138cc565b613aab81612c5c565b840191505092915050565b60006020820190508181036000830152613ad08184613a7d565b905092915050565b7f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201527f722063616c6c0000000000000000000000000000000000000000000000000000602082015250565b6000613b3460268361323f565b9150613b3f82613ad8565b604082019050919050565b60006020820190508181036000830152613b6381613b27565b9050919050565b7f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000600082015250565b6000613ba0601d8361323f565b9150613bab82613b6a565b602082019050919050565b60006020820190508181036000830152613bcf81613b93565b905091905056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000809000a
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.