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";
import "../erc1155/interfaces/IERC1155Standard.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,
bool is1155
) 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 = is1155 ? ((amount * 8) / 10) : 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,
address collectionContract
) external view returns (uint256, bool) {
bool is1155 = _is1155(collectionContract);
if (_isFeeSubsidized(vectorId, minter)) {
return (0, is1155);
}
if (currency == address(0)) {
return (_nativeGasTokenMintFee(is1155) * numToMint, is1155);
} else {
return (_getClassicVectorERC20MintFeeCap(currency, numToMint, is1155), is1155);
}
}
/**
* @notice See {IMintFeeOracle-getMechanicMintFee}
*/
function getMechanicMintFee(
bytes32 mechanicVectorId,
uint32 numToMint,
address mechanic,
address minter,
address collectionContract
) external view returns (uint256) {
if (_isMintFeeWaivedMechanic(mechanic) || _isFeeSubsidized(mechanicVectorId, minter)) {
return 0;
} else {
return _nativeGasTokenMintFee(collectionContract) * 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.contractAddress),
_vector.currency
);
} else {
return (_nativeGasTokenMintFee(_vector.contractAddress) * uint256(numToMint), address(0));
}
}
/**
* @notice Get gated vector mint fee (optimized for offchain querying)
*/
function getGatedVectorMintFee(
bytes32 vectorId,
uint256 numToMint,
address minter,
address currency,
address collectionContract
) external view returns (uint256, address) {
if (_isFeeSubsidized(vectorId, minter)) {
return (0, currency);
}
if (currency != address(0)) {
return (_getClassicVectorERC20MintFeeCap(currency, numToMint, collectionContract), currency);
}
return (_nativeGasTokenMintFee(collectionContract) * 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 (_nativeGasTokenMintFee(_mechanicMetadata.contractAddress) * 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,
address collectionContract
) private view returns (uint256) {
ERC20Config memory config = _allowlistedERC20s[currency];
uint256 divisor = _is1155(collectionContract) ? 2 : 1;
if (config.baseMintFee != 0) {
return (config.baseMintFee / divisor) * numToMint;
} else if (config.realTimeOracle != address(0)) {
(uint160 sqrtPriceX96, , , , , , ) = IUniswapV3PoolState(config.realTimeOracle).slot0();
return _nativeGasTokenMintFee(collectionContract) * sqrtPriceX96ToUint(sqrtPriceX96) * numToMint;
} else {
_revert(InvalidERC20.selector);
}
}
function _getClassicVectorERC20MintFeeCap(
address currency,
uint256 numToMint,
bool is1155
) private view returns (uint256) {
ERC20Config memory config = _allowlistedERC20s[currency];
uint256 divisor = is1155 ? 2 : 1;
if (config.baseMintFee != 0) {
return (config.baseMintFee / divisor) * numToMint;
} else if (config.realTimeOracle != address(0)) {
(uint160 sqrtPriceX96, , , , , , ) = IUniswapV3PoolState(config.realTimeOracle).slot0();
return _nativeGasTokenMintFee(is1155) * sqrtPriceX96ToUint(sqrtPriceX96) * numToMint;
} else {
_revert(InvalidERC20.selector);
}
}
/* solhint-disable code-complexity */
function _isMintFeeWaivedMechanic(address mechanic) private view returns (bool) {
// RAM, DDAM
// we don't hit mint fee oracle in case of 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;
} else if (block.chainid == 984122) {
return
mechanic == 0x5AA1C7F5f9d2e7F2664d3C1f454560C6DaBED6c8 ||
mechanic == 0x9c602CE508E41ccAF2cF997D93A9FbE0166D8aE6;
} else if (block.chainid == 5000) {
return
mechanic == 0xd8f0A3AA4067be3D70a5B46A795Ad9dF9E65Cd3C ||
mechanic == 0xaF4d61951A425BA60ac1E7EA6d51e92d2F4748E4;
} else if (block.chainid == 534352) {
return
mechanic == 0xF6C67C7bb7018E4609d571023196A4682FdA6F2f ||
mechanic == 0xE019FF8033d9C761985A3EE1fa5d97Cc9Cf6d5c0;
}
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 if (block.chainid == 984122) {
return 0x9491aA1c2f46319A645637c4105f4199B251e4dD;
} else if (block.chainid == 5000) {
return 0xAFfC7C9BfB48FFD2a580e1a0d36f8cc7D45Dcb58;
} else if (block.chainid == 534352) {
return 0x4821B6e9aC0CCC590acCe2442bb6BB32388C1CB7;
} else {
return _backupReferralManager;
}
}
/**
* @notice Get the native gas token mint fee for the chain
*/
function _nativeGasTokenMintFee(address collectionContract) private view returns (uint256) {
uint256 divisor = _is1155(collectionContract) ? 2 : 1;
if (block.chainid == 137) {
return 2265000000000000000 / divisor;
} else if (block.chainid == 984122) {
return 500000000000000000 / divisor;
} else if (block.chainid == 5000) {
return 3500000000000000000 / divisor;
} else {
return 800000000000000 / divisor;
}
}
/**
* @notice Get the native gas token mint fee for the chain
*/
function _nativeGasTokenMintFee(bool is1155) private view returns (uint256) {
uint256 divisor = is1155 ? 2 : 1;
if (block.chainid == 137) {
return 2265000000000000000 / divisor;
} else if (block.chainid == 984122) {
return 500000000000000000 / divisor;
} else if (block.chainid == 5000) {
return 3500000000000000000 / divisor;
} else {
return 800000000000000 / divisor;
}
}
/**
* @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);
}
/**
* @notice Return if collection is an ERC1155 contract
*/
function _is1155(address collectionContract) private view returns (bool) {
try IERC1155Standard(collectionContract).highlightContractStandardHash() returns (bytes32 standardHash) {
return standardHash == 0x3a9654d81ac4dafbb9a2fb1cd3efa3de2783ae40b06b17a456bf5922ed02a3a7;
} catch Error(string memory reason) {
return false;
} catch {
return false;
}
}
}// 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;
interface IERC1155Standard {
/**
* @notice Return Highlight contract standard hash
*/
function highlightContractStandardHash() external view returns (bytes32);
}// 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
* @param is1155 If collection contract is an 1155
*/
function processClassicVectorMintFeeCap(
bytes32 vectorId,
bool payoutCreatorReward,
address vectorPaymentRecipient,
address currency,
uint256 amount,
address minter,
bool is1155
) 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
* @param collectionContract Collection NFT contract
*/
function getClassicVectorMintFeeCap(
bytes32 vectorId,
uint256 numToMint,
address minter,
address currency,
address collectionContract
) external view returns (uint256, bool);
/**
* @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
* @param collectionContract Collection NFT contract
*/
function getMechanicMintFee(
bytes32 vectorId,
uint32 numToMint,
address mechanic,
address minter,
address collectionContract
) 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"},{"internalType":"address","name":"collectionContract","type":"address"}],"name":"getClassicVectorMintFeeCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"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"},{"internalType":"address","name":"collectionContract","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"},{"internalType":"address","name":"collectionContract","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"},{"internalType":"bool","name":"is1155","type":"bool"}],"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
60a06040523060805234801561001457600080fd5b50608051612d6361004c600039600081816104ee01528181610537015281816105c001528181610600015261067c0152612d636000f3fe60806040526004361061013c5760003560e01c80632d6829b2146101415780632dda7bc5146101635780633659cfe61461018e5780634f1ef286146101ae57806352d1902d146101c15780635fc3ea0b146101d657806362a31a09146101f657806362e03bcc14610216578063639c93da146102365780636478cd98146102565780636f18e93f14610276578063715018a61461028957806376c198931461029e578063860caf0a146102d35780638830eac0146102f35780638da5cb5b146103135780639247ef90146103405780639690ca56146103605780639cab9ce814610380578063b2a3a9a0146103a0578063b8fd5cf5146103c0578063bde5703f146103e0578063cc2a9a5b1461041d578063d63695381461043d578063f2fde38b1461045d578063f67dcf881461047d578063fe1e8e7e1461049d575b600080fd5b34801561014d57600080fd5b5061016161015c366004612364565b6104b9565b005b34801561016f57600080fd5b5061017b600160c01b81565b6040519081526020015b60405180910390f35b34801561019a57600080fd5b506101616101a9366004612364565b6104e3565b6101616101bc3660046123ec565b6105b5565b3480156101cd57600080fd5b5061017b61066f565b3480156101e257600080fd5b506101616101f1366004612497565b61071e565b34801561020257600080fd5b506101616102113660046124d9565b61079d565b34801561022257600080fd5b50610161610231366004612364565b610825565b34801561024257600080fd5b50610161610251366004612364565b610855565b34801561026257600080fd5b50610161610271366004612517565b61087f565b61017b610284366004612534565b61089a565b34801561029557600080fd5b50610161610c40565b3480156102aa57600080fd5b506102be6102b93660046125b8565b610c54565b60408051928352901515602083015201610185565b3480156102df57600080fd5b506101616102ee366004612364565b610cbe565b3480156102ff57600080fd5b5061016161030e366004612364565b610ce8565b34801561031f57600080fd5b50610328610d12565b6040516001600160a01b039091168152602001610185565b34801561034c57600080fd5b5061016161035b366004612617565b610d21565b34801561036c57600080fd5b5061017b61037b366004612658565b610de4565b34801561038c57600080fd5b5061016161039b3660046124d9565b610e32565b3480156103ac57600080fd5b506101616103bb3660046124d9565b610eba565b3480156103cc57600080fd5b506101616103db366004612364565b610f32565b3480156103ec57600080fd5b506104006103fb3660046125b8565b610f54565b604080519283526001600160a01b03909116602083015201610185565b34801561042957600080fd5b5061016161043836600461269b565b610fb7565b34801561044957600080fd5b5061040061045836600461271d565b611141565b34801561046957600080fd5b50610161610478366004612364565b61122b565b34801561048957600080fd5b5061040061049836600461271d565b6112a1565b3480156104a957600080fd5b5061017b670de0b6b3a764000081565b6104c16113a8565b606780546001600160a01b0319166001600160a01b0392909216919091179055565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156105355760405162461bcd60e51b815260040161052c9061274b565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610567611407565b6001600160a01b03161461058d5760405162461bcd60e51b815260040161052c90612785565b61059681611423565b604080516000808252602082019092526105b29183919061142b565b50565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156105fe5760405162461bcd60e51b815260040161052c9061274b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610630611407565b6001600160a01b0316146106565760405162461bcd60e51b815260040161052c90612785565b61065f82611423565b61066b8282600161142b565b5050565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461070a5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b606482015260840161052c565b50600080516020612d108339815191525b90565b6107266113a8565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb9061075490849086906004016127bf565b6020604051808303816000875af1158015610773573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079791906127e3565b50505050565b6107a56113a8565b60006107b18383611596565b60008181526066602052604090205490915060ff1661080b5760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1c9958591e481cdd589cda591a5e995960521b604482015260640161052c565b6000908152606660205260409020805460ff191690555050565b61082d6113a8565b606980546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b61085d6113a8565b606a80546001600160a01b0319166001600160a01b0392909216919091179055565b6108876113a8565b6069805460ff1916911515919091179055565b6065546000906001600160a01b031633146108bf576108bf639a04794d60e01b6115df565b6001600160a01b0385166108e4578334146108e4576108e46321ac1c7960e21b6115df565b60006108ee6115e9565b9050836001600160a01b0316816001600160a01b03161415610afe576000606461091987600a612800565b610923919061282d565b604051630a9d031560e01b8152600481018c90529091506000906001600160a01b03841690630a9d031590602401602060405180830381865afa15801561096e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610992919061285a565b90506001600160a01b038116158015906109b557506001600160a01b0381163214155b15610afb576001600160a01b038816610a39576000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610a15576040519150601f19603f3d011682016040523d82523d6000602084013e610a1a565b606091505b5050905080610a3357610a33637cd69c3960e11b6115df565b50610aac565b60405163a9059cbb60e01b81526001600160a01b0389169063a9059cbb90610a6790849086906004016127bf565b6020604051808303816000875af1158015610a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aaa91906127e3565b505b876001600160a01b0316816001600160a01b03168c7f01bf363dbade8c9713473bfb336069d6c556e904f84103f174b5ef488657196985604051610af291815260200190565b60405180910390a45b50505b8715610c2f57600083610b1b57610b1660028761282d565b610b32565b600a610b28876008612800565b610b32919061282d565b90506001600160a01b038716610bb3576000886001600160a01b03168260405160006040518083038185875af1925050503d8060008114610b8f576040519150601f19603f3d011682016040523d82523d6000602084013e610b94565b606091505b5050905080610bad57610bad637cd69c3960e11b6115df565b50610c26565b60405163a9059cbb60e01b81526001600160a01b0388169063a9059cbb90610be1908b9085906004016127bf565b6020604051808303816000875af1158015610c00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2491906127e3565b505b9150610c359050565b60009150505b979650505050505050565b610c486113a8565b610c526000611783565b565b6000806000610c62846117d5565b9050610c6e888761189d565b15610c7e57600092509050610cb4565b6001600160a01b038516610ca95786610c96826118c8565b610ca09190612800565b92509050610cb4565b610ca085888361194b565b9550959350505050565b610cc66113a8565b606b80546001600160a01b0319166001600160a01b0392909216919091179055565b610cf06113a8565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b6033546001600160a01b031690565b610d296113a8565b610d36602082018261288c565b6001600160601b031615801590610d6557506000610d5a6040830160208401612364565b6001600160a01b0316145b158015610dab5750610d7a602082018261288c565b6001600160601b0316158015610da957506000610d9d6040830160208401612364565b6001600160a01b031614155b155b15610dc057610dc06360c3620d60e11b6115df565b6001600160a01b0382166000908152606860205260409020819061079782826128a9565b6000610def84611aad565b80610dff5750610dff868461189d565b15610e0c57506000610e29565b8463ffffffff16610e1c83611e8a565b610e269190612800565b90505b95945050505050565b610e3a6113a8565b6000610e468383611596565b60008181526066602052604090205490915060ff1615610e9d5760405162461bcd60e51b8152602060048201526012602482015271105b1c9958591e481cdd589cda591a5e995960721b604482015260640161052c565b6000908152606660205260409020805460ff191660011790555050565b610ec26113a8565b6000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610f0f576040519150601f19603f3d011682016040523d82523d6000602084013e610f14565b606091505b5050905080610f2d57610f2d637cd69c3960e11b6115df565b505050565b610f3a6113a8565b6001600160a01b0316600090815260686020526040812055565b600080610f61878661189d565b15610f7157506000905082610cb4565b6001600160a01b03841615610f9557610f8b848785611ea1565b8491509150610cb4565b85610f9f84611e8a565b610fa99190612800565b976000975095505050505050565b600054610100900460ff1615808015610fd75750600054600160ff909116105b80610ff85750610fe630611fc1565b158015610ff8575060005460ff166001145b61105b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161052c565b6000805460ff19166001179055801561107e576000805461ff0019166101001790555b611086611fd0565b61108f86611783565b606580546001600160a01b03199081166001600160a01b038a81169190911790925560678054821688841617905560698054610100600160a81b03191661010088851602179055606a80548216868416179055606b80549091169184169190911790558015611138576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60655460405162820a0360e31b815260048101859052600091829182916001600160a01b03169063041050189060240160c060405180830381865afa15801561118e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b291906128eb565b80519091506001600160a01b03166111d4576111d463f8e6d17560e01b6115df565b6111e18160400151611aad565b806111f157506111f1868561189d565b15611203576000809250925050611223565b846112118260000151611e8a565b61121b9190612800565b600092509250505b935093915050565b6112336113a8565b6001600160a01b0381166112985760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161052c565b6105b281611783565b6000806112ae858461189d565b156112be57506000905080611223565b60655460405163228c835960e21b8152600481018790526000916001600160a01b031690638a320d64906024016101c060405180830381865afa158015611309573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132d91906129c0565b80519091506001600160a01b031661134f5761134f63f8e6d17560e01b6115df565b60c08101516001600160a01b031615611384576113758160c00151868360000151611ea1565b8160c001519250925050611223565b846113928260000151611e8a565b61139c9190612800565b60009250925050611223565b336113b1610d12565b6001600160a01b031614610c525760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161052c565b600080516020612d10833981519152546001600160a01b031690565b6105b26113a8565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561145e57610f2d83611fff565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156114b8575060408051601f3d908101601f191682019092526114b591810190612acb565b60015b61151b5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161052c565b600080516020612d10833981519152811461158a5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161052c565b50610f2d838383612099565b600082826040516020016115c192919091825260601b6001600160601b031916602082015260340190565b60405160208183030381529060405280519060200120905092915050565b8060005260046000fd5b6000466001141561160d575073d3c63951b2ed18e8d92b5b251c3b636a45a547d090565b466121051415611630575073d9e58978808d17f99ccceab5195b052e972c018890565b46600a14156116525750739cf5b12d2e2a88083647ff2fe0610f818b28ec7790565b466276adf114156116765750737cb2cecfcffdcce0bf69366e52caec6bd719cd4490565b4661a4b11415611699575073617b2383d93909590fac0b2aaa547ec5615d82ef90565b46608914156116bb5750736fd07d4b5fd7093762fb2f278769aa7e2511d45c90565b4662014a3414156116df5750734619b9673241eb41b642dc04371100d238b73ffe90565b4662aa36a71415611703575073d33c1be264bb98f86e18cd816d5fd44e97cb716390565b46620f043a14156117275750739491aa1c2f46319a645637c4105f4199b251e4dd90565b46611388141561174a575073affc7c9bfb48ffd2a580e1a0d36f8cc7d45dcb5890565b4662082750141561176e5750734821b6e9ac0ccc590acce2442bb6bb32388c1cb790565b5060695461010090046001600160a01b031690565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000816001600160a01b031663cbab0bd36040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611831575060408051601f3d908101601f1916820190925261182e91810190612acb565b60015b6118705761183d612ae4565b806308c379a014156118665750611852612aff565b8061185d5750611868565b50600092915050565b505b506000919050565b7f3a9654d81ac4dafbb9a2fb1cd3efa3de2783ae40b06b17a456bf5922ed02a3a71492915050565b919050565b6000606660006118ad8585611596565b815260208101919091526040016000205460ff169392505050565b600080826118d75760016118da565b60025b60ff1690504660891415611901576118fa81671f6ee57fe042800061282d565b9392505050565b46620f043a141561191e576118fa816706f05b59d3b2000061282d565b46611388141561193a576118fa816730927f74c9de000061282d565b6118fa816602d79883d2000061282d565b6001600160a01b0380841660009081526068602090815260408083208151808301909252546001600160601b0381168252600160601b90049093169083015290818361199857600161199b565b60025b60ff16905081600001516001600160601b03166000146119e057815185906119cd9083906001600160601b031661282d565b6119d79190612800565b925050506118fa565b60208201516001600160a01b031615611a9457600082602001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015611a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5b9190612b9a565b505050505050905085611a6d826120be565b611a76876118c8565b611a809190612800565b611a8a9190612800565b93505050506118fa565b611aa4630eca12dd60e31b6115df565b50509392505050565b60004660011415611b055773dfee0ed4a217f37b3fa87624ee00fe5685bdc5096001600160a01b0383161480611aff57507394fa6e7fc2555ada63ea56cfff425558360f00746001600160a01b038316145b92915050565b466121051415611b585773922e9f8cc491facbd403afa143aa53ee9146474c6001600160a01b0383161480611aff5750506001600160a01b031673a748be280c9a00edaf7d04076fe8a93c59e95b031490565b46600a1415611baa5773b207774ac4e32ece47771e64bde5ec3894c1de6b6001600160a01b0383161480611aff5750506001600160a01b03167315753e20667961fb30d5aa92e2255b876568be7e1490565b4661a4b11415611bfd57737f75358787f880506c5dc6100386f77be8de0a306001600160a01b0383161480611aff5750506001600160a01b0316733a2afe86e594540cbf3ea345dd29e09228f186d21490565b466276adf11415611c5157730afb6566c836d1c4788cd2b54bd9ca0158cc2d3d6001600160a01b0383161480611aff5750506001600160a01b031673f12a4018647dd2275072967fd5f3ac5fef7a04711490565b4660891415611ca357734ccb72e7e0cd948af50bc7bf598fc4e027b70f986001600160a01b0383161480611aff5750506001600160a01b031673ae22cd8052d64e7c2af6b5e3045fab0a86c8334c1490565b4662aa36a71415611cf75773a2d14ca9985de170db128c8cb74cecb35eeaf47e6001600160a01b0383161480611aff5750506001600160a01b031673cebc3b3134fbef95ed13aecdf997d4371d0223851490565b4662014a341415611d4b57739958f83f383ca150bb2252b4275d3e3051be469f6001600160a01b0383161480611aff5750506001600160a01b0316734821b6e9ac0ccc590acce2442bb6bb32388c1cb71490565b46620f043a1415611d9f57735aa1c7f5f9d2e7f2664d3c1f454560c6dabed6c86001600160a01b0383161480611aff5750506001600160a01b0316739c602ce508e41ccaf2cf997d93a9fbe0166d8ae61490565b466113881415611df25773d8f0a3aa4067be3d70a5b46a795ad9df9e65cd3c6001600160a01b0383161480611aff5750506001600160a01b031673af4d61951a425ba60ac1e7ea6d51e92d2f4748e41490565b46620827501415611e465773f6c67c7bb7018e4609d571023196a4682fda6f2f6001600160a01b0383161480611aff5750506001600160a01b031673e019ff8033d9c761985a3ee1fa5d97cc9cf6d5c01490565b606a546001600160a01b0383811691161480611e6f5750606b546001600160a01b038381169116145b80611aff5750506067546001600160a01b0390811691161490565b600080611e96836117d5565b6118d75760016118da565b6001600160a01b0380841660009081526068602090815260408083208151808301909252546001600160601b0381168252600160601b9004909316908301529081611eeb846117d5565b611ef6576001611ef9565b60025b60ff16905081600001516001600160601b0316600014611f2b57815185906119cd9083906001600160601b031661282d565b60208201516001600160a01b031615611a9457600082602001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015611f82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa69190612b9a565b505050505050905085611fb8826120be565b611a7687611e8a565b6001600160a01b03163b151590565b600054610100900460ff16611ff75760405162461bcd60e51b815260040161052c90612c29565b610c526120e9565b61200881611fc1565b61206a5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161052c565b600080516020612d1083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6120a283612119565b6000825111806120af5750805b15610f2d576107978383612159565b6000611aff6120d66001600160a01b03841680612800565b670de0b6b3a7640000600160c01b61217e565b600054610100900460ff166121105760405162461bcd60e51b815260040161052c90612c29565b610c5233611783565b61212281611fff565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606118fa8383604051806060016040528060278152602001612d3060279139612231565b6000808060001985870985870292508281108382030391505080600014156121b857600084116121ad57600080fd5b5082900490506118fa565b8084116121c457600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b6060600080856001600160a01b03168560405161224e9190612ca0565b600060405180830381855af49150503d8060008114612289576040519150601f19603f3d011682016040523d82523d6000602084013e61228e565b606091505b509150915061229f868383876122a9565b9695505050505050565b6060831561231357825161230c576122c085611fc1565b61230c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161052c565b508161231d565b61231d8383612325565b949350505050565b8151156123355781518083602001fd5b8060405162461bcd60e51b815260040161052c9190612cbc565b6001600160a01b03811681146105b257600080fd5b60006020828403121561237657600080fd5b81356118fa8161234f565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b03811182821017156123bc576123bc612381565b6040525050565b6040516101c081016001600160401b03811182821017156123e6576123e6612381565b60405290565b600080604083850312156123ff57600080fd5b823561240a8161234f565b91506020838101356001600160401b038082111561242757600080fd5b818601915086601f83011261243b57600080fd5b81358181111561244d5761244d612381565b6040519150612465601f8201601f1916850183612397565b808252878482850101111561247957600080fd5b80848401858401376000848284010152508093505050509250929050565b6000806000606084860312156124ac57600080fd5b83356124b78161234f565b92506020840135915060408401356124ce8161234f565b809150509250925092565b600080604083850312156124ec57600080fd5b8235915060208301356124fe8161234f565b809150509250929050565b80151581146105b257600080fd5b60006020828403121561252957600080fd5b81356118fa81612509565b600080600080600080600060e0888a03121561254f57600080fd5b87359650602088013561256181612509565b955060408801356125718161234f565b945060608801356125818161234f565b93506080880135925060a08801356125988161234f565b915060c08801356125a881612509565b8091505092959891949750929550565b600080600080600060a086880312156125d057600080fd5b853594506020860135935060408601356125e98161234f565b925060608601356125f98161234f565b915060808601356126098161234f565b809150509295509295909350565b600080828403606081121561262b57600080fd5b83356126368161234f565b92506040601f198201121561264a57600080fd5b506020830190509250929050565b600080600080600060a0868803121561267057600080fd5b85359450602086013563ffffffff8116811461268b57600080fd5b935060408601356125e98161234f565b60008060008060008060c087890312156126b457600080fd5b86356126bf8161234f565b955060208701356126cf8161234f565b945060408701356126df8161234f565b935060608701356126ef8161234f565b925060808701356126ff8161234f565b915060a087013561270f8161234f565b809150509295509295509295565b60008060006060848603121561273257600080fd5b833592506020840135915060408401356124ce8161234f565b6020808252602c90820152600080516020612cf083398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c90820152600080516020612cf083398151915260408201526b6163746976652070726f787960a01b606082015260800190565b6001600160a01b03929092168252602082015260400190565b805161189881612509565b6000602082840312156127f557600080fd5b81516118fa81612509565b600081600019048311821515161561282857634e487b7160e01b600052601160045260246000fd5b500290565b60008261284a57634e487b7160e01b600052601260045260246000fd5b500490565b80516118988161234f565b60006020828403121561286c57600080fd5b81516118fa8161234f565b6001600160601b03811681146105b257600080fd5b60006020828403121561289e57600080fd5b81356118fa81612877565b81356128b481612877565b81546001600160601b03199081166001600160601b0392909216918217835560208401356128e18161234f565b60601b1617905550565b600060c082840312156128fd57600080fd5b60405160c081016001600160401b038111828210171561291f5761291f612381565b604052825161292d8161234f565b8152602083015161293d81612877565b602082015260408301516129508161234f565b6040820152606083015161296381612509565b6060820152608083015161297681612509565b608082015261298760a084016127d8565b60a08201529392505050565b805165ffffffffffff8116811461189857600080fd5b80516001600160c01b038116811461189857600080fd5b60006101c082840312156129d357600080fd5b6129db6123c3565b6129e48361284f565b81526129f260208401612993565b6020820152612a0360408401612993565b6040820152612a146060840161284f565b6060820152612a2560808401612993565b6080820152612a3660a08401612993565b60a0820152612a4760c0840161284f565b60c0820152612a5860e08401612993565b60e0820152610100612a6b818501612993565b90820152610120612a7d8482016129a9565b90820152610140612a8f848201612993565b90820152610160612aa18482016127d8565b90820152610180612ab38482016127d8565b908201526101a0928301519281019290925250919050565b600060208284031215612add57600080fd5b5051919050565b600060033d111561071b5760046000803e5060005160e01c90565b600060443d1015612b0d5790565b6040516003193d81016004833e81513d6001600160401b038083116024840183101715612b3c57505050505090565b8285019150815181811115612b545750505050505090565b843d8701016020828501011115612b6e5750505050505090565b612b7d60208286010187612397565b509095945050505050565b805161ffff8116811461189857600080fd5b600080600080600080600060e0888a031215612bb557600080fd5b8751612bc08161234f565b8097505060208801518060020b8114612bd857600080fd5b9550612be660408901612b88565b9450612bf460608901612b88565b9350612c0260808901612b88565b925060a088015160ff81168114612c1857600080fd5b60c08901519092506125a881612509565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60005b83811015612c8f578181015183820152602001612c77565b838111156107975750506000910152565b60008251612cb2818460208701612c74565b9190910192915050565b6020815260008251806020840152612cdb816040850160208701612c74565b601f01601f1916919091016040019291505056fe46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080a000a
Deployed Bytecode
0x60806040526004361061013c5760003560e01c80632d6829b2146101415780632dda7bc5146101635780633659cfe61461018e5780634f1ef286146101ae57806352d1902d146101c15780635fc3ea0b146101d657806362a31a09146101f657806362e03bcc14610216578063639c93da146102365780636478cd98146102565780636f18e93f14610276578063715018a61461028957806376c198931461029e578063860caf0a146102d35780638830eac0146102f35780638da5cb5b146103135780639247ef90146103405780639690ca56146103605780639cab9ce814610380578063b2a3a9a0146103a0578063b8fd5cf5146103c0578063bde5703f146103e0578063cc2a9a5b1461041d578063d63695381461043d578063f2fde38b1461045d578063f67dcf881461047d578063fe1e8e7e1461049d575b600080fd5b34801561014d57600080fd5b5061016161015c366004612364565b6104b9565b005b34801561016f57600080fd5b5061017b600160c01b81565b6040519081526020015b60405180910390f35b34801561019a57600080fd5b506101616101a9366004612364565b6104e3565b6101616101bc3660046123ec565b6105b5565b3480156101cd57600080fd5b5061017b61066f565b3480156101e257600080fd5b506101616101f1366004612497565b61071e565b34801561020257600080fd5b506101616102113660046124d9565b61079d565b34801561022257600080fd5b50610161610231366004612364565b610825565b34801561024257600080fd5b50610161610251366004612364565b610855565b34801561026257600080fd5b50610161610271366004612517565b61087f565b61017b610284366004612534565b61089a565b34801561029557600080fd5b50610161610c40565b3480156102aa57600080fd5b506102be6102b93660046125b8565b610c54565b60408051928352901515602083015201610185565b3480156102df57600080fd5b506101616102ee366004612364565b610cbe565b3480156102ff57600080fd5b5061016161030e366004612364565b610ce8565b34801561031f57600080fd5b50610328610d12565b6040516001600160a01b039091168152602001610185565b34801561034c57600080fd5b5061016161035b366004612617565b610d21565b34801561036c57600080fd5b5061017b61037b366004612658565b610de4565b34801561038c57600080fd5b5061016161039b3660046124d9565b610e32565b3480156103ac57600080fd5b506101616103bb3660046124d9565b610eba565b3480156103cc57600080fd5b506101616103db366004612364565b610f32565b3480156103ec57600080fd5b506104006103fb3660046125b8565b610f54565b604080519283526001600160a01b03909116602083015201610185565b34801561042957600080fd5b5061016161043836600461269b565b610fb7565b34801561044957600080fd5b5061040061045836600461271d565b611141565b34801561046957600080fd5b50610161610478366004612364565b61122b565b34801561048957600080fd5b5061040061049836600461271d565b6112a1565b3480156104a957600080fd5b5061017b670de0b6b3a764000081565b6104c16113a8565b606780546001600160a01b0319166001600160a01b0392909216919091179055565b306001600160a01b037f00000000000000000000000069c589fd9d6a706aa25d862967363458bb47ec931614156105355760405162461bcd60e51b815260040161052c9061274b565b60405180910390fd5b7f00000000000000000000000069c589fd9d6a706aa25d862967363458bb47ec936001600160a01b0316610567611407565b6001600160a01b03161461058d5760405162461bcd60e51b815260040161052c90612785565b61059681611423565b604080516000808252602082019092526105b29183919061142b565b50565b306001600160a01b037f00000000000000000000000069c589fd9d6a706aa25d862967363458bb47ec931614156105fe5760405162461bcd60e51b815260040161052c9061274b565b7f00000000000000000000000069c589fd9d6a706aa25d862967363458bb47ec936001600160a01b0316610630611407565b6001600160a01b0316146106565760405162461bcd60e51b815260040161052c90612785565b61065f82611423565b61066b8282600161142b565b5050565b6000306001600160a01b037f00000000000000000000000069c589fd9d6a706aa25d862967363458bb47ec93161461070a5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b606482015260840161052c565b50600080516020612d108339815191525b90565b6107266113a8565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb9061075490849086906004016127bf565b6020604051808303816000875af1158015610773573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079791906127e3565b50505050565b6107a56113a8565b60006107b18383611596565b60008181526066602052604090205490915060ff1661080b5760405162461bcd60e51b8152602060048201526016602482015275139bdd08185b1c9958591e481cdd589cda591a5e995960521b604482015260640161052c565b6000908152606660205260409020805460ff191690555050565b61082d6113a8565b606980546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b61085d6113a8565b606a80546001600160a01b0319166001600160a01b0392909216919091179055565b6108876113a8565b6069805460ff1916911515919091179055565b6065546000906001600160a01b031633146108bf576108bf639a04794d60e01b6115df565b6001600160a01b0385166108e4578334146108e4576108e46321ac1c7960e21b6115df565b60006108ee6115e9565b9050836001600160a01b0316816001600160a01b03161415610afe576000606461091987600a612800565b610923919061282d565b604051630a9d031560e01b8152600481018c90529091506000906001600160a01b03841690630a9d031590602401602060405180830381865afa15801561096e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610992919061285a565b90506001600160a01b038116158015906109b557506001600160a01b0381163214155b15610afb576001600160a01b038816610a39576000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610a15576040519150601f19603f3d011682016040523d82523d6000602084013e610a1a565b606091505b5050905080610a3357610a33637cd69c3960e11b6115df565b50610aac565b60405163a9059cbb60e01b81526001600160a01b0389169063a9059cbb90610a6790849086906004016127bf565b6020604051808303816000875af1158015610a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aaa91906127e3565b505b876001600160a01b0316816001600160a01b03168c7f01bf363dbade8c9713473bfb336069d6c556e904f84103f174b5ef488657196985604051610af291815260200190565b60405180910390a45b50505b8715610c2f57600083610b1b57610b1660028761282d565b610b32565b600a610b28876008612800565b610b32919061282d565b90506001600160a01b038716610bb3576000886001600160a01b03168260405160006040518083038185875af1925050503d8060008114610b8f576040519150601f19603f3d011682016040523d82523d6000602084013e610b94565b606091505b5050905080610bad57610bad637cd69c3960e11b6115df565b50610c26565b60405163a9059cbb60e01b81526001600160a01b0388169063a9059cbb90610be1908b9085906004016127bf565b6020604051808303816000875af1158015610c00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2491906127e3565b505b9150610c359050565b60009150505b979650505050505050565b610c486113a8565b610c526000611783565b565b6000806000610c62846117d5565b9050610c6e888761189d565b15610c7e57600092509050610cb4565b6001600160a01b038516610ca95786610c96826118c8565b610ca09190612800565b92509050610cb4565b610ca085888361194b565b9550959350505050565b610cc66113a8565b606b80546001600160a01b0319166001600160a01b0392909216919091179055565b610cf06113a8565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b6033546001600160a01b031690565b610d296113a8565b610d36602082018261288c565b6001600160601b031615801590610d6557506000610d5a6040830160208401612364565b6001600160a01b0316145b158015610dab5750610d7a602082018261288c565b6001600160601b0316158015610da957506000610d9d6040830160208401612364565b6001600160a01b031614155b155b15610dc057610dc06360c3620d60e11b6115df565b6001600160a01b0382166000908152606860205260409020819061079782826128a9565b6000610def84611aad565b80610dff5750610dff868461189d565b15610e0c57506000610e29565b8463ffffffff16610e1c83611e8a565b610e269190612800565b90505b95945050505050565b610e3a6113a8565b6000610e468383611596565b60008181526066602052604090205490915060ff1615610e9d5760405162461bcd60e51b8152602060048201526012602482015271105b1c9958591e481cdd589cda591a5e995960721b604482015260640161052c565b6000908152606660205260409020805460ff191660011790555050565b610ec26113a8565b6000816001600160a01b03168360405160006040518083038185875af1925050503d8060008114610f0f576040519150601f19603f3d011682016040523d82523d6000602084013e610f14565b606091505b5050905080610f2d57610f2d637cd69c3960e11b6115df565b505050565b610f3a6113a8565b6001600160a01b0316600090815260686020526040812055565b600080610f61878661189d565b15610f7157506000905082610cb4565b6001600160a01b03841615610f9557610f8b848785611ea1565b8491509150610cb4565b85610f9f84611e8a565b610fa99190612800565b976000975095505050505050565b600054610100900460ff1615808015610fd75750600054600160ff909116105b80610ff85750610fe630611fc1565b158015610ff8575060005460ff166001145b61105b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161052c565b6000805460ff19166001179055801561107e576000805461ff0019166101001790555b611086611fd0565b61108f86611783565b606580546001600160a01b03199081166001600160a01b038a81169190911790925560678054821688841617905560698054610100600160a81b03191661010088851602179055606a80548216868416179055606b80549091169184169190911790558015611138576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60655460405162820a0360e31b815260048101859052600091829182916001600160a01b03169063041050189060240160c060405180830381865afa15801561118e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b291906128eb565b80519091506001600160a01b03166111d4576111d463f8e6d17560e01b6115df565b6111e18160400151611aad565b806111f157506111f1868561189d565b15611203576000809250925050611223565b846112118260000151611e8a565b61121b9190612800565b600092509250505b935093915050565b6112336113a8565b6001600160a01b0381166112985760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161052c565b6105b281611783565b6000806112ae858461189d565b156112be57506000905080611223565b60655460405163228c835960e21b8152600481018790526000916001600160a01b031690638a320d64906024016101c060405180830381865afa158015611309573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132d91906129c0565b80519091506001600160a01b031661134f5761134f63f8e6d17560e01b6115df565b60c08101516001600160a01b031615611384576113758160c00151868360000151611ea1565b8160c001519250925050611223565b846113928260000151611e8a565b61139c9190612800565b60009250925050611223565b336113b1610d12565b6001600160a01b031614610c525760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161052c565b600080516020612d10833981519152546001600160a01b031690565b6105b26113a8565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561145e57610f2d83611fff565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156114b8575060408051601f3d908101601f191682019092526114b591810190612acb565b60015b61151b5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161052c565b600080516020612d10833981519152811461158a5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161052c565b50610f2d838383612099565b600082826040516020016115c192919091825260601b6001600160601b031916602082015260340190565b60405160208183030381529060405280519060200120905092915050565b8060005260046000fd5b6000466001141561160d575073d3c63951b2ed18e8d92b5b251c3b636a45a547d090565b466121051415611630575073d9e58978808d17f99ccceab5195b052e972c018890565b46600a14156116525750739cf5b12d2e2a88083647ff2fe0610f818b28ec7790565b466276adf114156116765750737cb2cecfcffdcce0bf69366e52caec6bd719cd4490565b4661a4b11415611699575073617b2383d93909590fac0b2aaa547ec5615d82ef90565b46608914156116bb5750736fd07d4b5fd7093762fb2f278769aa7e2511d45c90565b4662014a3414156116df5750734619b9673241eb41b642dc04371100d238b73ffe90565b4662aa36a71415611703575073d33c1be264bb98f86e18cd816d5fd44e97cb716390565b46620f043a14156117275750739491aa1c2f46319a645637c4105f4199b251e4dd90565b46611388141561174a575073affc7c9bfb48ffd2a580e1a0d36f8cc7d45dcb5890565b4662082750141561176e5750734821b6e9ac0ccc590acce2442bb6bb32388c1cb790565b5060695461010090046001600160a01b031690565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000816001600160a01b031663cbab0bd36040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611831575060408051601f3d908101601f1916820190925261182e91810190612acb565b60015b6118705761183d612ae4565b806308c379a014156118665750611852612aff565b8061185d5750611868565b50600092915050565b505b506000919050565b7f3a9654d81ac4dafbb9a2fb1cd3efa3de2783ae40b06b17a456bf5922ed02a3a71492915050565b919050565b6000606660006118ad8585611596565b815260208101919091526040016000205460ff169392505050565b600080826118d75760016118da565b60025b60ff1690504660891415611901576118fa81671f6ee57fe042800061282d565b9392505050565b46620f043a141561191e576118fa816706f05b59d3b2000061282d565b46611388141561193a576118fa816730927f74c9de000061282d565b6118fa816602d79883d2000061282d565b6001600160a01b0380841660009081526068602090815260408083208151808301909252546001600160601b0381168252600160601b90049093169083015290818361199857600161199b565b60025b60ff16905081600001516001600160601b03166000146119e057815185906119cd9083906001600160601b031661282d565b6119d79190612800565b925050506118fa565b60208201516001600160a01b031615611a9457600082602001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015611a37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5b9190612b9a565b505050505050905085611a6d826120be565b611a76876118c8565b611a809190612800565b611a8a9190612800565b93505050506118fa565b611aa4630eca12dd60e31b6115df565b50509392505050565b60004660011415611b055773dfee0ed4a217f37b3fa87624ee00fe5685bdc5096001600160a01b0383161480611aff57507394fa6e7fc2555ada63ea56cfff425558360f00746001600160a01b038316145b92915050565b466121051415611b585773922e9f8cc491facbd403afa143aa53ee9146474c6001600160a01b0383161480611aff5750506001600160a01b031673a748be280c9a00edaf7d04076fe8a93c59e95b031490565b46600a1415611baa5773b207774ac4e32ece47771e64bde5ec3894c1de6b6001600160a01b0383161480611aff5750506001600160a01b03167315753e20667961fb30d5aa92e2255b876568be7e1490565b4661a4b11415611bfd57737f75358787f880506c5dc6100386f77be8de0a306001600160a01b0383161480611aff5750506001600160a01b0316733a2afe86e594540cbf3ea345dd29e09228f186d21490565b466276adf11415611c5157730afb6566c836d1c4788cd2b54bd9ca0158cc2d3d6001600160a01b0383161480611aff5750506001600160a01b031673f12a4018647dd2275072967fd5f3ac5fef7a04711490565b4660891415611ca357734ccb72e7e0cd948af50bc7bf598fc4e027b70f986001600160a01b0383161480611aff5750506001600160a01b031673ae22cd8052d64e7c2af6b5e3045fab0a86c8334c1490565b4662aa36a71415611cf75773a2d14ca9985de170db128c8cb74cecb35eeaf47e6001600160a01b0383161480611aff5750506001600160a01b031673cebc3b3134fbef95ed13aecdf997d4371d0223851490565b4662014a341415611d4b57739958f83f383ca150bb2252b4275d3e3051be469f6001600160a01b0383161480611aff5750506001600160a01b0316734821b6e9ac0ccc590acce2442bb6bb32388c1cb71490565b46620f043a1415611d9f57735aa1c7f5f9d2e7f2664d3c1f454560c6dabed6c86001600160a01b0383161480611aff5750506001600160a01b0316739c602ce508e41ccaf2cf997d93a9fbe0166d8ae61490565b466113881415611df25773d8f0a3aa4067be3d70a5b46a795ad9df9e65cd3c6001600160a01b0383161480611aff5750506001600160a01b031673af4d61951a425ba60ac1e7ea6d51e92d2f4748e41490565b46620827501415611e465773f6c67c7bb7018e4609d571023196a4682fda6f2f6001600160a01b0383161480611aff5750506001600160a01b031673e019ff8033d9c761985a3ee1fa5d97cc9cf6d5c01490565b606a546001600160a01b0383811691161480611e6f5750606b546001600160a01b038381169116145b80611aff5750506067546001600160a01b0390811691161490565b600080611e96836117d5565b6118d75760016118da565b6001600160a01b0380841660009081526068602090815260408083208151808301909252546001600160601b0381168252600160601b9004909316908301529081611eeb846117d5565b611ef6576001611ef9565b60025b60ff16905081600001516001600160601b0316600014611f2b57815185906119cd9083906001600160601b031661282d565b60208201516001600160a01b031615611a9457600082602001516001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa158015611f82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa69190612b9a565b505050505050905085611fb8826120be565b611a7687611e8a565b6001600160a01b03163b151590565b600054610100900460ff16611ff75760405162461bcd60e51b815260040161052c90612c29565b610c526120e9565b61200881611fc1565b61206a5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161052c565b600080516020612d1083398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6120a283612119565b6000825111806120af5750805b15610f2d576107978383612159565b6000611aff6120d66001600160a01b03841680612800565b670de0b6b3a7640000600160c01b61217e565b600054610100900460ff166121105760405162461bcd60e51b815260040161052c90612c29565b610c5233611783565b61212281611fff565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606118fa8383604051806060016040528060278152602001612d3060279139612231565b6000808060001985870985870292508281108382030391505080600014156121b857600084116121ad57600080fd5b5082900490506118fa565b8084116121c457600080fd5b6000848688096000868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b6060600080856001600160a01b03168560405161224e9190612ca0565b600060405180830381855af49150503d8060008114612289576040519150601f19603f3d011682016040523d82523d6000602084013e61228e565b606091505b509150915061229f868383876122a9565b9695505050505050565b6060831561231357825161230c576122c085611fc1565b61230c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161052c565b508161231d565b61231d8383612325565b949350505050565b8151156123355781518083602001fd5b8060405162461bcd60e51b815260040161052c9190612cbc565b6001600160a01b03811681146105b257600080fd5b60006020828403121561237657600080fd5b81356118fa8161234f565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b03811182821017156123bc576123bc612381565b6040525050565b6040516101c081016001600160401b03811182821017156123e6576123e6612381565b60405290565b600080604083850312156123ff57600080fd5b823561240a8161234f565b91506020838101356001600160401b038082111561242757600080fd5b818601915086601f83011261243b57600080fd5b81358181111561244d5761244d612381565b6040519150612465601f8201601f1916850183612397565b808252878482850101111561247957600080fd5b80848401858401376000848284010152508093505050509250929050565b6000806000606084860312156124ac57600080fd5b83356124b78161234f565b92506020840135915060408401356124ce8161234f565b809150509250925092565b600080604083850312156124ec57600080fd5b8235915060208301356124fe8161234f565b809150509250929050565b80151581146105b257600080fd5b60006020828403121561252957600080fd5b81356118fa81612509565b600080600080600080600060e0888a03121561254f57600080fd5b87359650602088013561256181612509565b955060408801356125718161234f565b945060608801356125818161234f565b93506080880135925060a08801356125988161234f565b915060c08801356125a881612509565b8091505092959891949750929550565b600080600080600060a086880312156125d057600080fd5b853594506020860135935060408601356125e98161234f565b925060608601356125f98161234f565b915060808601356126098161234f565b809150509295509295909350565b600080828403606081121561262b57600080fd5b83356126368161234f565b92506040601f198201121561264a57600080fd5b506020830190509250929050565b600080600080600060a0868803121561267057600080fd5b85359450602086013563ffffffff8116811461268b57600080fd5b935060408601356125e98161234f565b60008060008060008060c087890312156126b457600080fd5b86356126bf8161234f565b955060208701356126cf8161234f565b945060408701356126df8161234f565b935060608701356126ef8161234f565b925060808701356126ff8161234f565b915060a087013561270f8161234f565b809150509295509295509295565b60008060006060848603121561273257600080fd5b833592506020840135915060408401356124ce8161234f565b6020808252602c90820152600080516020612cf083398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c90820152600080516020612cf083398151915260408201526b6163746976652070726f787960a01b606082015260800190565b6001600160a01b03929092168252602082015260400190565b805161189881612509565b6000602082840312156127f557600080fd5b81516118fa81612509565b600081600019048311821515161561282857634e487b7160e01b600052601160045260246000fd5b500290565b60008261284a57634e487b7160e01b600052601260045260246000fd5b500490565b80516118988161234f565b60006020828403121561286c57600080fd5b81516118fa8161234f565b6001600160601b03811681146105b257600080fd5b60006020828403121561289e57600080fd5b81356118fa81612877565b81356128b481612877565b81546001600160601b03199081166001600160601b0392909216918217835560208401356128e18161234f565b60601b1617905550565b600060c082840312156128fd57600080fd5b60405160c081016001600160401b038111828210171561291f5761291f612381565b604052825161292d8161234f565b8152602083015161293d81612877565b602082015260408301516129508161234f565b6040820152606083015161296381612509565b6060820152608083015161297681612509565b608082015261298760a084016127d8565b60a08201529392505050565b805165ffffffffffff8116811461189857600080fd5b80516001600160c01b038116811461189857600080fd5b60006101c082840312156129d357600080fd5b6129db6123c3565b6129e48361284f565b81526129f260208401612993565b6020820152612a0360408401612993565b6040820152612a146060840161284f565b6060820152612a2560808401612993565b6080820152612a3660a08401612993565b60a0820152612a4760c0840161284f565b60c0820152612a5860e08401612993565b60e0820152610100612a6b818501612993565b90820152610120612a7d8482016129a9565b90820152610140612a8f848201612993565b90820152610160612aa18482016127d8565b90820152610180612ab38482016127d8565b908201526101a0928301519281019290925250919050565b600060208284031215612add57600080fd5b5051919050565b600060033d111561071b5760046000803e5060005160e01c90565b600060443d1015612b0d5790565b6040516003193d81016004833e81513d6001600160401b038083116024840183101715612b3c57505050505090565b8285019150815181811115612b545750505050505090565b843d8701016020828501011115612b6e5750505050505090565b612b7d60208286010187612397565b509095945050505050565b805161ffff8116811461189857600080fd5b600080600080600080600060e0888a031215612bb557600080fd5b8751612bc08161234f565b8097505060208801518060020b8114612bd857600080fd5b9550612be660408901612b88565b9450612bf460608901612b88565b9350612c0260808901612b88565b925060a088015160ff81168114612c1857600080fd5b60c08901519092506125a881612509565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60005b83811015612c8f578181015183820152602001612c77565b838111156107975750506000910152565b60008251612cb2818460208701612c74565b9190910192915050565b6020815260008251806020840152612cdb816040850160208701612c74565b601f01601f1916919091016040019291505056fe46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080a000a
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.