Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
MintFeeOracle
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 1 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "./interfaces/IMintFeeOracle.sol";
import "./interfaces/IAbridgedMintVector.sol";
import "./mechanics/interfaces/IMechanicMintManagerView.sol";
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "../utils/FullMath.sol";
import "../utils/IUniswapV3PoolState.sol";
import "./referrals/IReferralManagerView.sol";
/**
* @title MintManager's mint fee oracle
* @author highlight.xyz
*/
contract MintFeeOracle is UUPSUpgradeable, OwnableUpgradeable {
/**
* @notice Throw when an action is unauthorized
*/
error Unauthorized();
/**
* @notice Throw when an ERC20 is invalid
*/
error InvalidERC20();
/**
* @notice Throw when an ERC20 config is invalid
*/
error InvalidERC20Config();
/**
* @notice Throw when caller is not the MintManager
*/
error NotMintManager();
/**
* @notice Throw when an invalid ether value is sent in when processing an ether mint fee cap
*/
error InvalidEtherMintFeeCap();
/**
* @notice Throw when sending ether fails
*/
error EtherSendFailed();
/**
* @notice Throw when a mint vector's expected type is false
*/
error InvalidVectorType();
/**
* @notice Throw when resolved referrer is invalid
*/
error InvalidReferrer();
/**
* @notice Config for allowlisted ERC20s
* @param baseMintFee Base fee fee amount per token (if price isn't real-time)
* @param realTimeOracle Address of real time oracle to query if price is real-time
*/
struct ERC20Config {
uint96 baseMintFee;
address realTimeOracle;
}
/**
* @notice MintManager
*/
address private _mintManager;
/**
* @notice Mint fee subsidized config (vector + user)
*/
mapping(bytes32 => bool) private _subsidizedMintConfig;
/**
* @notice Gasless mechanic address
*/
address private _gaslessMechanicAddress;
/**
* @notice Allowlisted ERC20s -> mint fee
*/
mapping(address => ERC20Config) private _allowlistedERC20s;
/**
* @notice When true, creator rewards is enabled
*/
bool private _creatorRewardsEnabled;
/**
* @notice Constants for uniswap price calculation
*/
uint256 public constant ETH_WEI = 10 ** 18;
uint256 public constant FULL_MATH_SHIFT = 1 << 192;
/**
* @notice Backup referral manager
*/
address private _backupReferralManager;
/**
* @notice Backup referral manager
*/
address private _backupDiscreteDutchAuctionMechanic;
/**
* @notice Backup referral manager
*/
address private _backupRankedAuctionMechanic;
/**
* @notice Emitted when a referrer is paid out a portion of the mint fee
* @param vectorId Vector ID
* @param referrer Referrer
* @param currency Currency
* @param referralPayout Amount paid out to referrer
*/
event ReferralPayout(
bytes32 indexed vectorId,
address indexed referrer,
address indexed currency,
uint256 referralPayout
);
/**
* @notice Only let the mint manager call
*/
modifier onlyMintManager() {
if (msg.sender != _mintManager) {
_revert(NotMintManager.selector);
}
_;
}
/* solhint-disable no-empty-blocks */
/**
* @notice Initialize contract
*/
function initialize(
address mintManager,
address platform,
address gaslessMechanic,
address backupReferralManager,
address backupDiscreteDutchAuctionMechanic,
address backupRankedAuctionMechanic
) external initializer {
__Ownable_init();
_transferOwnership(platform);
_mintManager = mintManager;
_gaslessMechanicAddress = gaslessMechanic;
_backupReferralManager = backupReferralManager;
_backupDiscreteDutchAuctionMechanic = backupDiscreteDutchAuctionMechanic;
_backupRankedAuctionMechanic = backupRankedAuctionMechanic;
}
/**
* @notice Set an allowlisted erc20 config
* @param erc20 ERC20 address
* @param config ERC20 config
*/
function setAllowlistedERC20Config(address erc20, ERC20Config calldata config) external onlyOwner {
if (
!(config.baseMintFee != 0 && config.realTimeOracle == address(0)) &&
!(config.baseMintFee == 0 && config.realTimeOracle != address(0))
) {
_revert(InvalidERC20Config.selector);
}
_allowlistedERC20s[erc20] = config;
}
/**
* @notice Delist an allowlisted erc20 config
* @param erc20 ERC20 address
*/
function delistERC20(address erc20) external onlyOwner {
delete _allowlistedERC20s[erc20];
}
/**
* @notice Set mint manager
*/
function setMintManager(address newMintManager) external onlyOwner {
_mintManager = newMintManager;
}
/**
* @notice Set backup referral manager
*/
function setBackupReferralManager(address newBackupReferralManager) external onlyOwner {
_backupReferralManager = newBackupReferralManager;
}
/**
* @notice Set backup discrete dutch auction mechanic
*/
function setBackupDiscreteDutchAuctionMechanic(address newBackupDiscreteDutchAuctionMechanic) external onlyOwner {
_backupDiscreteDutchAuctionMechanic = newBackupDiscreteDutchAuctionMechanic;
}
/**
* @notice Set backup ranked auction mechanic
*/
function setBackupRankedAuctionMechanic(address newBackupRankedAuctionMechanic) external onlyOwner {
_backupRankedAuctionMechanic = newBackupRankedAuctionMechanic;
}
/**
* @notice Set gasless mechanic
*/
function setGaslessMechanic(address newGaslessMechanic) external onlyOwner {
_gaslessMechanicAddress = newGaslessMechanic;
}
/**
* @notice Set creator rewards enabled
*/
function setCreatorRewardsEnabled(bool creatorRewardsEnabled) external onlyOwner {
_creatorRewardsEnabled = creatorRewardsEnabled;
}
/**
* @notice Subsidize mint fee for a mint config (vector + sender)
*/
function subsidizeMintConfig(bytes32 vectorId, address minter) external onlyOwner {
bytes32 mintConfig = _encodeMintConfig(vectorId, minter);
require(!_subsidizedMintConfig[mintConfig], "Already subsidized");
_subsidizedMintConfig[mintConfig] = true;
}
/**
* @notice Subsidize mint fee for a mint config (vector + sender)
*/
function unsubsidizeMintVector(bytes32 vectorId, address minter) external onlyOwner {
bytes32 mintConfig = _encodeMintConfig(vectorId, minter);
require(_subsidizedMintConfig[mintConfig], "Not already subsidized");
_subsidizedMintConfig[mintConfig] = false;
}
/**
* @notice Withdraw native gas token owed to platform
*/
function withdrawNativeGasToken(uint256 amountToWithdraw, address payable recipient) external onlyOwner {
(bool sentToPlatform, ) = recipient.call{ value: amountToWithdraw }("");
if (!sentToPlatform) {
_revert(EtherSendFailed.selector);
}
}
/**
* @notice Withdraw ERC20 owed to platform
*/
function withdrawERC20(address currency, uint256 amountToWithdraw, address recipient) external onlyOwner {
IERC20(currency).transfer(recipient, amountToWithdraw);
}
/* solhint-disable code-complexity */
/**
* @notice See {IMintFeeOracle-processClassicVectorMintFeeCap}
*/
function processClassicVectorMintFeeCap(
bytes32 vectorId,
bool payoutCreatorReward,
address vectorPaymentRecipient,
address currency,
uint256 amount,
address minter
) external payable onlyMintManager returns (uint256) {
if (currency == address(0)) {
if (msg.value != amount) {
_revert(InvalidEtherMintFeeCap.selector);
}
}
address referralManager = _referralManager();
if (referralManager == minter) {
uint256 referralPayout = (amount * 10) / 100;
// get referrer via referral manager
address referrer = IReferralManagerView(referralManager).getCurrentReferrer(vectorId);
// only send referral if minter wasn't referrer and if referrer wasn't zero address
if (referrer != address(0) && referrer != tx.origin) {
if (currency == address(0)) {
(bool sentToRecipient, ) = payable(referrer).call{ value: referralPayout }("");
if (!sentToRecipient) {
_revert(EtherSendFailed.selector);
}
} else {
IERC20(currency).transfer(referrer, referralPayout);
}
emit ReferralPayout(vectorId, referrer, currency, referralPayout);
}
}
if (payoutCreatorReward) {
uint256 creatorPayout = amount / 2;
if (currency == address(0)) {
(bool sentToRecipient, ) = vectorPaymentRecipient.call{ value: creatorPayout }("");
if (!sentToRecipient) {
_revert(EtherSendFailed.selector);
}
} else {
IERC20(currency).transfer(vectorPaymentRecipient, creatorPayout);
}
return creatorPayout;
}
return 0;
}
/* solhint-enable code-complexity */
/**
* @notice See {IMintFeeOracle-getClassicVectorMintFeeCap}
*/
function getClassicVectorMintFeeCap(
bytes32 vectorId,
uint256 numToMint,
address minter,
address currency
) external view returns (uint256) {
if (_isFeeSubsidized(vectorId, minter)) {
return 0;
}
if (currency == address(0)) {
return (block.chainid == 137 ? 2265000000000000000 : 800000000000000) * numToMint;
} else {
return _getClassicVectorERC20MintFeeCap(currency, numToMint);
}
}
/**
* @notice See {IMintFeeOracle-getMechanicMintFee}
*/
function getMechanicMintFee(
bytes32 mechanicVectorId,
uint32 numToMint,
address mechanic,
address minter
) external view returns (uint256) {
if (_isMintFeeWaivedMechanic(mechanic) || _isFeeSubsidized(mechanicVectorId, minter)) {
return 0;
} else {
return (block.chainid == 137 ? 2265000000000000000 : 800000000000000) * uint256(numToMint);
}
}
/**
* @notice Get public vector mint fee (optimized for offchain querying)
*/
function getPublicVectorMintFee(
uint256 vectorId,
uint256 numToMint,
address minter
) external view returns (uint256, address) {
if (_isFeeSubsidized(bytes32(vectorId), minter)) {
return (0, address(0));
}
IAbridgedMintVector.AbridgedVector memory _vector = IAbridgedMintVector(_mintManager).getAbridgedVector(
vectorId
);
if (_vector.contractAddress == address(0)) {
_revert(InvalidVectorType.selector);
}
if (_vector.currency != address(0)) {
return (_getClassicVectorERC20MintFeeCap(_vector.currency, numToMint), _vector.currency);
} else {
return ((block.chainid == 137 ? 2265000000000000000 : 800000000000000) * uint256(numToMint), address(0));
}
}
/**
* @notice Get gated vector mint fee (optimized for offchain querying)
*/
function getGatedVectorMintFee(
bytes32 vectorId,
uint256 numToMint,
address minter,
address currency
) external view returns (uint256, address) {
if (_isFeeSubsidized(vectorId, minter)) {
return (0, currency);
}
if (currency != address(0)) {
return (_getClassicVectorERC20MintFeeCap(currency, numToMint), currency);
}
return ((block.chainid == 137 ? 2265000000000000000 : 800000000000000) * uint256(numToMint), address(0));
}
/**
* @notice Get mechanic vector mint fee (optimized for offchain querying)
*/
function getMechanicVectorMintFee(
bytes32 vectorId,
uint256 numToMint,
address minter
) external view returns (uint256, address) {
IMechanicData.MechanicVectorMetadata memory _mechanicMetadata = IMechanicMintManagerView(_mintManager)
.mechanicVectorMetadata(vectorId);
if (_mechanicMetadata.contractAddress == address(0)) {
_revert(InvalidVectorType.selector);
}
if (_isMintFeeWaivedMechanic(_mechanicMetadata.mechanic) || _isFeeSubsidized(vectorId, minter)) {
return (0, address(0));
}
return ((block.chainid == 137 ? 2265000000000000000 : 800000000000000) * uint256(numToMint), address(0));
}
/**
* @notice Limit upgrades of contract to MintFeeOracle owner
* @param // New implementation address
*/
function _authorizeUpgrade(address) internal override onlyOwner {}
/**
* @dev For more efficient reverts.
*/
function _revert(bytes4 errorSelector) internal pure {
assembly {
mstore(0x00, errorSelector)
revert(0x00, 0x04)
}
}
/**
* @notice Return if mint fee is subsidized for a mint config
* @param vectorId ID of vector
* @param minter Original minter address
*/
function _isFeeSubsidized(bytes32 vectorId, address minter) private view returns (bool) {
return _subsidizedMintConfig[_encodeMintConfig(vectorId, minter)];
}
/**
* @notice Encode a mint config
* @param vectorId ID of vector
* @param minter Original minter address
*/
function _encodeMintConfig(bytes32 vectorId, address minter) private pure returns (bytes32) {
return keccak256(abi.encodePacked(vectorId, minter));
}
function _getClassicVectorERC20MintFeeCap(address currency, uint256 numToMint) private view returns (uint256) {
ERC20Config memory config = _allowlistedERC20s[currency];
if (config.baseMintFee != 0) {
return config.baseMintFee * numToMint;
} else if (config.realTimeOracle != address(0)) {
(uint160 sqrtPriceX96, , , , , , ) = IUniswapV3PoolState(config.realTimeOracle).slot0();
return
(block.chainid == 137 ? 2265000000000000000 : 800000000000000) *
sqrtPriceX96ToUint(sqrtPriceX96) *
numToMint;
} else {
_revert(InvalidERC20.selector);
}
}
/* solhint-disable code-complexity */
function _isMintFeeWaivedMechanic(address mechanic) private view returns (bool) {
// RAM, DDAM
// TODO: add gasless mechanic
if (block.chainid == 1) {
return
mechanic == 0xDFEe0Ed4A217F37b3FA87624eE00fe5685bDc509 ||
mechanic == 0x94Fa6e7Fc2555aDA63eA56cfFF425558360F0074;
} else if (block.chainid == 8453) {
return
mechanic == 0x922E9f8cc491fACBd403afa143AA53ee9146474C ||
mechanic == 0xA748BE280C9a00edaF7d04076FE8A93c59e95B03;
} else if (block.chainid == 10) {
return
mechanic == 0xb207774Ac4E32eCE47771e64BDE5ec3894C1De6b ||
mechanic == 0x15753e20667961fB30d5aa92e2255B876568BE7e;
} else if (block.chainid == 42161) {
return
mechanic == 0x7f75358787f880506c5dc6100386F77be8DE0A30 ||
mechanic == 0x3a2aFe86E594540cbf3eA345dd29e09228f186D2;
} else if (block.chainid == 7777777) {
return
mechanic == 0x0AFB6566C836D1C4788cD2b54Bd9cA0158CC2D3D ||
mechanic == 0xf12A4018647DD2275072967Fd5F3ac5Fef7a0471;
} else if (block.chainid == 137) {
return
mechanic == 0x4CCB72E7E0Cd948aF50bC7Bf598Fc4E027b70f98 ||
mechanic == 0xAE22Cd8052D64e7C2aF6B5E3045Fab0a86C8334C;
} else if (block.chainid == 11155111) {
return
mechanic == 0xa2D14CA9985De170db128c8CB74Cecb35eEAF47E ||
mechanic == 0xceBc3B3134FbEF95ED13AEcdF997D4371d022385;
} else if (block.chainid == 84532) {
return
mechanic == 0x9958F83F383CA150BB2252B4275D3e3051be469F ||
mechanic == 0x4821B6e9aC0CCC590acCe2442bb6BB32388C1CB7;
}
return
mechanic == _backupDiscreteDutchAuctionMechanic ||
mechanic == _backupRankedAuctionMechanic ||
mechanic == _gaslessMechanicAddress;
}
/**
* @notice Get the referral manager
*/
function _referralManager() private view returns (address) {
if (block.chainid == 1) {
return 0xD3C63951b2Ed18e8d92B5b251C3B636A45A547d0;
} else if (block.chainid == 8453) {
return 0xd9E58978808d17F99ccCEAb5195B052E972c0188;
} else if (block.chainid == 10) {
return 0x9CF5B12D2e2a88083647Ff2Fe0610F818b28eC77;
} else if (block.chainid == 7777777) {
return 0x7Cb2cecFCFFdccE0bf69366e52caec6BD719CD44;
} else if (block.chainid == 42161) {
return 0x617b2383D93909590fAC0b2aaa547EC5615d82eF;
} else if (block.chainid == 137) {
return 0x6fd07d4B5fd7093762Fb2f278769aa7e2511d45c;
} else if (block.chainid == 84532) {
return 0x4619b9673241eB41B642Dc04371100d238b73fFE;
} else if (block.chainid == 11155111) {
return 0xd33c1bE264bb98F86e18CD816D5fd44e97cb7163;
} else {
return _backupReferralManager;
}
}
/**
* @notice Convert uniswap sqrtX96 price
* @dev token0 always assumed to be ETH
*/
function sqrtPriceX96ToUint(uint160 sqrtPriceX96) private pure returns (uint256) {
return FullMath.mulDiv(uint256(sqrtPriceX96) * uint256(sqrtPriceX96), ETH_WEI, FULL_MATH_SHIFT);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/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.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
interface IERC1967 {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/IERC1967.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967Upgrade is IERC1967 {
// 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 Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822.sol";
import "../ERC1967/ERC1967Upgrade.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 IERC1822Proxiable, ERC1967Upgrade {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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);
/**
* @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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/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.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
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:
* ```solidity
* 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`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
/**
* @title MintManager interface for onchain abridged mint vectors
* @author highlight.xyz
*/
interface IAbridgedMintVector {
/**
* @notice On-chain mint vector (stored data)
* @param contractAddress NFT smart contract address
* @param startTimestamp When minting opens on vector
* @param endTimestamp When minting ends on vector
* @param paymentRecipient Payment recipient
* @param maxTotalClaimableViaVector Max number of tokens that can be minted via vector
* @param totalClaimedViaVector Total number of tokens minted via vector
* @param currency Currency used for payment. Native gas token, if zero address
* @param tokenLimitPerTx Max number of tokens that can be minted in one transaction
* @param maxUserClaimableViaVector Max number of tokens that can be minted by user via vector
* @param pricePerToken Price that has to be paid per minted token
* @param editionId Edition ID, if vector is for edition based collection
* @param editionBasedCollection If vector is for an edition based collection
* @param requireDirectEOA Require minters to directly be EOAs
* @param allowlistRoot Root of merkle tree with allowlist
*/
struct AbridgedVectorData {
uint160 contractAddress;
uint48 startTimestamp;
uint48 endTimestamp;
uint160 paymentRecipient;
uint48 maxTotalClaimableViaVector;
uint48 totalClaimedViaVector;
uint160 currency;
uint48 tokenLimitPerTx;
uint48 maxUserClaimableViaVector;
uint192 pricePerToken;
uint48 editionId;
bool editionBasedCollection;
bool requireDirectEOA;
bytes32 allowlistRoot;
}
/**
* @notice On-chain mint vector (public) - See {AbridgedVectorData}
*/
struct AbridgedVector {
address contractAddress;
uint48 startTimestamp;
uint48 endTimestamp;
address paymentRecipient;
uint48 maxTotalClaimableViaVector;
uint48 totalClaimedViaVector;
address currency;
uint48 tokenLimitPerTx;
uint48 maxUserClaimableViaVector;
uint192 pricePerToken;
uint48 editionId;
bool editionBasedCollection;
bool requireDirectEOA;
bytes32 allowlistRoot;
}
/**
* @notice Config defining what fields to update
* @param updateStartTimestamp If 1, update startTimestamp
* @param updateEndTimestamp If 1, update endTimestamp
* @param updatePaymentRecipient If 1, update paymentRecipient
* @param updateMaxTotalClaimableViaVector If 1, update maxTotalClaimableViaVector
* @param updateTokenLimitPerTx If 1, update tokenLimitPerTx
* @param updateMaxUserClaimableViaVector If 1, update maxUserClaimableViaVector
* @param updatePricePerToken If 1, update pricePerToken
* @param updateCurrency If 1, update currency
* @param updateRequireDirectEOA If 1, update requireDirectEOA
* @param updateMetadata If 1, update MintVector metadata
*/
struct UpdateAbridgedVectorConfig {
uint16 updateStartTimestamp;
uint16 updateEndTimestamp;
uint16 updatePaymentRecipient;
uint16 updateMaxTotalClaimableViaVector;
uint16 updateTokenLimitPerTx;
uint16 updateMaxUserClaimableViaVector;
uint8 updatePricePerToken;
uint8 updateCurrency;
uint8 updateRequireDirectEOA;
uint8 updateMetadata;
}
/**
* @notice Creates on-chain vector
* @param _vector Vector to create
*/
function createAbridgedVector(AbridgedVectorData memory _vector) external;
/**
* @notice Updates on-chain vector
* @param vectorId ID of vector to update
* @param _newVector New vector details
* @param updateConfig Number encoding what fields to update
* @param pause Pause / unpause vector
* @param flexibleData Flexible data in vector metadata
*/
function updateAbridgedVector(
uint256 vectorId,
AbridgedVector calldata _newVector,
UpdateAbridgedVectorConfig calldata updateConfig,
bool pause,
uint128 flexibleData
) external;
/**
* @notice Pauses or unpauses an on-chain mint vector
* @param vectorId ID of abridged vector to pause
* @param pause True to pause, False to unpause
* @param flexibleData Flexible data that can be interpreted differently
*/
function setAbridgedVectorMetadata(uint256 vectorId, bool pause, uint128 flexibleData) external;
/**
* @notice Get on-chain abridged vector
* @param vectorId ID of abridged vector to get
*/
function getAbridgedVector(uint256 vectorId) external view returns (AbridgedVector memory);
/**
* @notice Get on-chain abridged vector metadata
* @param vectorId ID of abridged vector to get
*/
function getAbridgedVectorMetadata(uint256 vectorId) external view returns (bool, uint128);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
/**
* @title MintManager interface for a mint fee oracle
* @author highlight.xyz
*/
interface IMintFeeOracle {
/**
* @notice Process the mint fee for a classic mv
* @param vectorId Vector ID
* @param payoutCreatorReward Payout creator reward
* @param vectorPaymentRecipient Vector payment recipient
* @param currency Mint fee currency currency
* @param amount Sale amount
* @param minter Minter address
*/
function processClassicVectorMintFeeCap(
bytes32 vectorId,
bool payoutCreatorReward,
address vectorPaymentRecipient,
address currency,
uint256 amount,
address minter
) external payable returns (uint256);
/**
* @notice Get the mint fee cap for a classic mv
* @param vectorId Vector ID (bytes32)
* @param numToMint Number of tokens to mint in this transaction
* @param minter Minter address
* @param currency Sale currency
*/
function getClassicVectorMintFeeCap(
bytes32 vectorId,
uint256 numToMint,
address minter,
address currency
) external view returns (uint256);
/**
* @notice Get the mint fee for a mechanic mint mv
* @param vectorId Vector ID
* @param numToMint Number of tokens to mint in this transaction
* @param mechanic Address of mechanic facilitating mint
* @param minter Address minting
*/
function getMechanicMintFee(
bytes32 vectorId,
uint32 numToMint,
address mechanic,
address minter
) external view returns (uint256);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
/**
* @notice Defines a mechanic's metadata on the MintManager
*/
interface IMechanicData {
/**
* @notice A mechanic's metadata
* @param contractAddress Collection contract address
* @param editionId Edition ID if the collection is edition based
* @param mechanic Address of mint mechanic contract
* @param isEditionBased True if collection is edition based
* @param isChoose True if collection uses a collector's choice mint paradigm
* @param paused True if mechanic vector is paused
*/
struct MechanicVectorMetadata {
address contractAddress;
uint96 editionId;
address mechanic;
bool isEditionBased;
bool isChoose;
bool paused;
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
import "./IMechanicData.sol";
interface IMechanicMintManagerView is IMechanicData {
/**
* @notice Get a mechanic vector's metadata
* @param mechanicVectorId Global mechanic vector ID
*/
function mechanicVectorMetadata(bytes32 mechanicVectorId) external view returns (MechanicVectorMetadata memory);
/**
* @notice Returns whether an address is a valid platform executor
* @param _executor Address to be checked
*/
function isPlatformExecutor(address _executor) external view returns (bool);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
interface IReferralManagerView {
/**
* @notice Get referrer for a tx
*/
function getCurrentReferrer(bytes32 vectorId) external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
/* solhint-disable max-line-length */
/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = a * b
// Compute the product mod 2**256 and mod 2**256 - 1
// then use the Chinese Remainder Theorem to reconstruct
// the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2**256 + prod0
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(a, b, not(0))
prod0 := mul(a, b)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division
if (prod1 == 0) {
require(denominator > 0);
assembly {
result := div(prod0, denominator)
}
return result;
}
// Make sure the result is less than 2**256.
// Also prevents denominator == 0
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0]
// Compute remainder using mulmod
uint256 remainder;
assembly {
remainder := mulmod(a, b, denominator)
}
// Subtract 256 bit number from 512 bit number
assembly {
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator
// Compute largest power of two divisor of denominator.
// Always >= 1.
uint256 twos = (0 - denominator) & denominator;
// Divide denominator by power of two
assembly {
denominator := div(denominator, twos)
}
// Divide [prod1 prod0] by the factors of two
assembly {
prod0 := div(prod0, twos)
}
// Shift in bits from prod1 into prod0. For this we need
// to flip `twos` such that it is 2**256 / twos.
// If twos is zero, then it becomes one
assembly {
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
// Invert denominator mod 2**256
// Now that denominator is an odd number, it has an inverse
// modulo 2**256 such that denominator * inv = 1 mod 2**256.
// Compute the inverse by starting with a seed that is correct
// correct for four bits. That is, denominator * inv = 1 mod 2**4
uint256 inv = (3 * denominator) ^ 2;
// Now use Newton-Raphson iteration to improve the precision.
// Thanks to Hensel's lifting lemma, this also works in modular
// arithmetic, doubling the correct bits in each step.
inv *= 2 - denominator * inv; // inverse mod 2**8
inv *= 2 - denominator * inv; // inverse mod 2**16
inv *= 2 - denominator * inv; // inverse mod 2**32
inv *= 2 - denominator * inv; // inverse mod 2**64
inv *= 2 - denominator * inv; // inverse mod 2**128
inv *= 2 - denominator * inv; // inverse mod 2**256
// Because the division is now exact we can divide by multiplying
// with the modular inverse of denominator. This will give us the
// correct result modulo 2**256. Since the precoditions guarantee
// that the outcome is less than 2**256, this is the final result.
// We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inv;
return result;
}
}
/// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) > 0) {
require(result < type(uint256).max);
result++;
}
}
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.10;
/* solhint-disable max-line-length */
/// @title Pool state that can change
/// @notice These methods compose the pool's state, and can change with any frequency including multiple times
/// per transaction
interface IUniswapV3PoolState {
/// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas
/// when accessed externally.
/// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value
/// tick The current tick of the pool, i.e. according to the last tick transition that was run.
/// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick
/// boundary.
/// observationIndex The index of the last oracle observation that was written,
/// observationCardinality The current maximum number of observations stored in the pool,
/// observationCardinalityNext The next maximum number of observations, to be updated when the observation.
/// feeProtocol The protocol fee for both tokens of the pool.
/// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0
/// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.
/// unlocked Whether the pool is currently locked to reentrancy
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
/// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool
/// @dev This value can overflow the uint256
function feeGrowthGlobal0X128() external view returns (uint256);
/// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool
/// @dev This value can overflow the uint256
function feeGrowthGlobal1X128() external view returns (uint256);
/// @notice The amounts of token0 and token1 that are owed to the protocol
/// @dev Protocol fees will never exceed uint128 max in either token
function protocolFees() external view returns (uint128 token0, uint128 token1);
/// @notice The currently in range liquidity available to the pool
/// @dev This value has no relationship to the total liquidity across all ticks
function liquidity() external view returns (uint128);
/// @notice Look up information about a specific tick in the pool
/// @param tick The tick to look up
/// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or
/// tick upper,
/// liquidityNet how much liquidity changes when the pool price crosses the tick,
/// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,
/// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,
/// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick
/// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,
/// secondsOutside the seconds spent on the other side of the tick from the current tick,
/// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.
/// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.
/// In addition, these values are only relative and must be used only in comparison to previous snapshots for
/// a specific position.
function ticks(
int24 tick
)
external
view
returns (
uint128 liquidityGross,
int128 liquidityNet,
uint256 feeGrowthOutside0X128,
uint256 feeGrowthOutside1X128,
int56 tickCumulativeOutside,
uint160 secondsPerLiquidityOutsideX128,
uint32 secondsOutside,
bool initialized
);
/// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information
function tickBitmap(int16 wordPosition) external view returns (uint256);
/// @notice Returns the information about a position by the position's key
/// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper
/// @return _liquidity The amount of liquidity in the position,
/// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,
/// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,
/// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,
/// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke
function positions(
bytes32 key
)
external
view
returns (
uint128 _liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
/// @notice Returns data about a specific observation index
/// @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 secondsPerLiquidityCumulativeX128 the seconds per in range liquidity 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 observations(
uint256 index
)
external
view
returns (
uint32 blockTimestamp,
int56 tickCumulative,
uint160 secondsPerLiquidityCumulativeX128,
bool initialized
);
}{
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 1
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"EtherSendFailed","type":"error"},{"inputs":[],"name":"InvalidERC20","type":"error"},{"inputs":[],"name":"InvalidERC20Config","type":"error"},{"inputs":[],"name":"InvalidEtherMintFeeCap","type":"error"},{"inputs":[],"name":"InvalidReferrer","type":"error"},{"inputs":[],"name":"InvalidVectorType","type":"error"},{"inputs":[],"name":"NotMintManager","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":true,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"uint256","name":"referralPayout","type":"uint256"}],"name":"ReferralPayout","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"ETH_WEI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FULL_MATH_SHIFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"erc20","type":"address"}],"name":"delistERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"internalType":"uint256","name":"numToMint","type":"uint256"},{"internalType":"address","name":"minter","type":"address"},{"internalType":"address","name":"currency","type":"address"}],"name":"getClassicVectorMintFeeCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"internalType":"uint256","name":"numToMint","type":"uint256"},{"internalType":"address","name":"minter","type":"address"},{"internalType":"address","name":"currency","type":"address"}],"name":"getGatedVectorMintFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"uint32","name":"numToMint","type":"uint32"},{"internalType":"address","name":"mechanic","type":"address"},{"internalType":"address","name":"minter","type":"address"}],"name":"getMechanicMintFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"internalType":"uint256","name":"numToMint","type":"uint256"},{"internalType":"address","name":"minter","type":"address"}],"name":"getMechanicVectorMintFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vectorId","type":"uint256"},{"internalType":"uint256","name":"numToMint","type":"uint256"},{"internalType":"address","name":"minter","type":"address"}],"name":"getPublicVectorMintFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"mintManager","type":"address"},{"internalType":"address","name":"platform","type":"address"},{"internalType":"address","name":"gaslessMechanic","type":"address"},{"internalType":"address","name":"backupReferralManager","type":"address"},{"internalType":"address","name":"backupDiscreteDutchAuctionMechanic","type":"address"},{"internalType":"address","name":"backupRankedAuctionMechanic","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"internalType":"bool","name":"payoutCreatorReward","type":"bool"},{"internalType":"address","name":"vectorPaymentRecipient","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"minter","type":"address"}],"name":"processClassicVectorMintFeeCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"erc20","type":"address"},{"components":[{"internalType":"uint96","name":"baseMintFee","type":"uint96"},{"internalType":"address","name":"realTimeOracle","type":"address"}],"internalType":"struct MintFeeOracle.ERC20Config","name":"config","type":"tuple"}],"name":"setAllowlistedERC20Config","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newBackupDiscreteDutchAuctionMechanic","type":"address"}],"name":"setBackupDiscreteDutchAuctionMechanic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newBackupRankedAuctionMechanic","type":"address"}],"name":"setBackupRankedAuctionMechanic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newBackupReferralManager","type":"address"}],"name":"setBackupReferralManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"creatorRewardsEnabled","type":"bool"}],"name":"setCreatorRewardsEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newGaslessMechanic","type":"address"}],"name":"setGaslessMechanic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newMintManager","type":"address"}],"name":"setMintManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"internalType":"address","name":"minter","type":"address"}],"name":"subsidizeMintConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"internalType":"address","name":"minter","type":"address"}],"name":"unsubsidizeMintVector","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":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"amountToWithdraw","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountToWithdraw","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"name":"withdrawNativeGasToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a06040523060805234801561001457600080fd5b506080516128a661004c600039600081816104d90152818161052201528181610662015281816106a2015261071e01526128a66000f3fe60806040526004361061013c5760003560e01c80632d6829b2146101415780632dda7bc5146101635780633659cfe61461018e57806347abcfce146101ae5780634cdb6056146101ce5780634f1ef286146101ee57806352d1902d146102015780635fc3ea0b1461021657806362a31a091461023657806362e03bcc14610256578063639c93da146102765780636478cd9814610296578063715018a6146102b6578063860caf0a146102cb5780638830eac0146102eb5780638da5cb5b1461030b5780639247ef90146103385780639cab9ce814610358578063a587c4e814610378578063b2a3a9a01461038b578063b8fd5cf5146103ab578063bea2ac07146103cb578063cc2a9a5b14610408578063d636953814610428578063f2fde38b14610448578063f67dcf8814610468578063fe1e8e7e14610488575b600080fd5b34801561014d57600080fd5b5061016161015c366004611f6d565b6104a4565b005b34801561016f57600080fd5b5061017b600160c01b81565b6040519081526020015b60405180910390f35b34801561019a57600080fd5b506101616101a9366004611f6d565b6104ce565b3480156101ba57600080fd5b5061017b6101c9366004611f8a565b6105a0565b3480156101da57600080fd5b5061017b6101e9366004611fd4565b610613565b6101616101fc366004612084565b610657565b34801561020d57600080fd5b5061017b610711565b34801561022257600080fd5b5061016161023136600461212b565b6107bf565b34801561024257600080fd5b5061016161025136600461216d565b61083e565b34801561026257600080fd5b50610161610271366004611f6d565b6108c6565b34801561028257600080fd5b50610161610291366004611f6d565b6108f6565b3480156102a257600080fd5b506101616102b13660046121ab565b610920565b3480156102c257600080fd5b5061016161093b565b3480156102d757600080fd5b506101616102e6366004611f6d565b61094f565b3480156102f757600080fd5b50610161610306366004611f6d565b610979565b34801561031757600080fd5b506103206109a3565b6040516001600160a01b039091168152602001610185565b34801561034457600080fd5b506101616103533660046121c8565b6109b2565b34801561036457600080fd5b5061016161037336600461216d565b610a75565b61017b610386366004612209565b610afd565b34801561039757600080fd5b506101616103a636600461216d565b610e81565b3480156103b757600080fd5b506101616103c6366004611f6d565b610ef9565b3480156103d757600080fd5b506103eb6103e6366004611f8a565b610f1b565b604080519283526001600160a01b03909116602083015201610185565b34801561041457600080fd5b50610161610423366004612279565b610f9e565b34801561043457600080fd5b506103eb6104433660046122ed565b611128565b34801561045457600080fd5b50610161610463366004611f6d565b61122d565b34801561047457600080fd5b506103eb6104833660046122ed565b6112a3565b34801561049457600080fd5b5061017b670de0b6b3a764000081565b6104ac6113c0565b606780546001600160a01b0319166001600160a01b0392909216919091179055565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156105205760405162461bcd60e51b81526004016105179061231b565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661055261141f565b6001600160a01b0316146105785760405162461bcd60e51b815260040161051790612355565b6105818161143b565b6040805160008082526020820190925261059d91839190611443565b50565b60006105ac85846115ae565b156105b95750600061060b565b6001600160a01b0382166106015783466089146105dd576602d79883d200006105e7565b671f6ee57fe04280005b6001600160401b03166105fa919061238f565b905061060b565b6105fa82856115db565b949350505050565b600061061e8361172d565b8061062e575061062e85836115ae565b1561063b5750600061060b565b8363ffffffff16466089146105dd576602d79883d200006105e7565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156106a05760405162461bcd60e51b81526004016105179061231b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166106d261141f565b6001600160a01b0316146106f85760405162461bcd60e51b815260040161051790612355565b6107018261143b565b61070d82826001611443565b5050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146107ac5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610517565b5060008051602061285383398151915290565b6107c76113c0565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb906107f590849086906004016123bc565b6020604051808303816000875af1158015610814573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083891906123e5565b50505050565b6108466113c0565b60006108528383611a0b565b60008181526066602052604090205490915060ff166108ac5760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1c9958591e481cdd589cda591a5e995960521b6044820152606401610517565b6000908152606660205260409020805460ff191690555050565b6108ce6113c0565b606980546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6108fe6113c0565b606a80546001600160a01b0319166001600160a01b0392909216919091179055565b6109286113c0565b6069805460ff1916911515919091179055565b6109436113c0565b61094d6000611a54565b565b6109576113c0565b606b80546001600160a01b0319166001600160a01b0392909216919091179055565b6109816113c0565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b6033546001600160a01b031690565b6109ba6113c0565b6109c76020820182612417565b6001600160601b0316158015906109f6575060006109eb6040830160208401611f6d565b6001600160a01b0316145b158015610a3c5750610a0b6020820182612417565b6001600160601b0316158015610a3a57506000610a2e6040830160208401611f6d565b6001600160a01b031614155b155b15610a5157610a516360c3620d60e11b611aa6565b6001600160a01b038216600090815260686020526040902081906108388282612434565b610a7d6113c0565b6000610a898383611a0b565b60008181526066602052604090205490915060ff1615610ae05760405162461bcd60e51b8152602060048201526012602482015271105b1c9958591e481cdd589cda591a5e995960721b6044820152606401610517565b6000908152606660205260409020805460ff191660011790555050565b6065546000906001600160a01b03163314610b2257610b22639a04794d60e01b611aa6565b6001600160a01b038416610b4757823414610b4757610b476321ac1c7960e21b611aa6565b6000610b51611ab0565b9050826001600160a01b0316816001600160a01b03161415610d615760006064610b7c86600a61238f565b610b869190612476565b604051630a9d031560e01b8152600481018b90529091506000906001600160a01b03841690630a9d031590602401602060405180830381865afa158015610bd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf591906124a3565b90506001600160a01b03811615801590610c1857506001600160a01b0381163214155b15610d5e576001600160a01b038716610c9c576000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610c78576040519150601f19603f3d011682016040523d82523d6000602084013e610c7d565b606091505b5050905080610c9657610c96637cd69c3960e11b611aa6565b50610d0f565b60405163a9059cbb60e01b81526001600160a01b0388169063a9059cbb90610cca90849086906004016123bc565b6020604051808303816000875af1158015610ce9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0d91906123e5565b505b866001600160a01b0316816001600160a01b03168b7f01bf363dbade8c9713473bfb336069d6c556e904f84103f174b5ef488657196985604051610d5591815260200190565b60405180910390a45b50505b8615610e71576000610d74600286612476565b90506001600160a01b038616610df5576000876001600160a01b03168260405160006040518083038185875af1925050503d8060008114610dd1576040519150601f19603f3d011682016040523d82523d6000602084013e610dd6565b606091505b5050905080610def57610def637cd69c3960e11b611aa6565b50610e68565b60405163a9059cbb60e01b81526001600160a01b0387169063a9059cbb90610e23908a9085906004016123bc565b6020604051808303816000875af1158015610e42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6691906123e5565b505b9150610e779050565b60009150505b9695505050505050565b610e896113c0565b6000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610ed6576040519150601f19603f3d011682016040523d82523d6000602084013e610edb565b606091505b5050905080610ef457610ef4637cd69c3960e11b611aa6565b505050565b610f016113c0565b6001600160a01b0316600090815260686020526040812055565b600080610f2886856115ae565b15610f3857506000905081610f95565b6001600160a01b03831615610f5b57610f5183866115db565b8391509150610f95565b8446608914610f71576602d79883d20000610f7b565b671f6ee57fe04280005b6001600160401b0316610f8e919061238f565b6000915091505b94509492505050565b600054610100900460ff1615808015610fbe5750600054600160ff909116105b80610fdf5750610fcd30611bdf565b158015610fdf575060005460ff166001145b6110425760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610517565b6000805460ff191660011790558015611065576000805461ff0019166101001790555b61106d611bee565b61107686611a54565b606580546001600160a01b03199081166001600160a01b038a81169190911790925560678054821688841617905560698054610100600160a81b03191661010088851602179055606a80548216868416179055606b8054909116918416919091179055801561111f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60655460405162820a0360e31b815260048101859052600091829182916001600160a01b03169063041050189060240160c060405180830381865afa158015611175573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119991906124c0565b80519091506001600160a01b03166111bb576111bb63f8e6d17560e01b611aa6565b6111c8816040015161172d565b806111d857506111d886856115ae565b156111ea576000809250925050611225565b8446608914611200576602d79883d2000061120a565b671f6ee57fe04280005b6001600160401b031661121d919061238f565b600092509250505b935093915050565b6112356113c0565b6001600160a01b03811661129a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610517565b61059d81611a54565b6000806112b085846115ae565b156112c057506000905080611225565b60655460405163228c835960e21b8152600481018790526000916001600160a01b031690638a320d64906024016101c060405180830381865afa15801561130b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132f9190612597565b80519091506001600160a01b03166113515761135163f8e6d17560e01b611aa6565b60c08101516001600160a01b031615611381576113728160c00151866115db565b8160c001519250925050611225565b8446608914611397576602d79883d200006113a1565b671f6ee57fe04280005b6001600160401b03166113b4919061238f565b60009250925050611225565b336113c96109a3565b6001600160a01b03161461094d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610517565b600080516020612853833981519152546001600160a01b031690565b61059d6113c0565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561147657610ef483611c1d565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156114d0575060408051601f3d908101601f191682019092526114cd918101906126a2565b60015b6115335760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610517565b60008051602061285383398151915281146115a25760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610517565b50610ef4838383611cb7565b6000606660006115be8585611a0b565b815260208101919091526040016000205460ff1690505b92915050565b6001600160a01b0380831660009081526068602090815260408083208151808301909252546001600160601b038116808352600160601b9091049094169181019190915290911561164457805161163c9084906001600160601b031661238f565b9150506115d5565b60208101516001600160a01b03161561171657600081602001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa15801561169b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bf91906126cd565b5050505050509050836116d182611cdc565b466089146116e6576602d79883d200006116f0565b671f6ee57fe04280005b6001600160401b0316611703919061238f565b61170d919061238f565b925050506115d5565b611726630eca12dd60e31b611aa6565b5092915050565b600046600114156117815773dfee0ed4a217f37b3fa87624ee00fe5685bdc5096001600160a01b03831614806115d55750506001600160a01b03167394fa6e7fc2555ada63ea56cfff425558360f00741490565b4661210514156117d45773922e9f8cc491facbd403afa143aa53ee9146474c6001600160a01b03831614806115d55750506001600160a01b031673a748be280c9a00edaf7d04076fe8a93c59e95b031490565b46600a14156118265773b207774ac4e32ece47771e64bde5ec3894c1de6b6001600160a01b03831614806115d55750506001600160a01b03167315753e20667961fb30d5aa92e2255b876568be7e1490565b4661a4b1141561187957737f75358787f880506c5dc6100386f77be8de0a306001600160a01b03831614806115d55750506001600160a01b0316733a2afe86e594540cbf3ea345dd29e09228f186d21490565b466276adf114156118cd57730afb6566c836d1c4788cd2b54bd9ca0158cc2d3d6001600160a01b03831614806115d55750506001600160a01b031673f12a4018647dd2275072967fd5f3ac5fef7a04711490565b466089141561191f57734ccb72e7e0cd948af50bc7bf598fc4e027b70f986001600160a01b03831614806115d55750506001600160a01b031673ae22cd8052d64e7c2af6b5e3045fab0a86c8334c1490565b4662aa36a714156119735773a2d14ca9985de170db128c8cb74cecb35eeaf47e6001600160a01b03831614806115d55750506001600160a01b031673cebc3b3134fbef95ed13aecdf997d4371d0223851490565b4662014a3414156119c757739958f83f383ca150bb2252b4275d3e3051be469f6001600160a01b03831614806115d55750506001600160a01b0316734821b6e9ac0ccc590acce2442bb6bb32388c1cb71490565b606a546001600160a01b03838116911614806119f05750606b546001600160a01b038381169116145b806115d55750506067546001600160a01b0390811691161490565b60008282604051602001611a3692919091825260601b6001600160601b031916602082015260340190565b60405160208183030381529060405280519060200120905092915050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8060005260046000fd5b60004660011415611ad4575073d3c63951b2ed18e8d92b5b251c3b636a45a547d090565b466121051415611af7575073d9e58978808d17f99ccceab5195b052e972c018890565b46600a1415611b195750739cf5b12d2e2a88083647ff2fe0610f818b28ec7790565b466276adf11415611b3d5750737cb2cecfcffdcce0bf69366e52caec6bd719cd4490565b4661a4b11415611b60575073617b2383d93909590fac0b2aaa547ec5615d82ef90565b4660891415611b825750736fd07d4b5fd7093762fb2f278769aa7e2511d45c90565b4662014a341415611ba65750734619b9673241eb41b642dc04371100d238b73ffe90565b4662aa36a71415611bca575073d33c1be264bb98f86e18cd816d5fd44e97cb716390565b5060695461010090046001600160a01b031690565b6001600160a01b03163b151590565b600054610100900460ff16611c155760405162461bcd60e51b81526004016105179061276c565b61094d611d07565b611c2681611bdf565b611c885760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610517565b60008051602061285383398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b611cc083611d37565b600082511180611ccd5750805b15610ef4576108388383611d77565b60006115d5611cf46001600160a01b0384168061238f565b670de0b6b3a7640000600160c01b611da3565b600054610100900460ff16611d2e5760405162461bcd60e51b81526004016105179061276c565b61094d33611a54565b611d4081611c1d565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060611d9c838360405180606001604052806027815260200161287360279139611e56565b9392505050565b600080806000198587098587029250828110838203039150508060001415611ddd5760008411611dd257600080fd5b508290049050611d9c565b808411611de957600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b6060600080856001600160a01b031685604051611e7391906127e3565b600060405180830381855af49150503d8060008114611eae576040519150601f19603f3d011682016040523d82523d6000602084013e611eb3565b606091505b5091509150610e778683838760608315611f29578251611f2257611ed685611bdf565b611f225760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610517565b508161060b565b61060b8383815115611f3e5781518083602001fd5b8060405162461bcd60e51b815260040161051791906127ff565b6001600160a01b038116811461059d57600080fd5b600060208284031215611f7f57600080fd5b8135611d9c81611f58565b60008060008060808587031215611fa057600080fd5b84359350602085013592506040850135611fb981611f58565b91506060850135611fc981611f58565b939692955090935050565b60008060008060808587031215611fea57600080fd5b84359350602085013563ffffffff8116811461200557600080fd5b92506040850135611fb981611f58565b634e487b7160e01b600052604160045260246000fd5b6040516101c081016001600160401b038111828210171561204e5761204e612015565b60405290565b604051601f8201601f191681016001600160401b038111828210171561207c5761207c612015565b604052919050565b6000806040838503121561209757600080fd5b82356120a281611f58565b91506020838101356001600160401b03808211156120bf57600080fd5b818601915086601f8301126120d357600080fd5b8135818111156120e5576120e5612015565b6120f7601f8201601f19168501612054565b9150808252878482850101111561210d57600080fd5b80848401858401376000848284010152508093505050509250929050565b60008060006060848603121561214057600080fd5b833561214b81611f58565b925060208401359150604084013561216281611f58565b809150509250925092565b6000806040838503121561218057600080fd5b82359150602083013561219281611f58565b809150509250929050565b801515811461059d57600080fd5b6000602082840312156121bd57600080fd5b8135611d9c8161219d565b60008082840360608112156121dc57600080fd5b83356121e781611f58565b92506040601f19820112156121fb57600080fd5b506020830190509250929050565b60008060008060008060c0878903121561222257600080fd5b8635955060208701356122348161219d565b9450604087013561224481611f58565b9350606087013561225481611f58565b92506080870135915060a087013561226b81611f58565b809150509295509295509295565b60008060008060008060c0878903121561229257600080fd5b863561229d81611f58565b955060208701356122ad81611f58565b945060408701356122bd81611f58565b935060608701356122cd81611f58565b925060808701356122dd81611f58565b915060a087013561226b81611f58565b60008060006060848603121561230257600080fd5b8335925060208401359150604084013561216281611f58565b6020808252602c9082015260008051602061283383398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c9082015260008051602061283383398151915260408201526b6163746976652070726f787960a01b606082015260800190565b60008160001904831182151516156123b757634e487b7160e01b600052601160045260246000fd5b500290565b6001600160a01b03929092168252602082015260400190565b80516123e08161219d565b919050565b6000602082840312156123f757600080fd5b8151611d9c8161219d565b6001600160601b038116811461059d57600080fd5b60006020828403121561242957600080fd5b8135611d9c81612402565b813561243f81612402565b81546001600160601b03199081166001600160601b03929092169182178355602084013561246c81611f58565b60601b1617905550565b60008261249357634e487b7160e01b600052601260045260246000fd5b500490565b80516123e081611f58565b6000602082840312156124b557600080fd5b8151611d9c81611f58565b600060c082840312156124d257600080fd5b60405160c081016001600160401b03811182821017156124f4576124f4612015565b604052825161250281611f58565b8152602083015161251281612402565b6020820152604083015161252581611f58565b604082015260608301516125388161219d565b6060820152608083015161254b8161219d565b608082015260a083015161255e8161219d565b60a08201529392505050565b805165ffffffffffff811681146123e057600080fd5b80516001600160c01b03811681146123e057600080fd5b60006101c082840312156125aa57600080fd5b6125b261202b565b6125bb83612498565b81526125c96020840161256a565b60208201526125da6040840161256a565b60408201526125eb60608401612498565b60608201526125fc6080840161256a565b608082015261260d60a0840161256a565b60a082015261261e60c08401612498565b60c082015261262f60e0840161256a565b60e082015261010061264281850161256a565b90820152610120612654848201612580565b9082015261014061266684820161256a565b908201526101606126788482016123d5565b9082015261018061268a8482016123d5565b908201526101a0928301519281019290925250919050565b6000602082840312156126b457600080fd5b5051919050565b805161ffff811681146123e057600080fd5b600080600080600080600060e0888a0312156126e857600080fd5b87516126f381611f58565b8097505060208801518060020b811461270b57600080fd5b9550612719604089016126bb565b9450612727606089016126bb565b9350612735608089016126bb565b925060a088015160ff8116811461274b57600080fd5b60c089015190925061275c8161219d565b8091505092959891949750929550565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60005b838110156127d25781810151838201526020016127ba565b838111156108385750506000910152565b600082516127f58184602087016127b7565b9190910192915050565b602081526000825180602084015261281e8160408501602087016127b7565b601f01601f1916919091016040019291505056fe46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080a000a
Deployed Bytecode
0x60806040526004361061013c5760003560e01c80632d6829b2146101415780632dda7bc5146101635780633659cfe61461018e57806347abcfce146101ae5780634cdb6056146101ce5780634f1ef286146101ee57806352d1902d146102015780635fc3ea0b1461021657806362a31a091461023657806362e03bcc14610256578063639c93da146102765780636478cd9814610296578063715018a6146102b6578063860caf0a146102cb5780638830eac0146102eb5780638da5cb5b1461030b5780639247ef90146103385780639cab9ce814610358578063a587c4e814610378578063b2a3a9a01461038b578063b8fd5cf5146103ab578063bea2ac07146103cb578063cc2a9a5b14610408578063d636953814610428578063f2fde38b14610448578063f67dcf8814610468578063fe1e8e7e14610488575b600080fd5b34801561014d57600080fd5b5061016161015c366004611f6d565b6104a4565b005b34801561016f57600080fd5b5061017b600160c01b81565b6040519081526020015b60405180910390f35b34801561019a57600080fd5b506101616101a9366004611f6d565b6104ce565b3480156101ba57600080fd5b5061017b6101c9366004611f8a565b6105a0565b3480156101da57600080fd5b5061017b6101e9366004611fd4565b610613565b6101616101fc366004612084565b610657565b34801561020d57600080fd5b5061017b610711565b34801561022257600080fd5b5061016161023136600461212b565b6107bf565b34801561024257600080fd5b5061016161025136600461216d565b61083e565b34801561026257600080fd5b50610161610271366004611f6d565b6108c6565b34801561028257600080fd5b50610161610291366004611f6d565b6108f6565b3480156102a257600080fd5b506101616102b13660046121ab565b610920565b3480156102c257600080fd5b5061016161093b565b3480156102d757600080fd5b506101616102e6366004611f6d565b61094f565b3480156102f757600080fd5b50610161610306366004611f6d565b610979565b34801561031757600080fd5b506103206109a3565b6040516001600160a01b039091168152602001610185565b34801561034457600080fd5b506101616103533660046121c8565b6109b2565b34801561036457600080fd5b5061016161037336600461216d565b610a75565b61017b610386366004612209565b610afd565b34801561039757600080fd5b506101616103a636600461216d565b610e81565b3480156103b757600080fd5b506101616103c6366004611f6d565b610ef9565b3480156103d757600080fd5b506103eb6103e6366004611f8a565b610f1b565b604080519283526001600160a01b03909116602083015201610185565b34801561041457600080fd5b50610161610423366004612279565b610f9e565b34801561043457600080fd5b506103eb6104433660046122ed565b611128565b34801561045457600080fd5b50610161610463366004611f6d565b61122d565b34801561047457600080fd5b506103eb6104833660046122ed565b6112a3565b34801561049457600080fd5b5061017b670de0b6b3a764000081565b6104ac6113c0565b606780546001600160a01b0319166001600160a01b0392909216919091179055565b306001600160a01b037f000000000000000000000000d3dc9bbfeee1701839991a753a68e477344218501614156105205760405162461bcd60e51b81526004016105179061231b565b60405180910390fd5b7f000000000000000000000000d3dc9bbfeee1701839991a753a68e477344218506001600160a01b031661055261141f565b6001600160a01b0316146105785760405162461bcd60e51b815260040161051790612355565b6105818161143b565b6040805160008082526020820190925261059d91839190611443565b50565b60006105ac85846115ae565b156105b95750600061060b565b6001600160a01b0382166106015783466089146105dd576602d79883d200006105e7565b671f6ee57fe04280005b6001600160401b03166105fa919061238f565b905061060b565b6105fa82856115db565b949350505050565b600061061e8361172d565b8061062e575061062e85836115ae565b1561063b5750600061060b565b8363ffffffff16466089146105dd576602d79883d200006105e7565b306001600160a01b037f000000000000000000000000d3dc9bbfeee1701839991a753a68e477344218501614156106a05760405162461bcd60e51b81526004016105179061231b565b7f000000000000000000000000d3dc9bbfeee1701839991a753a68e477344218506001600160a01b03166106d261141f565b6001600160a01b0316146106f85760405162461bcd60e51b815260040161051790612355565b6107018261143b565b61070d82826001611443565b5050565b6000306001600160a01b037f000000000000000000000000d3dc9bbfeee1701839991a753a68e4773442185016146107ac5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610517565b5060008051602061285383398151915290565b6107c76113c0565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb906107f590849086906004016123bc565b6020604051808303816000875af1158015610814573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083891906123e5565b50505050565b6108466113c0565b60006108528383611a0b565b60008181526066602052604090205490915060ff166108ac5760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1c9958591e481cdd589cda591a5e995960521b6044820152606401610517565b6000908152606660205260409020805460ff191690555050565b6108ce6113c0565b606980546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6108fe6113c0565b606a80546001600160a01b0319166001600160a01b0392909216919091179055565b6109286113c0565b6069805460ff1916911515919091179055565b6109436113c0565b61094d6000611a54565b565b6109576113c0565b606b80546001600160a01b0319166001600160a01b0392909216919091179055565b6109816113c0565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b6033546001600160a01b031690565b6109ba6113c0565b6109c76020820182612417565b6001600160601b0316158015906109f6575060006109eb6040830160208401611f6d565b6001600160a01b0316145b158015610a3c5750610a0b6020820182612417565b6001600160601b0316158015610a3a57506000610a2e6040830160208401611f6d565b6001600160a01b031614155b155b15610a5157610a516360c3620d60e11b611aa6565b6001600160a01b038216600090815260686020526040902081906108388282612434565b610a7d6113c0565b6000610a898383611a0b565b60008181526066602052604090205490915060ff1615610ae05760405162461bcd60e51b8152602060048201526012602482015271105b1c9958591e481cdd589cda591a5e995960721b6044820152606401610517565b6000908152606660205260409020805460ff191660011790555050565b6065546000906001600160a01b03163314610b2257610b22639a04794d60e01b611aa6565b6001600160a01b038416610b4757823414610b4757610b476321ac1c7960e21b611aa6565b6000610b51611ab0565b9050826001600160a01b0316816001600160a01b03161415610d615760006064610b7c86600a61238f565b610b869190612476565b604051630a9d031560e01b8152600481018b90529091506000906001600160a01b03841690630a9d031590602401602060405180830381865afa158015610bd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf591906124a3565b90506001600160a01b03811615801590610c1857506001600160a01b0381163214155b15610d5e576001600160a01b038716610c9c576000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610c78576040519150601f19603f3d011682016040523d82523d6000602084013e610c7d565b606091505b5050905080610c9657610c96637cd69c3960e11b611aa6565b50610d0f565b60405163a9059cbb60e01b81526001600160a01b0388169063a9059cbb90610cca90849086906004016123bc565b6020604051808303816000875af1158015610ce9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0d91906123e5565b505b866001600160a01b0316816001600160a01b03168b7f01bf363dbade8c9713473bfb336069d6c556e904f84103f174b5ef488657196985604051610d5591815260200190565b60405180910390a45b50505b8615610e71576000610d74600286612476565b90506001600160a01b038616610df5576000876001600160a01b03168260405160006040518083038185875af1925050503d8060008114610dd1576040519150601f19603f3d011682016040523d82523d6000602084013e610dd6565b606091505b5050905080610def57610def637cd69c3960e11b611aa6565b50610e68565b60405163a9059cbb60e01b81526001600160a01b0387169063a9059cbb90610e23908a9085906004016123bc565b6020604051808303816000875af1158015610e42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6691906123e5565b505b9150610e779050565b60009150505b9695505050505050565b610e896113c0565b6000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610ed6576040519150601f19603f3d011682016040523d82523d6000602084013e610edb565b606091505b5050905080610ef457610ef4637cd69c3960e11b611aa6565b505050565b610f016113c0565b6001600160a01b0316600090815260686020526040812055565b600080610f2886856115ae565b15610f3857506000905081610f95565b6001600160a01b03831615610f5b57610f5183866115db565b8391509150610f95565b8446608914610f71576602d79883d20000610f7b565b671f6ee57fe04280005b6001600160401b0316610f8e919061238f565b6000915091505b94509492505050565b600054610100900460ff1615808015610fbe5750600054600160ff909116105b80610fdf5750610fcd30611bdf565b158015610fdf575060005460ff166001145b6110425760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610517565b6000805460ff191660011790558015611065576000805461ff0019166101001790555b61106d611bee565b61107686611a54565b606580546001600160a01b03199081166001600160a01b038a81169190911790925560678054821688841617905560698054610100600160a81b03191661010088851602179055606a80548216868416179055606b8054909116918416919091179055801561111f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60655460405162820a0360e31b815260048101859052600091829182916001600160a01b03169063041050189060240160c060405180830381865afa158015611175573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061119991906124c0565b80519091506001600160a01b03166111bb576111bb63f8e6d17560e01b611aa6565b6111c8816040015161172d565b806111d857506111d886856115ae565b156111ea576000809250925050611225565b8446608914611200576602d79883d2000061120a565b671f6ee57fe04280005b6001600160401b031661121d919061238f565b600092509250505b935093915050565b6112356113c0565b6001600160a01b03811661129a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610517565b61059d81611a54565b6000806112b085846115ae565b156112c057506000905080611225565b60655460405163228c835960e21b8152600481018790526000916001600160a01b031690638a320d64906024016101c060405180830381865afa15801561130b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132f9190612597565b80519091506001600160a01b03166113515761135163f8e6d17560e01b611aa6565b60c08101516001600160a01b031615611381576113728160c00151866115db565b8160c001519250925050611225565b8446608914611397576602d79883d200006113a1565b671f6ee57fe04280005b6001600160401b03166113b4919061238f565b60009250925050611225565b336113c96109a3565b6001600160a01b03161461094d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610517565b600080516020612853833981519152546001600160a01b031690565b61059d6113c0565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561147657610ef483611c1d565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156114d0575060408051601f3d908101601f191682019092526114cd918101906126a2565b60015b6115335760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610517565b60008051602061285383398151915281146115a25760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610517565b50610ef4838383611cb7565b6000606660006115be8585611a0b565b815260208101919091526040016000205460ff1690505b92915050565b6001600160a01b0380831660009081526068602090815260408083208151808301909252546001600160601b038116808352600160601b9091049094169181019190915290911561164457805161163c9084906001600160601b031661238f565b9150506115d5565b60208101516001600160a01b03161561171657600081602001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa15801561169b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116bf91906126cd565b5050505050509050836116d182611cdc565b466089146116e6576602d79883d200006116f0565b671f6ee57fe04280005b6001600160401b0316611703919061238f565b61170d919061238f565b925050506115d5565b611726630eca12dd60e31b611aa6565b5092915050565b600046600114156117815773dfee0ed4a217f37b3fa87624ee00fe5685bdc5096001600160a01b03831614806115d55750506001600160a01b03167394fa6e7fc2555ada63ea56cfff425558360f00741490565b4661210514156117d45773922e9f8cc491facbd403afa143aa53ee9146474c6001600160a01b03831614806115d55750506001600160a01b031673a748be280c9a00edaf7d04076fe8a93c59e95b031490565b46600a14156118265773b207774ac4e32ece47771e64bde5ec3894c1de6b6001600160a01b03831614806115d55750506001600160a01b03167315753e20667961fb30d5aa92e2255b876568be7e1490565b4661a4b1141561187957737f75358787f880506c5dc6100386f77be8de0a306001600160a01b03831614806115d55750506001600160a01b0316733a2afe86e594540cbf3ea345dd29e09228f186d21490565b466276adf114156118cd57730afb6566c836d1c4788cd2b54bd9ca0158cc2d3d6001600160a01b03831614806115d55750506001600160a01b031673f12a4018647dd2275072967fd5f3ac5fef7a04711490565b466089141561191f57734ccb72e7e0cd948af50bc7bf598fc4e027b70f986001600160a01b03831614806115d55750506001600160a01b031673ae22cd8052d64e7c2af6b5e3045fab0a86c8334c1490565b4662aa36a714156119735773a2d14ca9985de170db128c8cb74cecb35eeaf47e6001600160a01b03831614806115d55750506001600160a01b031673cebc3b3134fbef95ed13aecdf997d4371d0223851490565b4662014a3414156119c757739958f83f383ca150bb2252b4275d3e3051be469f6001600160a01b03831614806115d55750506001600160a01b0316734821b6e9ac0ccc590acce2442bb6bb32388c1cb71490565b606a546001600160a01b03838116911614806119f05750606b546001600160a01b038381169116145b806115d55750506067546001600160a01b0390811691161490565b60008282604051602001611a3692919091825260601b6001600160601b031916602082015260340190565b60405160208183030381529060405280519060200120905092915050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8060005260046000fd5b60004660011415611ad4575073d3c63951b2ed18e8d92b5b251c3b636a45a547d090565b466121051415611af7575073d9e58978808d17f99ccceab5195b052e972c018890565b46600a1415611b195750739cf5b12d2e2a88083647ff2fe0610f818b28ec7790565b466276adf11415611b3d5750737cb2cecfcffdcce0bf69366e52caec6bd719cd4490565b4661a4b11415611b60575073617b2383d93909590fac0b2aaa547ec5615d82ef90565b4660891415611b825750736fd07d4b5fd7093762fb2f278769aa7e2511d45c90565b4662014a341415611ba65750734619b9673241eb41b642dc04371100d238b73ffe90565b4662aa36a71415611bca575073d33c1be264bb98f86e18cd816d5fd44e97cb716390565b5060695461010090046001600160a01b031690565b6001600160a01b03163b151590565b600054610100900460ff16611c155760405162461bcd60e51b81526004016105179061276c565b61094d611d07565b611c2681611bdf565b611c885760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610517565b60008051602061285383398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b611cc083611d37565b600082511180611ccd5750805b15610ef4576108388383611d77565b60006115d5611cf46001600160a01b0384168061238f565b670de0b6b3a7640000600160c01b611da3565b600054610100900460ff16611d2e5760405162461bcd60e51b81526004016105179061276c565b61094d33611a54565b611d4081611c1d565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060611d9c838360405180606001604052806027815260200161287360279139611e56565b9392505050565b600080806000198587098587029250828110838203039150508060001415611ddd5760008411611dd257600080fd5b508290049050611d9c565b808411611de957600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b6060600080856001600160a01b031685604051611e7391906127e3565b600060405180830381855af49150503d8060008114611eae576040519150601f19603f3d011682016040523d82523d6000602084013e611eb3565b606091505b5091509150610e778683838760608315611f29578251611f2257611ed685611bdf565b611f225760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610517565b508161060b565b61060b8383815115611f3e5781518083602001fd5b8060405162461bcd60e51b815260040161051791906127ff565b6001600160a01b038116811461059d57600080fd5b600060208284031215611f7f57600080fd5b8135611d9c81611f58565b60008060008060808587031215611fa057600080fd5b84359350602085013592506040850135611fb981611f58565b91506060850135611fc981611f58565b939692955090935050565b60008060008060808587031215611fea57600080fd5b84359350602085013563ffffffff8116811461200557600080fd5b92506040850135611fb981611f58565b634e487b7160e01b600052604160045260246000fd5b6040516101c081016001600160401b038111828210171561204e5761204e612015565b60405290565b604051601f8201601f191681016001600160401b038111828210171561207c5761207c612015565b604052919050565b6000806040838503121561209757600080fd5b82356120a281611f58565b91506020838101356001600160401b03808211156120bf57600080fd5b818601915086601f8301126120d357600080fd5b8135818111156120e5576120e5612015565b6120f7601f8201601f19168501612054565b9150808252878482850101111561210d57600080fd5b80848401858401376000848284010152508093505050509250929050565b60008060006060848603121561214057600080fd5b833561214b81611f58565b925060208401359150604084013561216281611f58565b809150509250925092565b6000806040838503121561218057600080fd5b82359150602083013561219281611f58565b809150509250929050565b801515811461059d57600080fd5b6000602082840312156121bd57600080fd5b8135611d9c8161219d565b60008082840360608112156121dc57600080fd5b83356121e781611f58565b92506040601f19820112156121fb57600080fd5b506020830190509250929050565b60008060008060008060c0878903121561222257600080fd5b8635955060208701356122348161219d565b9450604087013561224481611f58565b9350606087013561225481611f58565b92506080870135915060a087013561226b81611f58565b809150509295509295509295565b60008060008060008060c0878903121561229257600080fd5b863561229d81611f58565b955060208701356122ad81611f58565b945060408701356122bd81611f58565b935060608701356122cd81611f58565b925060808701356122dd81611f58565b915060a087013561226b81611f58565b60008060006060848603121561230257600080fd5b8335925060208401359150604084013561216281611f58565b6020808252602c9082015260008051602061283383398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c9082015260008051602061283383398151915260408201526b6163746976652070726f787960a01b606082015260800190565b60008160001904831182151516156123b757634e487b7160e01b600052601160045260246000fd5b500290565b6001600160a01b03929092168252602082015260400190565b80516123e08161219d565b919050565b6000602082840312156123f757600080fd5b8151611d9c8161219d565b6001600160601b038116811461059d57600080fd5b60006020828403121561242957600080fd5b8135611d9c81612402565b813561243f81612402565b81546001600160601b03199081166001600160601b03929092169182178355602084013561246c81611f58565b60601b1617905550565b60008261249357634e487b7160e01b600052601260045260246000fd5b500490565b80516123e081611f58565b6000602082840312156124b557600080fd5b8151611d9c81611f58565b600060c082840312156124d257600080fd5b60405160c081016001600160401b03811182821017156124f4576124f4612015565b604052825161250281611f58565b8152602083015161251281612402565b6020820152604083015161252581611f58565b604082015260608301516125388161219d565b6060820152608083015161254b8161219d565b608082015260a083015161255e8161219d565b60a08201529392505050565b805165ffffffffffff811681146123e057600080fd5b80516001600160c01b03811681146123e057600080fd5b60006101c082840312156125aa57600080fd5b6125b261202b565b6125bb83612498565b81526125c96020840161256a565b60208201526125da6040840161256a565b60408201526125eb60608401612498565b60608201526125fc6080840161256a565b608082015261260d60a0840161256a565b60a082015261261e60c08401612498565b60c082015261262f60e0840161256a565b60e082015261010061264281850161256a565b90820152610120612654848201612580565b9082015261014061266684820161256a565b908201526101606126788482016123d5565b9082015261018061268a8482016123d5565b908201526101a0928301519281019290925250919050565b6000602082840312156126b457600080fd5b5051919050565b805161ffff811681146123e057600080fd5b600080600080600080600060e0888a0312156126e857600080fd5b87516126f381611f58565b8097505060208801518060020b811461270b57600080fd5b9550612719604089016126bb565b9450612727606089016126bb565b9350612735608089016126bb565b925060a088015160ff8116811461274b57600080fd5b60c089015190925061275c8161219d565b8091505092959891949750929550565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60005b838110156127d25781810151838201526020016127ba565b838111156108385750506000910152565b600082516127f58184602087016127b7565b9190910192915050565b602081526000825180602084015261281e8160408501602087016127b7565b601f01601f1916919091016040019291505056fe46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080a000a
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.