Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
MintManager
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: UNLICENSED pragma solidity 0.8.10; import "../utils/Ownable.sol"; import "../erc721/interfaces/IERC721GeneralMint.sol"; import "../erc721/interfaces/IERC721EditionMint.sol"; import "../utils/ERC721/IERC721.sol"; import "./interfaces/INativeMetaTransaction.sol"; import "../utils/EIP712Upgradeable.sol"; import "../metatx/ERC2771ContextUpgradeable.sol"; import "./interfaces/IAbridgedMintVector.sol"; import "./mechanics/interfaces/IMechanicMintManager.sol"; import "./mechanics/interfaces/IMechanic.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; /** * @title MintManager * @author highlight.xyz * @notice Faciliates lion's share of minting in Highlight protocol V2 by managing mint "vectors" on-chain and off-chain */ contract MintManager is EIP712Upgradeable, UUPSUpgradeable, OwnableUpgradeable, ERC2771ContextUpgradeable, IAbridgedMintVector, IMechanicMintManager { using ECDSA for bytes32; using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.AddressSet; /** * @notice Throw when sender is unauthorized to complete action */ error Unauthorized(); /** * @notice Throw when the executor being added or removed is invalid */ error InvalidExecutorChanged(); /** * @notice Throw when the action being applied to the vector has been frozen */ error VectorUpdateActionFrozen(); /** * @notice Throw when the totalClaimedViaVector passed in is invalid */ error InvalidTotalClaimed(); /** * @notice Throw when an invalid allowlist proof is used, or a regular mint is attempted on an allowlist vector */ error AllowlistInvalid(); /** * @notice Throw when a native gas token payment is attempted on a payment packet mint */ error CurrencyTypeInvalid(); /** * @notice Throw when the mint fee sent is too low */ error MintFeeTooLow(); /** * @notice Throw when an internal transfer of ether fails */ error EtherSendFailed(); /** * @notice Throw when a transaction signer is not the claimer passed in via a claim */ error SenderNotClaimer(); /** * @notice Throw when a claim is invalid */ error InvalidClaim(); /** * @notice Throw when an invalid amount is sent for a payment (native gas token or erc20) */ error InvalidPaymentAmount(); /** * @notice Throw when an on-chain mint vector's config parameter isn't met */ error OnchainVectorMintGuardFailed(); /** * @notice Throw when a mint is tried on a vector of the * wrong collection type (edition -> series, series -> edition) */ error VectorWrongCollectionType(); /** * @notice Throw when msgSender is not directly an EOA */ error SenderNotDirectEOA(); /** * @notice Throw when a mint recipient on a gated claim is different from the claimer, * and tx sender is not the claimer */ error UnsafeMintRecipient(); /** * @notice Throw when a mint is paused. */ error MintPaused(); /** * @notice Throw when an entity is already registered with a given ID */ error AlreadyRegisteredWithId(); /** * @notice Throw when a mechanic is invalid */ error InvalidMechanic(); /** * @notice Throw when a mechanic is paused */ error MechanicPaused(); /** * @notice On-chain mint vector * @param contractAddress NFT smart contract address * @param currency Currency used for payment. Native gas token, if zero address * @param paymentRecipient Payment recipient * @param startTimestamp When minting opens on vector * @param endTimestamp When minting ends on vector * @param pricePerToken Price that has to be paid per minted token * @param tokenLimitPerTx Max number of tokens that can be minted in one transaction * @param maxTotalClaimableViaVector Max number of tokens that can be minted via vector * @param maxUserClaimableViaVector Max number of tokens that can be minted by user via vector * @param totalClaimedViaVector Total number of tokens minted via vector * @param allowlistRoot Root of merkle tree with allowlist * @param paused If vector is paused */ struct Vector { address contractAddress; address currency; address payable paymentRecipient; uint256 startTimestamp; uint256 endTimestamp; uint256 pricePerToken; uint64 tokenLimitPerTx; uint64 maxTotalClaimableViaVector; uint64 maxUserClaimableViaVector; uint64 totalClaimedViaVector; bytes32 allowlistRoot; uint8 paused; } /** * @notice On-chain mint vector mutability rules * @param updatesFrozen If true, vector cannot be updated * @param deleteFrozen If true, vector cannot be deleted * @param pausesFrozen If true, vector cannot be paused */ struct VectorMutability { uint8 updatesFrozen; uint8 deleteFrozen; uint8 pausesFrozen; } /** * @notice Packet enabling impersonation of purchaser for currencies supporting meta-transactions * @param functionSignature Function to call on contract, with arguments encoded * @param sigR Elliptic curve signature component * @param sigS Elliptic curve signature component * @param sigV Elliptic curve signature component */ struct PurchaserMetaTxPacket { bytes functionSignature; bytes32 sigR; bytes32 sigS; uint8 sigV; } /** * @notice Claim that is signed off-chain with EIP-712, and unwrapped to facilitate fulfillment of mint * @param currency Currency used for payment. Native gas token, if zero address * @param contractAddress NFT smart contract address * @param claimer Account able to use this claim * @param paymentRecipient Payment recipient * @param pricePerToken Price that has to be paid per minted token * @param numTokensToMint Number of NFTs to mint in this transaction * @param maxClaimableViaVector Max number of tokens that can be minted via vector * @param maxClaimablePerUser Max number of tokens that can be minted by user via vector * @param editionId ID of edition to mint on. Unused if claim is passed into ERC721General minting function * @param claimExpiryTimestamp Time when claim expires * @param claimNonce Unique identifier of claim * @param offchainVectorId Unique identifier of vector offchain */ struct Claim { address currency; address contractAddress; address claimer; address payable paymentRecipient; uint256 pricePerToken; uint64 numTokensToMint; uint256 maxClaimableViaVector; uint256 maxClaimablePerUser; uint256 editionId; uint256 claimExpiryTimestamp; bytes32 claimNonce; bytes32 offchainVectorId; } /** * @notice Claim that is signed off-chain with EIP-712, and unwrapped to facilitate fulfillment of mint on a Series * @dev Max number claimable per transaction is enforced off-chain * @param currency Currency used for payment. Native gas token, if zero address * @param contractAddress NFT smart contract address * @param claimer Account able to use this claim * @param paymentRecipient Payment recipient * @param pricePerToken Price that has to be paid per minted token * @param maxPerTxn Max number of tokens that can be minted in a transaction * @param maxClaimableViaVector Max number of tokens that can be minted via vector * @param maxClaimablePerUser Max number of tokens that can be minted by user via vector * @param claimExpiryTimestamp Time when claim expires * @param claimNonce Unique identifier of claim * @param offchainVectorId Unique identifier of vector offchain */ struct SeriesClaim { address currency; address contractAddress; address claimer; address payable paymentRecipient; uint256 pricePerToken; uint64 maxPerTxn; uint64 maxClaimableViaVector; uint64 maxClaimablePerUser; uint64 claimExpiryTimestamp; bytes32 claimNonce; bytes32 offchainVectorId; } /** * @notice Tracks current claim state of offchain vectors * @param numClaimed Total claimed on vector * @param numClaimedPerUser Tracks totals claimed per user on vector */ struct OffchainVectorClaimState { uint256 numClaimed; mapping(address => uint256) numClaimedPerUser; } /* solhint-disable max-line-length */ /** * @notice DEPRECATED - Claim typehash used via typed structured data hashing (EIP-712) */ bytes32 private constant _CLAIM_TYPEHASH = keccak256( "Claim(address currency,address contractAddress,address claimer,address paymentRecipient,uint256 pricePerToken,uint64 numTokensToMint,uint256 maxClaimableViaVector,uint256 maxClaimablePerUser,uint256 editionId,uint256 claimExpiryTimestamp,bytes32 claimNonce,bytes32 offchainVectorId)" ); /** * @notice DEPRECATED - Claim typehash used via typed structured data hashing (EIP-712) */ bytes32 private constant _CLAIM_WITH_META_TX_PACKET_TYPEHASH = keccak256( "ClaimWithMetaTxPacket(address currency,address contractAddress,address claimer,uint256 pricePerToken,uint64 numTokensToMint,PurchaserMetaTxPacket purchaseToCreatorPacket,PurchaserMetaTxPacket purchaseToCreatorPacket,uint256 maxClaimableViaVector,uint256 maxClaimablePerUser,uint256 editionId,uint256 claimExpiryTimestamp,bytes32 claimNonce,bytes32 offchainVectorId)" ); /* solhint-enable max-line-length */ /** * @notice Platform receiving portion of payment */ address payable private _platform; /** * @notice System-wide mint vectors */ mapping(uint256 => Vector) public vectors; /** * @notice System-wide mint vectors' mutabilities */ mapping(uint256 => VectorMutability) public vectorMutabilities; /** * @notice System-wide vector ids to (user to user claims count) */ mapping(uint256 => mapping(address => uint64)) public userClaims; /** * @notice Tracks what nonces used in signed mint keys have been used for vectors enforced offchain * Requires the platform to not re-use offchain vector IDs. */ mapping(bytes32 => EnumerableSet.Bytes32Set) private _offchainVectorsToNoncesUsed; /** * @notice Tracks running state of offchain vectors */ mapping(bytes32 => OffchainVectorClaimState) public offchainVectorsClaimState; /** * @notice Maps vector ids to edition ids */ mapping(uint256 => uint256) public vectorToEditionId; /** * @notice Current vector id index */ uint256 private _vectorSupply; /** * @notice Platform transaction executors */ EnumerableSet.AddressSet internal _platformExecutors; /** * @notice Platform mint fee */ uint256 private _platformMintFee; /** * @notice System-wide mint vectors */ mapping(uint256 => AbridgedVectorData) private _abridgedVectors; /** * @notice Extra data about an abridged mint vector * Bits Layout: * - [0] `paused` * - [1..127] `unused` (for now) * - [128..255] `flexible data` */ mapping(uint256 => uint256) private _abridgedVectorMetadata; /** @notice The bit position of `flexibleData` in packed abridged vector metadata. */ uint256 private constant _BITPOS_AV_FLEXIBLE_DATA = 128; /** @notice The bitmask of `paused` in packed abridged vector metadata. */ uint256 private constant _BITMASK_AV_PAUSED = 1; /** * @notice Global mechanic vector metadatas */ mapping(bytes32 => MechanicVectorMetadata) public mechanicVectorMetadata; /** * @notice Emitted when platform executor is added or removed * @param executor Changed executor * @param added True if executor was added and false otherwise */ event PlatformExecutorChanged(address indexed executor, bool indexed added); /** * @notice Emitted when vector for edition based colletction is created on-chain * @param vectorId ID of vector * @param editionId Edition id of vector * @param contractAddress Collection contract address */ event EditionVectorCreated(uint256 indexed vectorId, uint48 indexed editionId, address indexed contractAddress); /** * @notice Emitted when vector for series based collection is created on-chain * @param vectorId ID of vector * @param contractAddress Collection contract address */ event SeriesVectorCreated(uint256 indexed vectorId, address indexed contractAddress); /** * @notice Emitted when vector is updated on-chain * @param vectorId ID of vector */ event VectorUpdated(uint256 indexed vectorId); /** * @notice Emitted when vector is deleted on-chain * @param vectorId ID of vector to delete */ event VectorDeleted(uint256 indexed vectorId); /** * @notice Emitted when vector metadata is set * @param vectorId ID of vector * @param paused True if vector was paused, false otherwise * @param flexibleData Flexible data set in a vector's metadata */ event VectorMetadataSet(uint256 indexed vectorId, bool indexed paused, uint128 indexed flexibleData); /** * @notice Emitted when payment is made in native gas token * @param paymentRecipient Creator recipient of payment * @param vectorId Vector that payment was for * @param amountToCreator Amount sent to creator * @param percentageBPSOfTotal Percentage (in basis points) that was sent to creator, of total payment */ event NativeGasTokenPayment( address indexed paymentRecipient, bytes32 indexed vectorId, uint256 amountToCreator, uint32 percentageBPSOfTotal ); /** * @notice Emitted when payment is made in ERC20 * @param currency ERC20 currency * @param paymentRecipient Creator recipient of payment * @param vectorId Vector that payment was for * @param payer Payer * @param amountToCreator Amount sent to creator * @param percentageBPSOfTotal Percentage (in basis points) that was sent to creator, of total payment */ event ERC20Payment( address indexed currency, address indexed paymentRecipient, bytes32 indexed vectorId, address payer, uint256 amountToCreator, uint32 percentageBPSOfTotal ); /** * @notice Emitted on a mint where discrete token ids are minted * @param vectorId Vector that payment was for * @param contractAddress Address of contract being minted on * @param onChainVector Denotes whether mint vector is on-chain * @param tokenIds Array of token ids to mint */ event ChooseTokenMint( bytes32 indexed vectorId, address indexed contractAddress, bool indexed onChainVector, uint256[] tokenIds ); /** * @notice Emitted on a mint where a number of tokens are minted monotonically * @param vectorId Vector that payment was for * @param contractAddress Address of contract being minted on * @param onChainVector Denotes whether mint vector is on-chain * @param numMinted Number of tokens minted */ event NumTokenMint( bytes32 indexed vectorId, address indexed contractAddress, bool indexed onChainVector, uint256 numMinted ); /** * @notice Emitted on a mint where a number of tokens are minted monotonically by the owner * @param contractAddress Address of contract being minted on * @param isEditionBased Denotes whether collection is edition-based * @param editionId Edition ID, if applicable * @param numMinted Number of tokens minted */ event CreatorReservesNumMint( address indexed contractAddress, bool indexed isEditionBased, uint256 indexed editionId, uint256 numMinted ); /** * @notice Emitted on a mint where a number of tokens are minted monotonically by the owner * @param contractAddress Address of contract being minted on * @param tokenIds IDs of tokens minted */ event CreatorReservesChooseMint(address indexed contractAddress, uint256[] tokenIds); /** * @notice Emitted when a mechanic vector is registered * @param mechanicVectorId Global mechanic vector ID * @param mechanic Mechanic's address * @param contractAddress Address of collection the mechanic is minting on * @param editionId ID of edition, if applicable * @param isEditionBased If true, edition based */ event MechanicVectorRegistered( bytes32 indexed mechanicVectorId, address indexed mechanic, address indexed contractAddress, uint256 editionId, bool isEditionBased ); /** * @notice Emitted when a mechanic vector's pause state is toggled * @param mechanicVectorId Global mechanic vector ID * @param paused If true, mechanic was paused. If false, mechanic was unpaused */ event MechanicVectorPauseSet(bytes32 indexed mechanicVectorId, bool indexed paused); /** * @notice Restricts calls to platform */ modifier onlyPlatform() { if (_msgSender() != _platform) { _revert(Unauthorized.selector); } _; } /** * @notice Initializes MintManager * @param platform Platform address * @param _owner MintManager owner * @param trustedForwarder Trusted meta-tx executor * @param initialExecutor Initial platform executor * @param initialPlatformMintFee Initial platform mint fee */ function initialize( address payable platform, address _owner, address trustedForwarder, address initialExecutor, uint256 initialPlatformMintFee ) external initializer { _platform = platform; __EIP721Upgradeable_initialize("MintManager", "1.0.0"); __ERC2771ContextUpgradeable__init__(trustedForwarder); __Ownable_init(); _transferOwnership(_owner); _platformExecutors.add(initialExecutor); _platformMintFee = initialPlatformMintFee; } /** * @notice Add or deprecate platform executor * @param _executor Platform executor to add or deprecate */ function addOrDeprecatePlatformExecutor(address _executor) external onlyOwner { if (_executor == address(0)) { _revert(InvalidExecutorChanged.selector); } if (_platformExecutors.contains(_executor)) { // remove exeuctor _platformExecutors.remove(_executor); } else { // add executor _platformExecutors.add(_executor); } } /** * @notice See {IAbridgedMintVector-createAbridgedVector} */ function createAbridgedVector(AbridgedVectorData calldata _vector) external { address msgSender = _msgSender(); if ( address(_vector.contractAddress) == msgSender || Ownable(address(_vector.contractAddress)).owner() == msgSender ) { if (_vector.totalClaimedViaVector > 0) { _revert(InvalidTotalClaimed.selector); } _vectorSupply++; _abridgedVectors[_vectorSupply] = _vector; if (_vector.editionBasedCollection) { emit EditionVectorCreated(_vectorSupply, _vector.editionId, address(_vector.contractAddress)); } else { emit SeriesVectorCreated(_vectorSupply, address(_vector.contractAddress)); } } else { _revert(Unauthorized.selector); } } /* solhint-disable code-complexity */ /** * @notice See {IAbridgedMintVector-updateAbridgedVector} */ function updateAbridgedVector( uint256 vectorId, AbridgedVector calldata _newVector, UpdateAbridgedVectorConfig calldata updateConfig, bool pause, uint128 flexibleData ) external { address contractAddress = address(_abridgedVectors[vectorId].contractAddress); address msgSender = _msgSender(); // check owner() first, more likely if (Ownable(contractAddress).owner() == msgSender || msgSender == contractAddress) { if (updateConfig.updateStartTimestamp > 0) { _abridgedVectors[vectorId].startTimestamp = _newVector.startTimestamp; } if (updateConfig.updateEndTimestamp > 0) { _abridgedVectors[vectorId].endTimestamp = _newVector.endTimestamp; } if (updateConfig.updatePaymentRecipient > 0) { _abridgedVectors[vectorId].paymentRecipient = uint160(_newVector.paymentRecipient); } if (updateConfig.updateMaxTotalClaimableViaVector > 0) { _abridgedVectors[vectorId].maxTotalClaimableViaVector = _newVector.maxTotalClaimableViaVector; } if (updateConfig.updateTokenLimitPerTx > 0) { _abridgedVectors[vectorId].tokenLimitPerTx = _newVector.tokenLimitPerTx; } if (updateConfig.updateMaxUserClaimableViaVector > 0) { _abridgedVectors[vectorId].maxUserClaimableViaVector = _newVector.maxUserClaimableViaVector; } if (updateConfig.updatePricePerToken > 0) { _abridgedVectors[vectorId].pricePerToken = _newVector.pricePerToken; } if (updateConfig.updateAllowlistRoot > 0) { _abridgedVectors[vectorId].allowlistRoot = _newVector.allowlistRoot; } if (updateConfig.updateRequireDirectEOA > 0) { _abridgedVectors[vectorId].requireDirectEOA = _newVector.requireDirectEOA; } if (updateConfig.updateMetadata > 0) { _abridgedVectorMetadata[vectorId] = _composeAbridgedVectorMetadata(pause, flexibleData); emit VectorMetadataSet(vectorId, pause, flexibleData); } emit VectorUpdated(vectorId); } else { _revert(Unauthorized.selector); } } /* solhint-enable code-complexity */ /** * @notice See {IAbridgedMintVector-deleteAbridgedVector} */ function deleteAbridgedVector(uint256 vectorId) external { address contractAddress = address(_abridgedVectors[vectorId].contractAddress); address msgSender = _msgSender(); // check .owner() first, more likely if (Ownable(contractAddress).owner() == msgSender || msgSender == contractAddress) { delete _abridgedVectors[vectorId]; delete _abridgedVectorMetadata[vectorId]; emit VectorDeleted(vectorId); } else { _revert(Unauthorized.selector); } } /** * @notice See {IAbridgedMintVector-setAbridgedVectorMetadata} */ function setAbridgedVectorMetadata(uint256 vectorId, bool pause, uint128 flexibleData) external { address contractAddress = address(_abridgedVectors[vectorId].contractAddress); address msgSender = _msgSender(); // check .owner() first, more likely if (Ownable(contractAddress).owner() == msgSender || msgSender == contractAddress) { _abridgedVectorMetadata[vectorId] = _composeAbridgedVectorMetadata(pause, flexibleData); emit VectorMetadataSet(vectorId, pause, flexibleData); } else { _revert(Unauthorized.selector); } } /** * @notice See {IMechanicMintManager-registerMechanicVector} */ function registerMechanicVector( MechanicVectorMetadata memory _mechanicVectorMetadata, uint96 seed, bytes calldata vectorData ) external { address msgSender = _msgSender(); bytes32 mechanicVectorId = _produceMechanicVectorId(_mechanicVectorMetadata, seed); if ( msgSender == _mechanicVectorMetadata.contractAddress || Ownable(_mechanicVectorMetadata.contractAddress).owner() == msgSender ) { if (mechanicVectorMetadata[mechanicVectorId].contractAddress != address(0)) { _revert(AlreadyRegisteredWithId.selector); } if ( _mechanicVectorMetadata.contractAddress == address(0) || _mechanicVectorMetadata.mechanic == address(0) || (_mechanicVectorMetadata.isEditionBased && _mechanicVectorMetadata.isChoose) || mechanicVectorId == bytes32(0) ) { _revert(InvalidMechanic.selector); } _mechanicVectorMetadata.paused = false; mechanicVectorMetadata[mechanicVectorId] = _mechanicVectorMetadata; } else { _revert(Unauthorized.selector); } IMechanic(_mechanicVectorMetadata.mechanic).createVector(mechanicVectorId, vectorData); emit MechanicVectorRegistered( mechanicVectorId, _mechanicVectorMetadata.mechanic, _mechanicVectorMetadata.contractAddress, _mechanicVectorMetadata.editionId, _mechanicVectorMetadata.isEditionBased ); } /** * @notice See {IMechanicMintManager-setPauseOnMechanicMintVector} */ function setPauseOnMechanicMintVector(bytes32 mechanicVectorId, bool pause) external { address msgSender = _msgSender(); address contractAddress = mechanicVectorMetadata[mechanicVectorId].contractAddress; if (contractAddress == address(0)) { _revert(InvalidMechanic.selector); } if (Ownable(contractAddress).owner() == msgSender || msgSender == contractAddress) { mechanicVectorMetadata[mechanicVectorId].paused = pause; } else { _revert(Unauthorized.selector); } emit MechanicVectorPauseSet(mechanicVectorId, pause); } /** * @notice See {IMechanicMintManager-mechanicMintNum} */ function mechanicMintNum( bytes32 mechanicVectorId, address recipient, uint32 numToMint, bytes calldata data ) external payable { MechanicVectorMetadata memory _mechanicVectorMetadata = mechanicVectorMetadata[mechanicVectorId]; if (_mechanicVectorMetadata.paused) { _revert(MechanicPaused.selector); } if (_mechanicVectorMetadata.isChoose) { _revert(InvalidMechanic.selector); } uint256 _platformFee = (numToMint * _platformMintFee); if (msg.value < _platformFee) { _revert(MintFeeTooLow.selector); } uint256 amountWithoutMintFee = msg.value - _platformFee; IMechanic(_mechanicVectorMetadata.mechanic).processNumMint{ value: amountWithoutMintFee }( mechanicVectorId, recipient, numToMint, _mechanicVectorMetadata, data ); if (_mechanicVectorMetadata.isEditionBased) { if (numToMint == 1) { IERC721EditionMint(_mechanicVectorMetadata.contractAddress).mintOneToRecipient( _mechanicVectorMetadata.editionId, recipient ); } else { IERC721EditionMint(_mechanicVectorMetadata.contractAddress).mintAmountToRecipient( _mechanicVectorMetadata.editionId, recipient, uint256(numToMint) ); } } else { if (numToMint == 1) { IERC721GeneralMint(_mechanicVectorMetadata.contractAddress).mintOneToOneRecipient(recipient); } else { IERC721GeneralMint(_mechanicVectorMetadata.contractAddress).mintAmountToOneRecipient( recipient, uint256(numToMint) ); } } emit NumTokenMint(mechanicVectorId, _mechanicVectorMetadata.contractAddress, true, uint256(numToMint)); } /** * @notice See {IMechanicMintManager-mechanicMintChoose} */ function mechanicMintChoose( bytes32 mechanicVectorId, address recipient, uint256[] calldata tokenIds, bytes calldata data ) external payable { MechanicVectorMetadata memory _mechanicVectorMetadata = mechanicVectorMetadata[mechanicVectorId]; if (_mechanicVectorMetadata.paused) { _revert(MechanicPaused.selector); } if (!_mechanicVectorMetadata.isChoose) { _revert(InvalidMechanic.selector); } uint32 numToMint = uint32(tokenIds.length); uint256 _platformFee = (numToMint * _platformMintFee); if (msg.value < _platformFee) { _revert(MintFeeTooLow.selector); } // send value without amount needed for mint fee IMechanic(_mechanicVectorMetadata.mechanic).processChooseMint{ value: msg.value - _platformFee }( mechanicVectorId, recipient, tokenIds, _mechanicVectorMetadata, data ); if (numToMint == 1) { IERC721GeneralMint(_mechanicVectorMetadata.contractAddress).mintSpecificTokenToOneRecipient( recipient, tokenIds[0] ); } else { IERC721GeneralMint(_mechanicVectorMetadata.contractAddress).mintSpecificTokensToOneRecipient( recipient, tokenIds ); } emit ChooseTokenMint(mechanicVectorId, _mechanicVectorMetadata.contractAddress, true, tokenIds); } /* solhint-disable code-complexity */ /** * @notice Let the owner of a collection mint creator reserves * @param collection Collection contract address * @param isEditionBased If true, collection is edition-based * @param editionId Edition ID of collection, if applicable * @param numToMint Number of tokens to mint on sequential mints * @param tokenIds To reserve mint collector's choice based mints * @param isCollectorsChoice If true, mint via collector's choice based paradigm * @param recipient Recipient of minted tokens */ function creatorReservesMint( address collection, bool isEditionBased, uint256 editionId, uint256 numToMint, uint256[] calldata tokenIds, bool isCollectorsChoice, address recipient ) external payable { address msgSender = _msgSender(); uint256 tokenIdsLength = tokenIds.length; if (tokenIdsLength > 0) { numToMint = tokenIdsLength; } if (Ownable(collection).owner() == msgSender || msgSender == collection) { // platform mint fee deprecated for creator reserves mints /* uint256 mintFeeAmount = _platformMintFee * numToMint; if (mintFeeAmount > msg.value) { _revert(InvalidPaymentAmount.selector); } */ if (isEditionBased) { if (numToMint == 1) { IERC721EditionMint(collection).mintOneToRecipient(editionId, recipient); } else { IERC721EditionMint(collection).mintAmountToRecipient(editionId, recipient, numToMint); } } else { if (numToMint == 1) { if (isCollectorsChoice) { IERC721GeneralMint(collection).mintSpecificTokenToOneRecipient(recipient, tokenIds[0]); } else { IERC721GeneralMint(collection).mintOneToOneRecipient(recipient); } } else { if (isCollectorsChoice) { IERC721GeneralMint(collection).mintSpecificTokensToOneRecipient(recipient, tokenIds); } else { IERC721GeneralMint(collection).mintAmountToOneRecipient(recipient, numToMint); } } } if (isCollectorsChoice) { emit CreatorReservesChooseMint(collection, tokenIds); } else { emit CreatorReservesNumMint(collection, isEditionBased, editionId, numToMint); } } else { _revert(Unauthorized.selector); } } /* solhint-enable code-complexity */ /** * @notice Mint on a Series with a valid claim where one can choose the tokens to mint * @param claim Series Claim * @param claimSignature Signed + encoded claim * @param mintRecipient Who to mint the NFT(s) to. * Can't mint to different recipient if tx isn't sent by claim.claimer. * @param tokenIds IDs of NFTs to mint */ function gatedSeriesMintChooseToken( SeriesClaim calldata claim, bytes calldata claimSignature, address mintRecipient, uint256[] calldata tokenIds ) external payable { address msgSender = _msgSender(); uint256 numTokensToMint = tokenIds.length; _processGatedSeriesMintClaim(claim, claimSignature, numTokensToMint, msgSender); // mint NFT(s) if (claim.claimer != msgSender && mintRecipient != claim.claimer) { _revert(UnsafeMintRecipient.selector); } if (numTokensToMint == 1) { IERC721GeneralMint(claim.contractAddress).mintSpecificTokenToOneRecipient(mintRecipient, tokenIds[0]); } else { IERC721GeneralMint(claim.contractAddress).mintSpecificTokensToOneRecipient(mintRecipient, tokenIds); } emit ChooseTokenMint(claim.offchainVectorId, claim.contractAddress, false, tokenIds); } /** * @notice Mint on a Series collection with a valid claim * @param claim Claim * @param claimSignature Signed + encoded claim * @param mintRecipient Who to mint the NFT(s) to. * Can't mint to different recipient if tx isn't sent by claim.claimer. */ function gatedSeriesMint( Claim calldata claim, bytes calldata claimSignature, address mintRecipient ) external payable { address msgSender = _msgSender(); _processGatedMintClaim(claim, claimSignature, msgSender); // mint NFT(s) if (claim.claimer != msgSender && mintRecipient != claim.claimer) { _revert(UnsafeMintRecipient.selector); } if (claim.numTokensToMint == 1) { IERC721GeneralMint(claim.contractAddress).mintOneToOneRecipient(mintRecipient); } else { IERC721GeneralMint(claim.contractAddress).mintAmountToOneRecipient(mintRecipient, claim.numTokensToMint); } } /** * @notice Mint via an abridged vector * @param vectorId ID of vector * @param numTokensToMint Number of tokens to mint * @param mintRecipient Who to mint the NFT(s) to */ function vectorMint721(uint256 vectorId, uint48 numTokensToMint, address mintRecipient) external payable { address msgSender = _msgSender(); address user = mintRecipient; if (_useSenderForUserLimit(vectorId)) { user = msgSender; } AbridgedVectorData memory _vector = _abridgedVectors[vectorId]; uint48 newNumClaimedViaVector = _vector.totalClaimedViaVector + numTokensToMint; uint48 newNumClaimedForUser = uint48(userClaims[vectorId][user]) + numTokensToMint; if (_vector.allowlistRoot != 0) { _revert(AllowlistInvalid.selector); } if (_vector.requireDirectEOA && msgSender != tx.origin) { _revert(SenderNotDirectEOA.selector); } _abridgedVectors[vectorId].totalClaimedViaVector = newNumClaimedViaVector; userClaims[vectorId][user] = uint64(newNumClaimedForUser); if (_vector.editionBasedCollection) { _vectorMintEdition721( vectorId, _vector, numTokensToMint, mintRecipient, newNumClaimedViaVector, newNumClaimedForUser ); } else { _vectorMintGeneral721( vectorId, _vector, numTokensToMint, mintRecipient, newNumClaimedViaVector, newNumClaimedForUser ); } } /** * @notice Mint on an ERC721Editions or ERC721SingleEdiion collection with a valid claim * @param _claim Claim * @param _signature Signed + encoded claim * @param _recipient Who to mint the NFT(s) to. * Can't mint to different recipient if tx isn't sent by claim.claimer. */ function gatedMintEdition721( Claim calldata _claim, bytes calldata _signature, address _recipient ) external payable { address msgSender = _msgSender(); _processGatedMintClaim(_claim, _signature, msgSender); // mint NFT(s) if (_claim.claimer != msgSender && _recipient != _claim.claimer) { _revert(UnsafeMintRecipient.selector); } if (_claim.numTokensToMint == 1) { IERC721EditionMint(_claim.contractAddress).mintOneToRecipient(_claim.editionId, _recipient); } else { IERC721EditionMint(_claim.contractAddress).mintAmountToRecipient( _claim.editionId, _recipient, _claim.numTokensToMint ); } } /** * @notice Withdraw native gas token owed to platform */ function withdrawNativeGasToken(uint256 amountToWithdraw) external onlyPlatform { (bool sentToPlatform, bytes memory dataPlatform) = _platform.call{ value: amountToWithdraw }(""); if (!sentToPlatform) { _revert(EtherSendFailed.selector); } } /** * @notice Update platform payment address */ function updatePlatformAndMintFee(address payable newPlatform, uint256 newPlatformMintFee) external onlyOwner { if (newPlatform == address(0)) { _revert(Unauthorized.selector); } _platform = newPlatform; _platformMintFee = newPlatformMintFee; } /** * @notice Returns platform executors */ function isPlatformExecutor(address _executor) external view returns (bool) { return _platformExecutors.contains(_executor); } /** * @notice Returns claim ids used for an offchain vector * @param vectorId ID of offchain vector */ function getClaimNoncesUsedForOffchainVector(bytes32 vectorId) external view returns (bytes32[] memory) { return _offchainVectorsToNoncesUsed[vectorId].values(); } /** * @notice Returns number of NFTs minted by user on vector * @param vectorId ID of offchain vector * @param user Minting user */ function getNumClaimedPerUserOffchainVector(bytes32 vectorId, address user) external view returns (uint256) { return offchainVectorsClaimState[vectorId].numClaimedPerUser[user]; } /** * @notice Verify that claim and claim signature are valid for a mint * @param claim Claim * @param signature Signed + encoded claim * @param expectedMsgSender *DEPRECATED*, keep for interface adherence */ function verifyClaim( Claim calldata claim, bytes calldata signature, address expectedMsgSender ) external view returns (bool) { address signer = _claimSigner(claim, signature); return _platformExecutors.contains(signer) && !_offchainVectorsToNoncesUsed[claim.offchainVectorId].contains(claim.claimNonce) && block.timestamp <= claim.claimExpiryTimestamp && (claim.maxClaimableViaVector == 0 || claim.numTokensToMint + offchainVectorsClaimState[claim.offchainVectorId].numClaimed <= claim.maxClaimableViaVector) && (claim.maxClaimablePerUser == 0 || claim.numTokensToMint + offchainVectorsClaimState[claim.offchainVectorId].numClaimedPerUser[claim.claimer] <= claim.maxClaimablePerUser); } /** * @notice Returns if nonce is used for the vector * @param vectorId ID of offchain vector * @param nonce Nonce being checked */ function isNonceUsed(bytes32 vectorId, bytes32 nonce) external view returns (bool) { return _offchainVectorsToNoncesUsed[vectorId].contains(nonce); } /** * @notice See {IAbridgedMintVector-getAbridgedVector} */ function getAbridgedVector(uint256 vectorId) external view returns (AbridgedVector memory) { AbridgedVectorData memory data = _abridgedVectors[vectorId]; return AbridgedVector( address(data.contractAddress), data.startTimestamp, data.endTimestamp, address(data.paymentRecipient), data.maxTotalClaimableViaVector, data.totalClaimedViaVector, address(data.currency), data.tokenLimitPerTx, data.maxUserClaimableViaVector, data.pricePerToken, data.editionId, data.editionBasedCollection, data.requireDirectEOA, data.allowlistRoot ); } /** * @notice See {IAbridgedMintVector-getAbridgedVectorMetadata} */ function getAbridgedVectorMetadata(uint256 vectorId) external view returns (bool, uint128) { return _decomposeAbridgedVectorMetadata(_abridgedVectorMetadata[vectorId]); } /* solhint-disable no-empty-blocks */ /** * @notice Limit upgrades of contract to MintManager owner * @param // New implementation address */ function _authorizeUpgrade(address) internal override onlyOwner {} /* solhint-enable no-empty-blocks */ /** * @notice Used for meta-transactions */ function _msgSender() internal view override(ContextUpgradeable, ERC2771ContextUpgradeable) returns (address sender) { return ERC2771ContextUpgradeable._msgSender(); } /** * @notice Used for meta-transactions */ function _msgData() internal view override(ContextUpgradeable, ERC2771ContextUpgradeable) returns (bytes calldata) { return ERC2771ContextUpgradeable._msgData(); } /** * @notice Process, verify, and update the state of a gated mint claim * @param claim Claim * @param claimSignature Signed + encoded claim * @param msgSender Transaction sender */ function _processGatedMintClaim(Claim calldata claim, bytes calldata claimSignature, address msgSender) private { _verifyAndUpdateClaim(claim, claimSignature); // calculate mint fee amount uint256 mintFeeAmount = _platformMintFee * claim.numTokensToMint; // make payments if (claim.currency == address(0) && claim.pricePerToken > 0) { // pay in native gas token uint256 amount = claim.numTokensToMint * claim.pricePerToken; _processNativeGasTokenPayment(amount, mintFeeAmount, claim.paymentRecipient, claim.offchainVectorId); } else if (claim.pricePerToken > 0) { // pay in ERC20 uint256 amount = claim.numTokensToMint * claim.pricePerToken; _processERC20Payment( amount, mintFeeAmount, claim.paymentRecipient, msgSender, claim.currency, claim.offchainVectorId ); } else { if (mintFeeAmount > msg.value) { _revert(MintFeeTooLow.selector); } } emit NumTokenMint(claim.offchainVectorId, claim.contractAddress, false, claim.numTokensToMint); } /** * @notice Process, verify, and update the state of a gated series mint claim * @param claim Series Claim * @param claimSignature Signed + encoded claim * @param numTokensToMint Number of tokens to mint on series * @param msgSender Transaction sender */ function _processGatedSeriesMintClaim( SeriesClaim calldata claim, bytes calldata claimSignature, uint256 numTokensToMint, address msgSender ) private { _verifyAndUpdateSeriesClaim(claim, claimSignature, numTokensToMint); // calculate mint fee amount uint256 mintFeeAmount = _platformMintFee * numTokensToMint; // make payments if (claim.currency == address(0) && claim.pricePerToken > 0) { // pay in native gas token uint256 amount = numTokensToMint * claim.pricePerToken; _processNativeGasTokenPayment(amount, mintFeeAmount, claim.paymentRecipient, claim.offchainVectorId); } else if (claim.pricePerToken > 0) { // pay in ERC20 uint256 amount = numTokensToMint * claim.pricePerToken; _processERC20Payment( amount, mintFeeAmount, claim.paymentRecipient, msgSender, claim.currency, claim.offchainVectorId ); } else { if (mintFeeAmount > msg.value) { _revert(MintFeeTooLow.selector); } } } /** * @notice Verify, and update the state of a gated mint claim * @param claim Claim * @param signature Signed + encoded claim */ function _verifyAndUpdateClaim(Claim calldata claim, bytes calldata signature) private { address signer = _claimSigner(claim, signature); // cannot cache here due to nested mapping uint256 expectedNumClaimedViaVector = offchainVectorsClaimState[claim.offchainVectorId].numClaimed + claim.numTokensToMint; uint256 expectedNumClaimedByUser = offchainVectorsClaimState[claim.offchainVectorId].numClaimedPerUser[ claim.claimer ] + claim.numTokensToMint; if ( !_platformExecutors.contains(signer) || _offchainVectorsToNoncesUsed[claim.offchainVectorId].contains(claim.claimNonce) || block.timestamp > claim.claimExpiryTimestamp || (expectedNumClaimedViaVector > claim.maxClaimableViaVector && claim.maxClaimableViaVector != 0) || (expectedNumClaimedByUser > claim.maxClaimablePerUser && claim.maxClaimablePerUser != 0) ) { _revert(InvalidClaim.selector); } _offchainVectorsToNoncesUsed[claim.offchainVectorId].add(claim.claimNonce); // mark claim nonce as used // update claim state offchainVectorsClaimState[claim.offchainVectorId].numClaimed = expectedNumClaimedViaVector; offchainVectorsClaimState[claim.offchainVectorId].numClaimedPerUser[claim.claimer] = expectedNumClaimedByUser; } /** * @notice Verify, and update the state of a gated series mint claim * @param claim Series Claim * @param signature Signed + encoded claim * @param numTokensToMint How many tokens to mint in this series claim */ function _verifyAndUpdateSeriesClaim( SeriesClaim calldata claim, bytes calldata signature, uint256 numTokensToMint ) private { address signer = _seriesClaimSigner(claim, signature); // cannot cache here due to nested mapping uint256 expectedNumClaimedViaVector = offchainVectorsClaimState[claim.offchainVectorId].numClaimed + numTokensToMint; uint256 expectedNumClaimedByUser = offchainVectorsClaimState[claim.offchainVectorId].numClaimedPerUser[ claim.claimer ] + numTokensToMint; if ( !_platformExecutors.contains(signer) || numTokensToMint > claim.maxPerTxn || _offchainVectorsToNoncesUsed[claim.offchainVectorId].contains(claim.claimNonce) || block.timestamp > claim.claimExpiryTimestamp || (expectedNumClaimedViaVector > claim.maxClaimableViaVector && claim.maxClaimableViaVector != 0) || (expectedNumClaimedByUser > claim.maxClaimablePerUser && claim.maxClaimablePerUser != 0) ) { _revert(InvalidClaim.selector); } _offchainVectorsToNoncesUsed[claim.offchainVectorId].add(claim.claimNonce); // mark claim nonce as used // update claim state offchainVectorsClaimState[claim.offchainVectorId].numClaimed = expectedNumClaimedViaVector; offchainVectorsClaimState[claim.offchainVectorId].numClaimedPerUser[claim.claimer] = expectedNumClaimedByUser; } /** * @notice Process a mint on an on-chain vector * @param _vectorId ID of vector being minted on * @param _vector Vector being minted on * @param numTokensToMint Number of NFTs to mint on vector * @param newNumClaimedViaVector New number of NFTs minted via vector after this ones * @param newNumClaimedForUser New number of NFTs minted by user via vector after this ones */ function _processVectorMint( uint256 _vectorId, AbridgedVectorData memory _vector, uint48 numTokensToMint, uint48 newNumClaimedViaVector, uint48 newNumClaimedForUser ) private { if ( (_vector.maxTotalClaimableViaVector < newNumClaimedViaVector && _vector.maxTotalClaimableViaVector != 0) || (_vector.maxUserClaimableViaVector < newNumClaimedForUser && _vector.maxUserClaimableViaVector != 0) || ((_vector.startTimestamp > block.timestamp && _vector.startTimestamp != 0) || (block.timestamp > _vector.endTimestamp && _vector.endTimestamp != 0)) || (numTokensToMint == 0) || (numTokensToMint > _vector.tokenLimitPerTx && _vector.tokenLimitPerTx != 0) ) { _revert(OnchainVectorMintGuardFailed.selector); } if (_isVectorPaused(_abridgedVectorMetadata[_vectorId])) { _revert(MintPaused.selector); } // calculate mint fee amount uint256 mintFeeAmount = _platformMintFee * numTokensToMint; if (_vector.currency == 0 && _vector.pricePerToken > 0) { // pay in native gas token uint256 amount = numTokensToMint * _vector.pricePerToken; _processNativeGasTokenPayment( amount, mintFeeAmount, payable(address(_vector.paymentRecipient)), bytes32(_vectorId) ); } else if (_vector.pricePerToken > 0) { // pay in ERC20 uint256 amount = numTokensToMint * _vector.pricePerToken; _processERC20Payment( amount, mintFeeAmount, payable(address(_vector.paymentRecipient)), _msgSender(), address(_vector.currency), bytes32(_vectorId) ); } else { if (mintFeeAmount > msg.value) { _revert(MintFeeTooLow.selector); } } emit NumTokenMint(bytes32(_vectorId), address(_vector.contractAddress), true, numTokensToMint); } /** * @notice Mint on vector pointing to ERC721General collection * @param _vectorId ID of vector * @param _vector Vector being minted on * @param numTokensToMint Number of tokens to mint * @param mintRecipient Who to mint the NFT(s) to * @param newNumClaimedViaVector New number of NFTs minted via vector after this ones * @param newNumClaimedForUser New number of NFTs minted by user via vector after this ones */ function _vectorMintGeneral721( uint256 _vectorId, AbridgedVectorData memory _vector, uint48 numTokensToMint, address mintRecipient, uint48 newNumClaimedViaVector, uint48 newNumClaimedForUser ) private { _processVectorMint(_vectorId, _vector, numTokensToMint, newNumClaimedViaVector, newNumClaimedForUser); if (numTokensToMint == 1) { IERC721GeneralMint(address(_vector.contractAddress)).mintOneToOneRecipient(mintRecipient); } else { IERC721GeneralMint(address(_vector.contractAddress)).mintAmountToOneRecipient( mintRecipient, numTokensToMint ); } } /** * @notice Mint on vector pointing to ERC721Editions or ERC721SingleEdiion collection * @param _vectorId ID of vector * @param _vector Vector being minted on * @param numTokensToMint Number of tokens to mint * @param mintRecipient Who to mint the NFT(s) to * @param newNumClaimedViaVector New number of NFTs minted via vector after this ones * @param newNumClaimedForUser New number of NFTs minted by user via vector after this ones */ function _vectorMintEdition721( uint256 _vectorId, AbridgedVectorData memory _vector, uint48 numTokensToMint, address mintRecipient, uint48 newNumClaimedViaVector, uint48 newNumClaimedForUser ) private { _processVectorMint(_vectorId, _vector, numTokensToMint, newNumClaimedViaVector, newNumClaimedForUser); if (numTokensToMint == 1) { IERC721EditionMint(address(_vector.contractAddress)).mintOneToRecipient(_vector.editionId, mintRecipient); } else { IERC721EditionMint(address(_vector.contractAddress)).mintAmountToRecipient( _vector.editionId, mintRecipient, numTokensToMint ); } } /** * @notice Process payment in native gas token, sending to creator and platform * @param totalAmount Total amount being paid * @param mintFeeAmount Amount to pay platform * @param recipient Creator recipient of payment * @param vectorId ID of vector (on-chain or off-chain) */ function _processNativeGasTokenPayment( uint256 totalAmount, uint256 mintFeeAmount, address payable recipient, bytes32 vectorId ) private { if (totalAmount + mintFeeAmount != msg.value) { _revert(InvalidPaymentAmount.selector); } (bool sentToRecipient, bytes memory dataRecipient) = recipient.call{ value: totalAmount }(""); if (!sentToRecipient) { _revert(EtherSendFailed.selector); } emit NativeGasTokenPayment(recipient, vectorId, totalAmount, 10000); } /** * @notice Process payment in ERC20, sending to creator and platform * @param totalAmount Total amount being paid * @param mintFeeAmount Amount to pay platform in mint fees * @param recipient Creator recipient of payment * @param payer Payer * @param currency ERC20 currency * @param vectorId ID of vector (on-chain or off-chain) */ function _processERC20Payment( uint256 totalAmount, uint256 mintFeeAmount, address recipient, address payer, address currency, bytes32 vectorId ) private { if (mintFeeAmount != msg.value) { _revert(MintFeeTooLow.selector); } IERC20(currency).transferFrom(payer, recipient, totalAmount); // IERC20(currency).transferFrom(payer, _platform, totalAmount - amountToCreator); emit ERC20Payment(currency, recipient, vectorId, payer, totalAmount, 10000); } /** * @notice Recover claim signature signer * @param claim Claim * @param signature Claim signature */ function _claimSigner(Claim calldata claim, bytes calldata signature) private view returns (address) { return _hashTypedDataV4( keccak256(bytes.concat(_claimABIEncoded1(claim), _claimABIEncoded2(claim.offchainVectorId))) ).recover(signature); } /** * @notice Recover series claim signature signer * @param claim Series Claim * @param signature Series Claim signature */ function _seriesClaimSigner(SeriesClaim calldata claim, bytes calldata signature) private view returns (address) { return _hashTypedDataV4(keccak256(_seriesClaimABIEncoded(claim))).recover(signature); } /** * @dev Understand whether to use the transaction sender or the nft recipient for per-user limits on onchain vectors */ function _useSenderForUserLimit(uint256 mintVectorId) private view returns (bool) { return false; /* ((block.chainid == 1 && mintVectorId < 19) || (block.chainid == 5 && mintVectorId < 188) || (block.chainid == 42161 && mintVectorId < 6) || (block.chainid == 421613 && mintVectorId < 3) || (block.chainid == 84531 && mintVectorId < 14) || (block.chainid == 8453 && mintVectorId < 60) || (block.chainid == 7777777 && mintVectorId < 20) || (block.chainid == 999 && mintVectorId < 10) || (block.chainid == 10 && mintVectorId < 11) || (block.chainid == 420 && mintVectorId < 3) || (block.chainid == 137 && mintVectorId < 7) || (block.chainid == 80001 && mintVectorId < 16)); */ } /** * @notice Deterministically produce mechanic vector ID from mechanic vector inputs * @param metadata Mechanic vector metadata * @param seed Used to seed uniqueness */ function _produceMechanicVectorId( MechanicVectorMetadata memory metadata, uint96 seed ) private pure returns (bytes32 mechanicVectorId) { mechanicVectorId = keccak256( abi.encodePacked( metadata.contractAddress, metadata.editionId, metadata.mechanic, metadata.isEditionBased, seed ) ); } /* solhint-disable max-line-length */ /** * @notice Get claim typehash */ function _getClaimTypeHash() private pure returns (bytes32) { return keccak256( "Claim(address currency,address contractAddress,address claimer,address paymentRecipient,uint256 pricePerToken,uint64 numTokensToMint,uint256 maxClaimableViaVector,uint256 maxClaimablePerUser,uint256 editionId,uint256 claimExpiryTimestamp,bytes32 claimNonce,bytes32 offchainVectorId)" ); } /** * @notice Get series claim typehash */ function _getSeriesClaimTypeHash() private pure returns (bytes32) { return keccak256( "SeriesClaim(address currency,address contractAddress,address claimer,address paymentRecipient,uint256 pricePerToken,uint64 maxPerTxn,uint64 maxClaimableViaVector,uint64 maxClaimablePerUser,uint64 claimExpiryTimestamp,bytes32 claimNonce,bytes32 offchainVectorId)" ); } /* solhint-enable max-line-length */ /** * @notice Return abi-encoded claim part one * @param claim Claim */ function _claimABIEncoded1(Claim calldata claim) private pure returns (bytes memory) { return abi.encode( _getClaimTypeHash(), claim.currency, claim.contractAddress, claim.claimer, claim.paymentRecipient, claim.pricePerToken, claim.numTokensToMint, claim.maxClaimableViaVector, claim.maxClaimablePerUser, claim.editionId, claim.claimExpiryTimestamp, claim.claimNonce ); } /** * @notice Return abi-encoded series claim part one * @param claim SeriesClaim */ function _seriesClaimABIEncoded(SeriesClaim calldata claim) private pure returns (bytes memory) { return abi.encode( _getSeriesClaimTypeHash(), claim.currency, claim.contractAddress, claim.claimer, claim.paymentRecipient, claim.pricePerToken, claim.maxPerTxn, claim.maxClaimableViaVector, claim.maxClaimablePerUser, claim.claimExpiryTimestamp, claim.claimNonce, claim.offchainVectorId ); } /** * @notice Return abi-encoded claim part two * @param offchainVectorId Offchain vector ID of claim */ function _claimABIEncoded2(bytes32 offchainVectorId) private pure returns (bytes memory) { return abi.encode(offchainVectorId); } /** * @notice Compose abridged vector metadata into a `uint256` * @param paused If the abridged vector is paused * @param flexibleData Flexible data */ function _composeAbridgedVectorMetadata(bool paused, uint128 flexibleData) private pure returns (uint256) { uint256 metadata = 0; if (paused) { metadata = metadata | _BITMASK_AV_PAUSED; } metadata = metadata | (uint256(flexibleData) << 128); return metadata; } /** * @notice Decompose abridged vector metadata from a `uint256` into its constituent parts * @param packedMetadata Packed abridged vector metadata */ function _decomposeAbridgedVectorMetadata(uint256 packedMetadata) private pure returns (bool, uint128) { bool paused = packedMetadata & _BITMASK_AV_PAUSED != 0; uint128 flexibleData = uint128(packedMetadata >> _BITPOS_AV_FLEXIBLE_DATA); return (paused, flexibleData); } /** * @notice Grab paused status for an onchain abridged mint vector * @param packedMetadata Packed abridged vector metadata */ function _isVectorPaused(uint256 packedMetadata) private pure returns (bool) { return packedMetadata & _BITMASK_AV_PAUSED != 0; } /** * @dev For more efficient reverts. */ function _revert(bytes4 errorSelector) private pure { assembly { mstore(0x00, errorSelector) revert(0x00, 0x04) } } }
// 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 v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @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 Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // 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(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. 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 for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the 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. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // 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 preconditions 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 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// 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: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Mint interface on editions contracts * @author highlight.xyz */ interface IERC721EditionMint { /** * @notice Mints one NFT to one recipient * @param editionId Edition to mint the NFT on * @param recipient Recipient of minted NFT */ function mintOneToRecipient(uint256 editionId, address recipient) external returns (uint256); /** * @notice Mints an amount of NFTs to one recipient * @param editionId Edition to mint the NFTs on * @param recipient Recipient of minted NFTs * @param amount Amount of NFTs minted */ function mintAmountToRecipient(uint256 editionId, address recipient, uint256 amount) external returns (uint256); /** * @notice Mints one NFT each to a number of recipients * @param editionId Edition to mint the NFTs on * @param recipients Recipients of minted NFTs */ function mintOneToRecipients(uint256 editionId, address[] memory recipients) external returns (uint256); /** * @notice Mints an amount of NFTs each to a number of recipients * @param editionId Edition to mint the NFTs on * @param recipients Recipients of minted NFTs * @param amount Amount of NFTs minted per recipient */ function mintAmountToRecipients( uint256 editionId, address[] memory recipients, uint256 amount ) external returns (uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice General721 mint interface * @author highlight.xyz */ interface IERC721GeneralMint { /** * @notice Mint one token to one recipient * @param recipient Recipient of minted NFT */ function mintOneToOneRecipient(address recipient) external returns (uint256); /** * @notice Mint an amount of tokens to one recipient * @param recipient Recipient of minted NFTs * @param amount Amount of NFTs minted */ function mintAmountToOneRecipient(address recipient, uint256 amount) external; /** * @notice Mint one token to multiple recipients. Useful for use-cases like airdrops * @param recipients Recipients of minted NFTs */ function mintOneToMultipleRecipients(address[] calldata recipients) external; /** * @notice Mint the same amount of tokens to multiple recipients * @param recipients Recipients of minted NFTs * @param amount Amount of NFTs minted to each recipient */ function mintSameAmountToMultipleRecipients(address[] calldata recipients, uint256 amount) external; /** * @notice Mint a chosen token id to a single recipient * @param recipient Recipient of chosen NFT * @param tokenId ID of NFT to mint */ function mintSpecificTokenToOneRecipient(address recipient, uint256 tokenId) external; /** * @notice Mint chosen token ids to a single recipient * @param recipient Recipient of chosen NFT * @param tokenIds IDs of NFTs to mint */ function mintSpecificTokensToOneRecipient(address recipient, uint256[] calldata tokenIds) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (metatx/ERC2771Context.sol) pragma solidity 0.8.10; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @dev Context variant with ERC2771 support. * Openzeppelin contract slightly modified by ishan@ highlight.xyz to be upgradeable. */ abstract contract ERC2771ContextUpgradeable is Initializable { address private _trustedForwarder; /** * @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; function isTrustedForwarder(address forwarder) public view virtual returns (bool) { return forwarder == _trustedForwarder; } function __ERC2771ContextUpgradeable__init__(address trustedForwarder) internal onlyInitializing { _trustedForwarder = trustedForwarder; } function _msgSender() internal view virtual returns (address sender) { if (isTrustedForwarder(msg.sender)) { // The assembly code is more direct than the Solidity version using `abi.decode`. /* solhint-disable no-inline-assembly */ assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) } /* solhint-enable no-inline-assembly */ } else { return msg.sender; } } function _msgData() internal view virtual returns (bytes calldata) { if (isTrustedForwarder(msg.sender)) { return msg.data[:msg.data.length - 20]; } else { return msg.data; } } }
// 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 updateAllowlistRoot If 1, update allowlistRoot * @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 updateAllowlistRoot; 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 Deletes on-chain vector * @param vectorId ID of abridged vector to delete */ function deleteAbridgedVector(uint256 vectorId) 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 NativeMetaTransaction interface. Used by eg. wETH on Polygon * @author highlight.xyz */ interface INativeMetaTransaction { /** * @notice Meta-transaction object * @param nonce Account nonce * @param from Account to be considered as sender * @param functionSignature Function to call on contract, with arguments encoded */ struct MetaTransaction { uint256 nonce; address from; bytes functionSignature; } /** * @notice Execute meta transaction on contract containing EIP-712 stuff natively * @param userAddress User to be considered as sender * @param functionSignature Function to call on contract, with arguments encoded * @param sigR Elliptic curve signature component * @param sigS Elliptic curve signature component * @param sigV Elliptic curve signature component */ function executeMetaTransaction( address userAddress, bytes memory functionSignature, bytes32 sigR, bytes32 sigS, uint8 sigV ) external payable returns (bytes memory); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "./IMechanicData.sol"; /** * @notice Interface that mint mechanics are forced to adhere to, * provided they support both collector's choice and sequential minting */ interface IMechanic is IMechanicData { /** * @notice Create a mechanic vector on the mechanic * @param mechanicVectorId Global mechanic vector ID * @param vectorData Mechanic vector data */ function createVector(bytes32 mechanicVectorId, bytes calldata vectorData) external; /** * @notice Process a sequential mint * @param mechanicVectorId Global ID identifying mint vector, using this mechanic * @param recipient Mint recipient * @param numToMint Number of tokens to mint * @param mechanicVectorMetadata Mechanic vector metadata * @param data Custom data that can be deserialized and processed according to implementation */ function processNumMint( bytes32 mechanicVectorId, address recipient, uint32 numToMint, MechanicVectorMetadata calldata mechanicVectorMetadata, bytes calldata data ) external payable; /** * @notice Process a collector's choice mint * @param mechanicVectorId Global ID identifying mint vector, using this mechanic * @param recipient Mint recipient * @param tokenIds IDs of tokens to mint * @param mechanicVectorMetadata Mechanic vector metadata * @param data Custom data that can be deserialized and processed according to implementation */ function processChooseMint( bytes32 mechanicVectorId, address recipient, uint256[] calldata tokenIds, MechanicVectorMetadata calldata mechanicVectorMetadata, bytes calldata data ) external payable; }
// 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"; /** * @notice Capabilities on MintManager pertaining to mechanics */ interface IMechanicMintManager is IMechanicData { /** * @notice Register a new mechanic vector * @param _mechanicVectorMetadata Mechanic vector metadata * @param seed Used to seed uniqueness into mechanic vector ID generation * @param vectorData Vector data to store on mechanic (optional) */ function registerMechanicVector( MechanicVectorMetadata calldata _mechanicVectorMetadata, uint96 seed, bytes calldata vectorData ) external; /** * @notice Pause or unpause a mechanic vector * @param mechanicVectorId Global mechanic ID * @param pause If true, pause the mechanic mint vector. If false, unpause */ function setPauseOnMechanicMintVector(bytes32 mechanicVectorId, bool pause) external; /** * @notice Mint a number of tokens sequentially via a mechanic vector * @param mechanicVectorId Global mechanic ID * @param recipient Mint recipient * @param numToMint Number of tokens to mint * @param data Custom data to be processed by mechanic */ function mechanicMintNum( bytes32 mechanicVectorId, address recipient, uint32 numToMint, bytes calldata data ) external payable; /** * @notice Mint a specific set of token ids via a mechanic vector * @param mechanicVectorId Global mechanic ID * @param recipient Mint recipient * @param tokenIds IDs of tokens to mint * @param data Custom data to be processed by mechanic */ function mechanicMintChoose( bytes32 mechanicVectorId, address recipient, uint256[] calldata tokenIds, bytes calldata data ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.10; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; /** * @author OpenZeppelin, modified by highlight.xyz to make compliant to upgradeable contracts * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ /* solhint-disable */ abstract contract EIP712Upgradeable is Initializable { /* solhint-disable var-name-mixedcase */ // Cache the domain separator, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private _CACHED_DOMAIN_SEPARATOR; uint256 private _CACHED_CHAIN_ID; bytes32 private _HASHED_NAME; bytes32 private _HASHED_VERSION; bytes32 private _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ function __EIP721Upgradeable_initialize(string memory name, string memory version) internal onlyInitializing { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); /* solhint-disable max-line-length */ bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); /* solhint-enable max-line-length */ _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator(bytes32 typeHash, bytes32 name, bytes32 version) private view returns (bytes32) { return keccak256(abi.encode(typeHash, name, version, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity 0.8.10; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity 0.8.10; import "../ERC165/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ /* solhint-disable */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity 0.8.10; import "@openzeppelin/contracts/utils/Context.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. */ /* solhint-disable */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
{ "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":"AllowlistInvalid","type":"error"},{"inputs":[],"name":"AlreadyRegisteredWithId","type":"error"},{"inputs":[],"name":"CurrencyTypeInvalid","type":"error"},{"inputs":[],"name":"EtherSendFailed","type":"error"},{"inputs":[],"name":"InvalidClaim","type":"error"},{"inputs":[],"name":"InvalidExecutorChanged","type":"error"},{"inputs":[],"name":"InvalidMechanic","type":"error"},{"inputs":[],"name":"InvalidPaymentAmount","type":"error"},{"inputs":[],"name":"InvalidTotalClaimed","type":"error"},{"inputs":[],"name":"MechanicPaused","type":"error"},{"inputs":[],"name":"MintFeeTooLow","type":"error"},{"inputs":[],"name":"MintPaused","type":"error"},{"inputs":[],"name":"OnchainVectorMintGuardFailed","type":"error"},{"inputs":[],"name":"SenderNotClaimer","type":"error"},{"inputs":[],"name":"SenderNotDirectEOA","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnsafeMintRecipient","type":"error"},{"inputs":[],"name":"VectorUpdateActionFrozen","type":"error"},{"inputs":[],"name":"VectorWrongCollectionType","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":true,"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"bool","name":"onChainVector","type":"bool"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"ChooseTokenMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"CreatorReservesChooseMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"bool","name":"isEditionBased","type":"bool"},{"indexed":true,"internalType":"uint256","name":"editionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"numMinted","type":"uint256"}],"name":"CreatorReservesNumMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"currency","type":"address"},{"indexed":true,"internalType":"address","name":"paymentRecipient","type":"address"},{"indexed":true,"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"payer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountToCreator","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"percentageBPSOfTotal","type":"uint32"}],"name":"ERC20Payment","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"vectorId","type":"uint256"},{"indexed":true,"internalType":"uint48","name":"editionId","type":"uint48"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"EditionVectorCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"indexed":true,"internalType":"bool","name":"paused","type":"bool"}],"name":"MechanicVectorPauseSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"mechanic","type":"address"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"editionId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isEditionBased","type":"bool"}],"name":"MechanicVectorRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"paymentRecipient","type":"address"},{"indexed":true,"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amountToCreator","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"percentageBPSOfTotal","type":"uint32"}],"name":"NativeGasTokenPayment","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":true,"internalType":"bool","name":"onChainVector","type":"bool"},{"indexed":false,"internalType":"uint256","name":"numMinted","type":"uint256"}],"name":"NumTokenMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"executor","type":"address"},{"indexed":true,"internalType":"bool","name":"added","type":"bool"}],"name":"PlatformExecutorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"vectorId","type":"uint256"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"SeriesVectorCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"vectorId","type":"uint256"}],"name":"VectorDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"vectorId","type":"uint256"},{"indexed":true,"internalType":"bool","name":"paused","type":"bool"},{"indexed":true,"internalType":"uint128","name":"flexibleData","type":"uint128"}],"name":"VectorMetadataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"vectorId","type":"uint256"}],"name":"VectorUpdated","type":"event"},{"inputs":[{"internalType":"address","name":"_executor","type":"address"}],"name":"addOrDeprecatePlatformExecutor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint160","name":"contractAddress","type":"uint160"},{"internalType":"uint48","name":"startTimestamp","type":"uint48"},{"internalType":"uint48","name":"endTimestamp","type":"uint48"},{"internalType":"uint160","name":"paymentRecipient","type":"uint160"},{"internalType":"uint48","name":"maxTotalClaimableViaVector","type":"uint48"},{"internalType":"uint48","name":"totalClaimedViaVector","type":"uint48"},{"internalType":"uint160","name":"currency","type":"uint160"},{"internalType":"uint48","name":"tokenLimitPerTx","type":"uint48"},{"internalType":"uint48","name":"maxUserClaimableViaVector","type":"uint48"},{"internalType":"uint192","name":"pricePerToken","type":"uint192"},{"internalType":"uint48","name":"editionId","type":"uint48"},{"internalType":"bool","name":"editionBasedCollection","type":"bool"},{"internalType":"bool","name":"requireDirectEOA","type":"bool"},{"internalType":"bytes32","name":"allowlistRoot","type":"bytes32"}],"internalType":"struct IAbridgedMintVector.AbridgedVectorData","name":"_vector","type":"tuple"}],"name":"createAbridgedVector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"bool","name":"isEditionBased","type":"bool"},{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"uint256","name":"numToMint","type":"uint256"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bool","name":"isCollectorsChoice","type":"bool"},{"internalType":"address","name":"recipient","type":"address"}],"name":"creatorReservesMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"vectorId","type":"uint256"}],"name":"deleteAbridgedVector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"currency","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"claimer","type":"address"},{"internalType":"address payable","name":"paymentRecipient","type":"address"},{"internalType":"uint256","name":"pricePerToken","type":"uint256"},{"internalType":"uint64","name":"numTokensToMint","type":"uint64"},{"internalType":"uint256","name":"maxClaimableViaVector","type":"uint256"},{"internalType":"uint256","name":"maxClaimablePerUser","type":"uint256"},{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"uint256","name":"claimExpiryTimestamp","type":"uint256"},{"internalType":"bytes32","name":"claimNonce","type":"bytes32"},{"internalType":"bytes32","name":"offchainVectorId","type":"bytes32"}],"internalType":"struct MintManager.Claim","name":"_claim","type":"tuple"},{"internalType":"bytes","name":"_signature","type":"bytes"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"gatedMintEdition721","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"currency","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"claimer","type":"address"},{"internalType":"address payable","name":"paymentRecipient","type":"address"},{"internalType":"uint256","name":"pricePerToken","type":"uint256"},{"internalType":"uint64","name":"numTokensToMint","type":"uint64"},{"internalType":"uint256","name":"maxClaimableViaVector","type":"uint256"},{"internalType":"uint256","name":"maxClaimablePerUser","type":"uint256"},{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"uint256","name":"claimExpiryTimestamp","type":"uint256"},{"internalType":"bytes32","name":"claimNonce","type":"bytes32"},{"internalType":"bytes32","name":"offchainVectorId","type":"bytes32"}],"internalType":"struct MintManager.Claim","name":"claim","type":"tuple"},{"internalType":"bytes","name":"claimSignature","type":"bytes"},{"internalType":"address","name":"mintRecipient","type":"address"}],"name":"gatedSeriesMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"currency","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"claimer","type":"address"},{"internalType":"address payable","name":"paymentRecipient","type":"address"},{"internalType":"uint256","name":"pricePerToken","type":"uint256"},{"internalType":"uint64","name":"maxPerTxn","type":"uint64"},{"internalType":"uint64","name":"maxClaimableViaVector","type":"uint64"},{"internalType":"uint64","name":"maxClaimablePerUser","type":"uint64"},{"internalType":"uint64","name":"claimExpiryTimestamp","type":"uint64"},{"internalType":"bytes32","name":"claimNonce","type":"bytes32"},{"internalType":"bytes32","name":"offchainVectorId","type":"bytes32"}],"internalType":"struct MintManager.SeriesClaim","name":"claim","type":"tuple"},{"internalType":"bytes","name":"claimSignature","type":"bytes"},{"internalType":"address","name":"mintRecipient","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"gatedSeriesMintChooseToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"vectorId","type":"uint256"}],"name":"getAbridgedVector","outputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint48","name":"startTimestamp","type":"uint48"},{"internalType":"uint48","name":"endTimestamp","type":"uint48"},{"internalType":"address","name":"paymentRecipient","type":"address"},{"internalType":"uint48","name":"maxTotalClaimableViaVector","type":"uint48"},{"internalType":"uint48","name":"totalClaimedViaVector","type":"uint48"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint48","name":"tokenLimitPerTx","type":"uint48"},{"internalType":"uint48","name":"maxUserClaimableViaVector","type":"uint48"},{"internalType":"uint192","name":"pricePerToken","type":"uint192"},{"internalType":"uint48","name":"editionId","type":"uint48"},{"internalType":"bool","name":"editionBasedCollection","type":"bool"},{"internalType":"bool","name":"requireDirectEOA","type":"bool"},{"internalType":"bytes32","name":"allowlistRoot","type":"bytes32"}],"internalType":"struct IAbridgedMintVector.AbridgedVector","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vectorId","type":"uint256"}],"name":"getAbridgedVectorMetadata","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vectorId","type":"bytes32"}],"name":"getClaimNoncesUsedForOffchainVector","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"internalType":"address","name":"user","type":"address"}],"name":"getNumClaimedPerUserOffchainVector","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"platform","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"trustedForwarder","type":"address"},{"internalType":"address","name":"initialExecutor","type":"address"},{"internalType":"uint256","name":"initialPlatformMintFee","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"vectorId","type":"bytes32"},{"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"isNonceUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_executor","type":"address"}],"name":"isPlatformExecutor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mechanicMintChoose","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint32","name":"numToMint","type":"uint32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"mechanicMintNum","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"mechanicVectorMetadata","outputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint96","name":"editionId","type":"uint96"},{"internalType":"address","name":"mechanic","type":"address"},{"internalType":"bool","name":"isEditionBased","type":"bool"},{"internalType":"bool","name":"isChoose","type":"bool"},{"internalType":"bool","name":"paused","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"offchainVectorsClaimState","outputs":[{"internalType":"uint256","name":"numClaimed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint96","name":"editionId","type":"uint96"},{"internalType":"address","name":"mechanic","type":"address"},{"internalType":"bool","name":"isEditionBased","type":"bool"},{"internalType":"bool","name":"isChoose","type":"bool"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IMechanicData.MechanicVectorMetadata","name":"_mechanicVectorMetadata","type":"tuple"},{"internalType":"uint96","name":"seed","type":"uint96"},{"internalType":"bytes","name":"vectorData","type":"bytes"}],"name":"registerMechanicVector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"vectorId","type":"uint256"},{"internalType":"bool","name":"pause","type":"bool"},{"internalType":"uint128","name":"flexibleData","type":"uint128"}],"name":"setAbridgedVectorMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"bool","name":"pause","type":"bool"}],"name":"setPauseOnMechanicMintVector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"vectorId","type":"uint256"},{"components":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"uint48","name":"startTimestamp","type":"uint48"},{"internalType":"uint48","name":"endTimestamp","type":"uint48"},{"internalType":"address","name":"paymentRecipient","type":"address"},{"internalType":"uint48","name":"maxTotalClaimableViaVector","type":"uint48"},{"internalType":"uint48","name":"totalClaimedViaVector","type":"uint48"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint48","name":"tokenLimitPerTx","type":"uint48"},{"internalType":"uint48","name":"maxUserClaimableViaVector","type":"uint48"},{"internalType":"uint192","name":"pricePerToken","type":"uint192"},{"internalType":"uint48","name":"editionId","type":"uint48"},{"internalType":"bool","name":"editionBasedCollection","type":"bool"},{"internalType":"bool","name":"requireDirectEOA","type":"bool"},{"internalType":"bytes32","name":"allowlistRoot","type":"bytes32"}],"internalType":"struct IAbridgedMintVector.AbridgedVector","name":"_newVector","type":"tuple"},{"components":[{"internalType":"uint16","name":"updateStartTimestamp","type":"uint16"},{"internalType":"uint16","name":"updateEndTimestamp","type":"uint16"},{"internalType":"uint16","name":"updatePaymentRecipient","type":"uint16"},{"internalType":"uint16","name":"updateMaxTotalClaimableViaVector","type":"uint16"},{"internalType":"uint16","name":"updateTokenLimitPerTx","type":"uint16"},{"internalType":"uint16","name":"updateMaxUserClaimableViaVector","type":"uint16"},{"internalType":"uint8","name":"updatePricePerToken","type":"uint8"},{"internalType":"uint8","name":"updateAllowlistRoot","type":"uint8"},{"internalType":"uint8","name":"updateRequireDirectEOA","type":"uint8"},{"internalType":"uint8","name":"updateMetadata","type":"uint8"}],"internalType":"struct IAbridgedMintVector.UpdateAbridgedVectorConfig","name":"updateConfig","type":"tuple"},{"internalType":"bool","name":"pause","type":"bool"},{"internalType":"uint128","name":"flexibleData","type":"uint128"}],"name":"updateAbridgedVector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newPlatform","type":"address"},{"internalType":"uint256","name":"newPlatformMintFee","type":"uint256"}],"name":"updatePlatformAndMintFee","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":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userClaims","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"vectorId","type":"uint256"},{"internalType":"uint48","name":"numTokensToMint","type":"uint48"},{"internalType":"address","name":"mintRecipient","type":"address"}],"name":"vectorMint721","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vectorMutabilities","outputs":[{"internalType":"uint8","name":"updatesFrozen","type":"uint8"},{"internalType":"uint8","name":"deleteFrozen","type":"uint8"},{"internalType":"uint8","name":"pausesFrozen","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vectorToEditionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vectors","outputs":[{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"address payable","name":"paymentRecipient","type":"address"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"pricePerToken","type":"uint256"},{"internalType":"uint64","name":"tokenLimitPerTx","type":"uint64"},{"internalType":"uint64","name":"maxTotalClaimableViaVector","type":"uint64"},{"internalType":"uint64","name":"maxUserClaimableViaVector","type":"uint64"},{"internalType":"uint64","name":"totalClaimedViaVector","type":"uint64"},{"internalType":"bytes32","name":"allowlistRoot","type":"bytes32"},{"internalType":"uint8","name":"paused","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"currency","type":"address"},{"internalType":"address","name":"contractAddress","type":"address"},{"internalType":"address","name":"claimer","type":"address"},{"internalType":"address payable","name":"paymentRecipient","type":"address"},{"internalType":"uint256","name":"pricePerToken","type":"uint256"},{"internalType":"uint64","name":"numTokensToMint","type":"uint64"},{"internalType":"uint256","name":"maxClaimableViaVector","type":"uint256"},{"internalType":"uint256","name":"maxClaimablePerUser","type":"uint256"},{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"uint256","name":"claimExpiryTimestamp","type":"uint256"},{"internalType":"bytes32","name":"claimNonce","type":"bytes32"},{"internalType":"bytes32","name":"offchainVectorId","type":"bytes32"}],"internalType":"struct MintManager.Claim","name":"claim","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"expectedMsgSender","type":"address"}],"name":"verifyClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountToWithdraw","type":"uint256"}],"name":"withdrawNativeGasToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523060805234801561001457600080fd5b50608051615e7d6200004d60003960008181611b1b01528181611b6401528181611e5001528181611e90015261204c0152615e7d6000f3fe6080604052600436106101aa5760003560e01c806304105018146101af57806306056f83146102705780630680475b146102855780630dbb18a1146102985780631d9165aa146102d357806323bc2078146102e65780632cf9adc8146102f95780633659cfe6146103195780633716e28414610339578063391a6d28146103695780634d66747b146103895780634f1ef286146103a957806352169be8146103bc57806352d1902d146103dc57806353274246146103f1578063572b6c0514610438578063619b8589146104585780636c1b7abd14610576578063715018a61461058957806377a856ea1461059e5780637e5811fc146105be5780638a320d64146105de5780638da5cb5b146109ce57806399bcbf21146109f05780639e2dc50014610a03578063a0f7652314610a51578063ae709ae314610aaa578063b052d17c14610ad7578063b414ae2f14610af7578063c462507e14610b24578063e28be14414610b8b578063e2f66b1e14610bab578063ee9147f514610bcb578063f2fde38b14610beb578063f4a4034514610c0b578063f7013ef614610c2b578063fc2c997114610c4b575b600080fd5b3480156101bb57600080fd5b506102206101ca366004614c9b565b60a960205260009081526040902080546001909101546001600160a01b03808316926001600160601b03600160a01b9182900416929182169160ff918104821691600160a81b8204811691600160b01b90041686565b604080516001600160a01b0397881681526001600160601b039096166020870152959093169484019490945215156060830152911515608082015290151560a082015260c0015b60405180910390f35b61028361027e366004614d28565b610c5e565b005b610283610293366004614e0a565b610fd3565b3480156102a457600080fd5b506102c56102b3366004614c9b565b60a16020526000908152604090205481565b604051908152602001610267565b6102836102e1366004614e7a565b6111bc565b6102836102f4366004614f19565b61144b565b34801561030557600080fd5b50610283610314366004614f90565b611675565b34801561032557600080fd5b50610283610334366004615003565b611b10565b34801561034557600080fd5b50610359610354366004615020565b611be2565b6040519015158152602001610267565b34801561037557600080fd5b50610283610384366004615042565b611c03565b34801561039557600080fd5b506102836103a4366004614c9b565b611d12565b6102836103b73660046150ee565b611e45565b3480156103c857600080fd5b506102836103d7366004615195565b611eff565b3480156103e857600080fd5b506102c561203f565b3480156103fd57600080fd5b506102c561040c3660046151c5565b600082815260a1602090815260408083206001600160a01b038516845260010190915290205492915050565b34801561044457600080fd5b50610359610453366004615003565b6120ed565b34801561046457600080fd5b506104f8610473366004614c9b565b609d602052600090815260409020805460018201546002830154600384015460048501546005860154600687015460078801546008909801546001600160a01b039788169896881697909516959394929391926001600160401b0380831693600160401b8404821693600160801b8104831693600160c01b9091049092169160ff168c565b604080516001600160a01b039d8e1681529b8d1660208d015299909b16988a01989098526060890196909652608088019490945260a08701929092526001600160401b0390811660c087015290811660e08601529081166101008501521661012083015261014082015260ff90911661016082015261018001610267565b6102836105843660046151ea565b612101565b34801561059557600080fd5b506102836122dc565b3480156105aa57600080fd5b506102836105b9366004615278565b6122f0565b3480156105ca57600080fd5b506102836105d9366004614c9b565b6124e2565b3480156105ea57600080fd5b506109c16105f9366004614c9b565b604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a0810191909152600060a76000848152602001908152602001600020604051806101c00160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016000820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160008201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160018201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016002820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016002820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160028201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016003820160009054906101000a90046001600160c01b03166001600160c01b03166001600160c01b031681526020016003820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160038201601e9054906101000a900460ff1615151515815260200160038201601f9054906101000a900460ff161515151581526020016004820154815250509050604051806101c0016040528082600001516001600160a01b03168152602001826020015165ffffffffffff168152602001826040015165ffffffffffff16815260200182606001516001600160a01b03168152602001826080015165ffffffffffff1681526020018260a0015165ffffffffffff1681526020018260c001516001600160a01b031681526020018260e0015165ffffffffffff16815260200182610100015165ffffffffffff1681526020018261012001516001600160c01b0316815260200182610140015165ffffffffffff1681526020018261016001511515815260200182610180015115158152602001826101a00151815250915050919050565b60405161026791906152a1565b3480156109da57600080fd5b506109e3612583565b60405161026791906153a4565b6102836109fe366004614e0a565b612592565b348015610a0f57600080fd5b50610a44610a1e3660046151c5565b609f6020908152600092835260408084209091529082529020546001600160401b031681565b60405161026791906153b8565b348015610a5d57600080fd5b50610a8b610a6c366004614c9b565b600090815260a860205260409020546001811615159160809190911c90565b6040805192151583526001600160801b03909116602083015201610267565b348015610ab657600080fd5b50610aca610ac5366004614c9b565b61270a565b60405161026791906153cc565b348015610ae357600080fd5b50610283610af2366004615003565b612724565b348015610b0357600080fd5b506102c5610b12366004614c9b565b60a26020526000908152604090205481565b348015610b3057600080fd5b50610b67610b3f366004614c9b565b609e6020526000908152604090205460ff808216916101008104821691620100009091041683565b6040805160ff94851681529284166020840152921691810191909152606001610267565b348015610b9757600080fd5b50610283610ba6366004615427565b612770565b348015610bb757600080fd5b50610359610bc6366004615003565b612aab565b348015610bd757600080fd5b50610283610be6366004615501565b612ab8565b348015610bf757600080fd5b50610283610c06366004615003565b612b03565b348015610c1757600080fd5b50610359610c26366004614e0a565b612b79565b348015610c3757600080fd5b50610283610c4636600461552d565b612cb4565b610283610c59366004615591565b612e55565b6000610c68613182565b9050838015610c75578096505b816001600160a01b03168a6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce1919061560c565b6001600160a01b03161480610d075750896001600160a01b0316826001600160a01b0316145b15610fb8578815610dce578660011415610d925760405163b859c93560e01b81526001600160a01b038b169063b859c93590610d49908b908790600401615629565b6020604051808303816000875af1158015610d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8c9190615640565b50610f1e565b604051631b30808d60e01b8152600481018990526001600160a01b038481166024830152604482018990528b1690631b30808d90606401610d49565b8660011415610e87578315610e5b57896001600160a01b0316630d640e818488886000818110610e0057610e00615659565b905060200201356040518363ffffffff1660e01b8152600401610e2492919061566f565b600060405180830381600087803b158015610e3e57600080fd5b505af1158015610e52573d6000803e3d6000fd5b50505050610f1e565b60405163184a94d560e01b81526001600160a01b038b169063184a94d590610d499086906004016153a4565b8315610ebd57604051636371fbe760e01b81526001600160a01b038b1690636371fbe790610e249086908a908a906004016156be565b604051630b7d2a8960e31b81526001600160a01b038b1690635be9544890610eeb9086908b9060040161566f565b600060405180830381600087803b158015610f0557600080fd5b505af1158015610f19573d6000803e3d6000fd5b505050505b8315610f6c57896001600160a01b03167f4e84cd8521d66b0c0a2d95e21910942e1616948e140df953825b0cb02c32a5e98787604051610f5f9291906156ec565b60405180910390a2610fc7565b878915158b6001600160a01b03167f4c0491da007181c9465d71c51f64ba4f8eb23133900a4bb2dae027b0c2252c3f8a604051610fab91815260200190565b60405180910390a4610fc7565b610fc76282b42960e81b613191565b50505050505050505050565b6000610fdd613182565b9050610feb8585858461319b565b6001600160a01b0381166110056060870160408801615003565b6001600160a01b03161415801561103d57506110276060860160408701615003565b6001600160a01b0316826001600160a01b031614155b15611052576110526343d0477760e01b613191565b61106260c0860160a08701615700565b6001600160401b0316600114156110fe576110836040860160208701615003565b6001600160a01b031663b859c935866101000135846040518363ffffffff1660e01b81526004016110b5929190615629565b6020604051808303816000875af11580156110d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f89190615640565b506111b5565b61110e6040860160208701615003565b6001600160a01b0316631b30808d6101008701358461113360c08a0160a08b01615700565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b0390911660248301526001600160401b031660448201526064016020604051808303816000875af115801561118f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b39190615640565b505b5050505050565b600086815260a96020908152604091829020825160c08101845281546001600160a01b0380821683526001600160601b03600160a01b9283900416948301949094526001909201549283169381019390935260ff908204811615156060840152600160a81b8204811615156080840152600160b01b9091041615801560a0830152611251576112516337e9321960e21b613191565b806080015161126a5761126a633bed786f60e21b613191565b60a65484906000906112829063ffffffff841661573f565b90508034101561129c5761129c63207226af60e01b613191565b60408301516001600160a01b031663552bf8d16112b9833461575e565b8b8b8b8b898c8c6040518963ffffffff1660e01b81526004016112e297969594939291906157f2565b6000604051808303818588803b1580156112fb57600080fd5b505af115801561130f573d6000803e3d6000fd5b50505050508163ffffffff16600114156113a05782516001600160a01b0316630d640e8189898960008161134557611345615659565b905060200201356040518363ffffffff1660e01b815260040161136992919061566f565b600060405180830381600087803b15801561138357600080fd5b505af1158015611397573d6000803e3d6000fd5b50505050611406565b8251604051636371fbe760e01b81526001600160a01b0390911690636371fbe7906113d3908b908b908b906004016156be565b600060405180830381600087803b1580156113ed57600080fd5b505af1158015611401573d6000803e3d6000fd5b505050505b6001151583600001516001600160a01b03168a600080516020615daa8339815191528a8a6040516114389291906156ec565b60405180910390a4505050505050505050565b6000611455613182565b905081600085815260a76020908152604080832081516101c08101835281546001600160a01b03808216835265ffffffffffff600160a01b808404821697850197909752600160d01b928390048116958401959095526001840154808216606085015286810486166080850152829004851660a08401819052600285015491821660c0850152958104851660e084015204831661010082015260038201546001600160c01b038116610120830152600160c01b810490931661014082015260ff600160f01b840481161515610160830152600160f81b9093049092161515610180830152600401546101a0820152919061155090879061584f565b6000888152609f602090815260408083206001600160a01b03881684529091528120549192509061158b9088906001600160401b031661584f565b6101a0840151909150156115a9576115a963e044e60f60e01b613191565b82610180015180156115c457506001600160a01b0385163214155b156115d9576115d9630977d34b60e01b613191565b600088815260a760209081526040808320600101805465ffffffffffff808816600160d01b026001600160d01b0390921691909117909155609f83528184206001600160a01b038916855290925290912080546001600160401b0319169183169190911790556101608301511561165d57611658888489898686613328565b61166b565b61166b88848989868661345c565b5050505050505050565b600085815260a760205260408120546001600160a01b031690611696613182565b9050806001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611704919061560c565b6001600160a01b0316148061172a5750816001600160a01b0316816001600160a01b0316145b15611af857600061173e6020870187615879565b61ffff16111561178e57611758604087016020880161589d565b600088815260a760205260409020805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b60006117a06040870160208801615879565b61ffff1611156117ed576117ba606087016040880161589d565b600088815260a760205260409020805465ffffffffffff92909216600160d01b026001600160d01b039092169190911790555b60006117ff6060870160408801615879565b61ffff161115611849576118196080870160608801615003565b600088815260a76020526040902060010180546001600160a01b0319166001600160a01b03929092169190911790555b600061185b6080870160608801615879565b61ffff1611156118ae5761187560a087016080880161589d565b600088815260a760205260409020600101805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b60006118c060a0870160808801615879565b61ffff161115611914576118db610100870160e0880161589d565b600088815260a760205260409020600201805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b600061192660c0870160a08801615879565b61ffff161115611978576119426101208701610100880161589d565b600088815260a760205260409020600201805465ffffffffffff92909216600160d01b026001600160d01b039092169190911790555b600061198a60e0870160c088016158ba565b60ff1611156119d5576119a5610140870161012088016158f2565b600088815260a76020526040902060030180546001600160c01b0319166001600160c01b03929092169190911790555b60006119e8610100870160e088016158ba565b60ff161115611a0c57600087815260a7602052604090206101a08701356004909101555b6000611a20610120870161010088016158ba565b60ff161115611a6957611a3b6101a08701610180880161590f565b600088815260a7602052604090206003018054911515600160f81b026001600160f81b039092169190911790555b6000611a7d610140870161012088016158ba565b60ff161115611ac857611a908484613511565b600088815260a860205260408082209290925590516001600160801b03851691861515918a91600080516020615e5183398151915291a45b60405187907fe772ce44f6b7edf20d62f174efc62c5a18484d62a710bd48d57af1afd140811c90600090a2611b07565b611b076282b42960e81b613191565b50505050505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415611b625760405162461bcd60e51b8152600401611b599061592c565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611b94613536565b6001600160a01b031614611bba5760405162461bcd60e51b8152600401611b5990615966565b611bc381613552565b60408051600080825260208201909252611bdf9183919061355a565b50565b600082815260a060205260408120611bfa90836136c5565b90505b92915050565b600083815260a760205260408120546001600160a01b031690611c24613182565b9050806001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c92919061560c565b6001600160a01b03161480611cb85750816001600160a01b0316816001600160a01b0316145b15611d0357611cc78484613511565b600086815260a860205260408082209290925590516001600160801b03851691861515918891600080516020615e5183398151915291a46111b5565b6111b56282b42960e81b613191565b600081815260a760205260408120546001600160a01b031690611d33613182565b9050806001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da1919061560c565b6001600160a01b03161480611dc75750816001600160a01b0316816001600160a01b0316145b15611e3157600083815260a76020908152604080832083815560018101849055600281018490556003810184905560040183905560a89091528082208290555184917fc838617e2997901e8e4856126ebd46593aef10fb97d78f88b4635c9420f6731691a2505050565b611e406282b42960e81b613191565b505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415611e8e5760405162461bcd60e51b8152600401611b599061592c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611ec0613536565b6001600160a01b031614611ee65760405162461bcd60e51b8152600401611b5990615966565b611eef82613552565b611efb8282600161355a565b5050565b6000611f09613182565b600084815260a960205260409020549091506001600160a01b031680611f3957611f39633bed786f60e21b613191565b816001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa5919061560c565b6001600160a01b03161480611fcb5750806001600160a01b0316826001600160a01b0316145b15611ffb57600084815260a960205260409020600101805460ff60b01b1916600160b01b8515150217905561200a565b61200a6282b42960e81b613191565b6040518315159085907fa5a0d9b368dd777972caaaa919c8ca3243792928d90f1b032a1bab6b243a73ab90600090a350505050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146120da5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401611b59565b50600080516020615dea83398151915290565b606a546001600160a01b0391821691161490565b600061210b613182565b90508161211b88888884866136d1565b6001600160a01b03821661213560608a0160408b01615003565b6001600160a01b03161415801561216d57506121576060890160408a01615003565b6001600160a01b0316856001600160a01b031614155b15612182576121826343d0477760e01b613191565b80600114156122185761219b6040890160208a01615003565b6001600160a01b0316630d640e8186868660008181106121bd576121bd615659565b905060200201356040518363ffffffff1660e01b81526004016121e192919061566f565b600060405180830381600087803b1580156121fb57600080fd5b505af115801561220f573d6000803e3d6000fd5b5050505061228a565b6122286040890160208a01615003565b6001600160a01b0316636371fbe78686866040518463ffffffff1660e01b8152600401612257939291906156be565b600060405180830381600087803b15801561227157600080fd5b505af1158015612285573d6000803e3d6000fd5b505050505b600061229c60408a0160208b01615003565b6001600160a01b0316896101400135600080516020615daa83398151915287876040516122ca9291906156ec565b60405180910390a45050505050505050565b6122e46137b1565b6122ee6000613820565b565b60006122fa613182565b90506001600160a01b0381166123136020840184615003565b6001600160a01b031614806123a657506001600160a01b03811661233a6020840184615003565b6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239b919061560c565b6001600160a01b0316145b156124d35760006123bd60c0840160a0850161589d565b65ffffffffffff1611156123db576123db63875fc25f60e01b613191565b60a380549060006123eb836159a0565b909155505060a354600090815260a760205260409020829061240d82826159ef565b5061242290506101808301610160840161590f565b1561248a576124346020830183615003565b6001600160a01b031661244f6101608401610140850161589d565b65ffffffffffff1660a3547fa712e8b25b3d4d043988e80f0a4087773b1c7e29e4115a4256e86aebe91c9be960405160405180910390a45050565b6124976020830183615003565b6001600160a01b031660a3547f7258df9bfe0a9fb9cf1285396575e6472f56ca38b4851afcb725c82726fd67ff60405160405180910390a35050565b611efb6282b42960e81b613191565b609c546001600160a01b03166124f6613182565b6001600160a01b031614612513576125136282b42960e81b613191565b609c5460405160009182916001600160a01b039091169084908381818185875af1925050503d8060008114612564576040519150601f19603f3d011682016040523d82523d6000602084013e612569565b606091505b509150915081611e4057611e40637cd69c3960e11b613191565b6038546001600160a01b031690565b600061259c613182565b90506125aa8585858461319b565b6001600160a01b0381166125c46060870160408801615003565b6001600160a01b0316141580156125fc57506125e66060860160408701615003565b6001600160a01b0316826001600160a01b031614155b15612611576126116343d0477760e01b613191565b61262160c0860160a08701615700565b6001600160401b03166001141561266d576126426040860160208701615003565b6001600160a01b031663184a94d5836040518263ffffffff1660e01b81526004016110b591906153a4565b61267d6040860160208701615003565b6001600160a01b0316635be954488361269c60c0890160a08a01615700565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160401b03166024820152604401600060405180830381600087803b1580156126eb57600080fd5b505af11580156126ff573d6000803e3d6000fd5b505050505050505050565b600081815260a060205260409020606090611bfd90613872565b61272c6137b1565b6001600160a01b03811661274a5761274a6340f3a16b60e01b613191565b61275560a482613886565b1561276557611efb60a48261389b565b611efb60a4826138b0565b600061277a613182565b85516020808801516040808a01516060808c015183516001600160601b031997831b8816818801526001600160a01b031960a096871b811660348301529390921b9096168184015294151560f81b60548601529189901b90911660558401528051808403604101815260619093019052815191012090915085600001516001600160a01b0316826001600160a01b0316148061288c5750816001600160a01b031686600001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561285d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612881919061560c565b6001600160a01b0316145b156129ba57600081815260a960205260409020546001600160a01b0316156128be576128be63250675bd60e21b613191565b85516001600160a01b031615806128e0575060408601516001600160a01b0316155b806128f85750856060015180156128f8575085608001515b80612901575080155b1561291657612916633bed786f60e21b613191565b600060a0870181815282825260a960209081526040928390208951918a01516001600160a01b03928316600160a01b6001600160601b039092168202178255938a01516001909101805460608c015160808d01519551939094166001600160a81b0319909116179215159094029190911761ffff60a81b1916600160a81b9215159290920260ff60b01b191691909117600160b01b911515919091021790556129c9565b6129c96282b42960e81b613191565b85604001516001600160a01b0316631a8d37928286866040518463ffffffff1660e01b81526004016129fd93929190615bc2565b600060405180830381600087803b158015612a1757600080fd5b505af1158015612a2b573d6000803e3d6000fd5b5050505085600001516001600160a01b031686604001516001600160a01b0316827f6ec667d7188a57a345b217226db199b2b1e98d2ccdb2eaa555af7ad19324303789602001518a60600151604051612a9b9291906001600160601b039290921682521515602082015260400190565b60405180910390a4505050505050565b6000611bfd60a483613886565b612ac06137b1565b6001600160a01b038216612add57612add6282b42960e81b613191565b609c80546001600160a01b0319166001600160a01b03939093169290921790915560a655565b612b0b6137b1565b6001600160a01b038116612b705760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401611b59565b611bdf81613820565b600080612b878686866138c5565b9050612b9460a482613886565b8015612bc05750610160860135600090815260a060205260409020612bbe906101408801356136c5565b155b8015612bd157508561012001354211155b8015612c24575060c08601351580612c245750610160860135600090815260a1602052604090205460c0870180359190612c0e9060a08a01615700565b6001600160401b0316612c219190615bdc565b11155b8015612ca8575060e08601351580612ca85750610160860135600090815260a1602052604080822060e089013592600190910191612c689060608b01908b01615003565b6001600160a01b03168152602081019190915260400160002054612c9260c0890160a08a01615700565b6001600160401b0316612ca59190615bdc565b11155b9150505b949350505050565b600054610100900460ff1615808015612cd45750600054600160ff909116105b80612cf55750612ce33061394f565b158015612cf5575060005460ff166001145b612d585760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401611b59565b6000805460ff191660011790558015612d7b576000805461ff0019166101001790555b609c80546001600160a01b0319166001600160a01b038816179055604080518082018252600b81526a26b4b73a26b0b730b3b2b960a91b602080830191909152825180840190935260058352640312e302e360dc1b90830152612ddd9161395e565b612de6846139df565b612dee613a28565b612df785613820565b612e0260a4846138b0565b5060a682905580156111b3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050565b600085815260a96020908152604091829020825160c08101845281546001600160a01b0380821683526001600160601b03600160a01b9283900416948301949094526001909201549283169381019390935260ff908204811615156060840152600160a81b8204811615156080840152600160b01b9091041615801560a0830152612eea57612eea6337e9321960e21b613191565b806080015115612f0457612f04633bed786f60e21b613191565b600060a6548563ffffffff16612f1a919061573f565b905080341015612f3457612f3463207226af60e01b613191565b6000612f40823461575e565b905082604001516001600160a01b031663f5d0e4af828a8a8a888b8b6040518863ffffffff1660e01b8152600401612f7d96959493929190615bf4565b6000604051808303818588803b158015612f9657600080fd5b505af1158015612faa573d6000803e3d6000fd5b50505050508260600151156130a5578563ffffffff1660011415613053578251602084015160405163b859c93560e01b81526001600160601b0390911660048201526001600160a01b0389811660248301529091169063b859c935906044015b6020604051808303816000875af1158015613029573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061304d9190615640565b5061314d565b82516020840151604051631b30808d60e01b81526001600160601b0390911660048201526001600160a01b03898116602483015263ffffffff8916604483015290911690631b30808d9060640161300a565b8563ffffffff16600114156130e357825160405163184a94d560e01b81526001600160a01b039091169063184a94d59061300a908a906004016153a4565b8251604051630b7d2a8960e31b81526001600160a01b0390911690635be954489061311a908a9063ffffffff8b169060040161566f565b600060405180830381600087803b15801561313457600080fd5b505af1158015613148573d6000803e3d6000fd5b505050505b825160405163ffffffff881681526001916001600160a01b0316908a90600080516020615e31833981519152906020016122ca565b600061318c613a57565b905090565b8060005260046000fd5b6131a6848484613a79565b60006131b860c0860160a08701615700565b6001600160401b031660a6546131ce919061573f565b905060006131df6020870187615003565b6001600160a01b03161480156131f9575060008560800135115b15613250576000608086013561321560c0880160a08901615700565b6001600160401b0316613228919061573f565b905061324a818361323f60808a0160608b01615003565b896101600135613c43565b506132cc565b6080850135156132b4576000608086013561327160c0880160a08901615700565b6001600160401b0316613284919061573f565b905061324a818361329b60808a0160608b01615003565b866132a960208c018c615003565b8b6101600135613d1f565b348111156132cc576132cc63207226af60e01b613191565b60006132de6040870160208801615003565b6001600160a01b0316610160870135600080516020615e3183398151915261330c60c08a0160a08b01615700565b60405161331991906153b8565b60405180910390a45050505050565b6133358686868585613e08565b8365ffffffffffff16600114156133d157845161014086015160405163b859c93560e01b815265ffffffffffff90911660048201526001600160a01b0385811660248301529091169063b859c935906044015b6020604051808303816000875af11580156133a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cb9190615640565b506111b3565b8451610140860151604051631b30808d60e01b815265ffffffffffff91821660048201526001600160a01b0386811660248301529187166044820152911690631b30808d906064016020604051808303816000875af1158015613438573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b079190615640565b6134698686868585613e08565b8365ffffffffffff16600114156134a957845160405163184a94d560e01b81526001600160a01b039091169063184a94d5906133889086906004016153a4565b8451604051630b7d2a8960e31b81526001600160a01b03858116600483015265ffffffffffff8716602483015290911690635be9544890604401600060405180830381600087803b1580156134fd57600080fd5b505af1158015610fc7573d6000803e3d6000fd5b600080831561351e576001175b6001600160801b0319608084901b1617905092915050565b600080516020615dea833981519152546001600160a01b031690565b611bdf6137b1565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561358d57611e4083614074565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156135e7575060408051601f3d908101601f191682019092526135e491810190615640565b60015b61364a5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401611b59565b600080516020615dea83398151915281146136b95760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401611b59565b50611e4083838361410e565b6000611bfa8383614139565b6136dd85858585614151565b60008260a6546136ed919061573f565b905060006136fe6020880188615003565b6001600160a01b0316148015613718575060008660800135115b1561374f57600061372d60808801358561573f565b90506133cb818361374460808b0160608c01615003565b8a6101400135613c43565b60808601351561379957600061376960808801358561573f565b90506133cb818361378060808b0160608c01615003565b8661378e60208d018d615003565b8c6101400135613d1f565b348111156111b3576111b363207226af60e01b613191565b6137b9613182565b6001600160a01b03166137ca612583565b6001600160a01b0316146122ee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611b59565b603880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6060600061387f83614375565b9392505050565b6000611bfa836001600160a01b038416614139565b6000611bfa836001600160a01b0384166143d1565b6000611bfa836001600160a01b0384166144c4565b6000612cac83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613949925061390f915088905061450e565b61391d886101600135614629565b60405160200161392e929190615c71565b6040516020818303038152906040528051906020012061463e565b90614685565b6001600160a01b03163b151590565b600054610100900460ff166139855760405162461bcd60e51b8152600401611b5990615c97565b815160208084019190912082519183019190912060038290556004819055466002557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6139d38184846146a9565b60015560055550505050565b600054610100900460ff16613a065760405162461bcd60e51b8152600401611b5990615c97565b606a80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16613a4f5760405162461bcd60e51b8152600401611b5990615c97565b6122ee6146f2565b6000613a62336120ed565b15613a74575060131936013560601c90565b503390565b6000613a868484846138c5565b90506000613a9a60c0860160a08701615700565b610160860135600090815260a16020526040902054613ac2916001600160401b031690615bdc565b90506000613ad660c0870160a08801615700565b6001600160401b031660a1600088610160013581526020019081526020016000206001016000886040016020810190613b0f9190615003565b6001600160a01b03166001600160a01b0316815260200190815260200160002054613b3a9190615bdc565b9050613b4760a484613886565b1580613b715750610160860135600090815260a060205260409020613b71906101408801356136c5565b80613b80575085610120013542115b80613b9c57508560c0013582118015613b9c575060c086013515155b80613bb857508560e0013581118015613bb8575060e086013515155b15613bcd57613bcd633b4f091f60e21b613191565b610160860135600090815260a060205260409020613bf090610140880135614729565b50610160860135600090815260a160205260408082208481558392600190910191613c219060608b01908b01615003565b6001600160a01b03168152602081019190915260400160002055505050505050565b34613c4e8486615bdc565b14613c6357613c63637e2897ef60e11b613191565b600080836001600160a01b03168660405160006040518083038185875af1925050503d8060008114613cb1576040519150601f19603f3d011682016040523d82523d6000602084013e613cb6565b606091505b509150915081613cd057613cd0637cd69c3960e11b613191565b60408051878152612710602082015284916001600160a01b038716917f9363885e28e7ba67b096932f9f00dff44742731d6cb4fa26ccd4424e78e41e13910160405180910390a3505050505050565b348514613d3657613d3663207226af60e01b613191565b6040516323b872dd60e01b81526001600160a01b0384811660048301528581166024830152604482018890528316906323b872dd906064016020604051808303816000875af1158015613d8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613db19190615ce2565b50604080516001600160a01b0385811682526020820189905261271092820192909252829180871691908516907fc899cbcc4511003ff90131e8b89605738e9a7f4925273377ae479a673cf5038c90606001612a9b565b8165ffffffffffff16846080015165ffffffffffff16108015613e365750608084015165ffffffffffff1615155b80613e6c57508065ffffffffffff1684610100015165ffffffffffff16108015613e6c575061010084015165ffffffffffff1615155b80613ec4575042846020015165ffffffffffff16118015613e985750602084015165ffffffffffff1615155b80613ec45750836040015165ffffffffffff1642118015613ec45750604084015165ffffffffffff1615155b80613ed5575065ffffffffffff8316155b80613f0957508360e0015165ffffffffffff168365ffffffffffff16118015613f09575060e084015165ffffffffffff1615155b15613f1e57613f1e63072b86df60e21b613191565b600085815260a8602052604090205460011615613f4557613f45636be9245d60e11b613191565b60008365ffffffffffff1660a654613f5d919061573f565b90508460c001516001600160a01b03166000148015613f8a575060008561012001516001600160c01b0316115b15613fce5760008561012001518565ffffffffffff16613faa9190615cff565b6001600160c01b03169050613fc8818388606001518a60001b613c43565b5061403d565b6101208501516001600160c01b0316156140255760008561012001518565ffffffffffff16613ffd9190615cff565b6001600160c01b03169050613fc88183886060015161401a613182565b60c08b01518c613d1f565b3481111561403d5761403d63207226af60e01b613191565b845160405165ffffffffffff861681526001916001600160a01b0316908890600080516020615e3183398151915290602001612a9b565b61407d8161394f565b6140df5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401611b59565b600080516020615dea83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61411783614735565b6000825111806141245750805b15611e40576141338383614775565b50505050565b60009081526001919091016020526040902054151590565b600061415e85858561479a565b610140860135600090815260a1602052604081205491925090614182908490615bdc565b905060008360a16000896101400135815260200190815260200160002060010160008960400160208101906141b79190615003565b6001600160a01b03166001600160a01b03168152602001908152602001600020546141e29190615bdc565b90506141ef60a484613886565b1580614212575061420660c0880160a08901615700565b6001600160401b031684115b8061423b5750610140870135600090815260a06020526040902061423b906101208901356136c5565b8061425f575061425361012088016101008901615700565b6001600160401b031642115b806142a3575061427560e0880160c08901615700565b6001600160401b0316821180156142a3575061429760e0880160c08901615700565b6001600160401b031615155b806142e957506142ba610100880160e08901615700565b6001600160401b0316811180156142e957506142dd610100880160e08901615700565b6001600160401b031615155b156142fe576142fe633b4f091f60e21b613191565b610140870135600090815260a06020526040902061432190610120890135614729565b50610140870135600090815260a1602052604080822084815583926001909101916143529060608c01908c01615003565b6001600160a01b0316815260208101919091526040016000205550505050505050565b6060816000018054806020026020016040519081016040528092919081815260200182805480156143c557602002820191906000526020600020905b8154815260200190600101908083116143b1575b50505050509050919050565b600081815260018301602052604081205480156144ba5760006143f560018361575e565b85549091506000906144099060019061575e565b905081811461446e57600086600001828154811061442957614429615659565b906000526020600020015490508087600001848154811061444c5761444c615659565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061447f5761447f615d2e565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611bfd565b6000915050611bfd565b60006144d08383614139565b61450657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611bfd565b506000611bfd565b60607f75d70c323d802883252e6285d4bb7cc6fcb7faca7fe3ab1d9e9f260aaa4c342461453e6020840184615003565b61454e6040850160208601615003565b61455e6060860160408701615003565b61456e6080870160608801615003565b608087013561458360c0890160a08a01615700565b6040805160208101989098526001600160a01b03968716908801529385166060870152918416608086015290921660a084015260c0808401929092526001600160401b031660e080840191909152908401356101008084019190915290840135610120808401919091529084013561014080840191909152908401356101608301528301356101808201526101a0015b6040516020818303038152906040529050919050565b60608160405160200161461391815260200190565b60006146486147f0565b60405161190160f01b6020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050919050565b60008060006146948585614814565b915091506146a18161485a565b509392505050565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b600054610100900460ff166147195760405162461bcd60e51b8152600401611b5990615c97565b6122ee614724613182565b613820565b6000611bfa83836144c4565b61473e81614074565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060611bfa8383604051806060016040528060278152602001615e0a602791396149a3565b6000612cac83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061394992506147e49150889050614a1b565b8051906020012061463e565b6000600254461415614803575060015490565b61318c6005546003546004546146a9565b60008082516041141561484b5760208301516040840151606085015160001a61483f87828585614b48565b94509450505050614853565b506000905060025b9250929050565b600081600481111561486e5761486e615d44565b14156148775750565b600181600481111561488b5761488b615d44565b14156148d45760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401611b59565b60028160048111156148e8576148e8615d44565b14156149365760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401611b59565b600381600481111561494a5761494a615d44565b1415611bdf5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401611b59565b6060600080856001600160a01b0316856040516149c09190615d5a565b600060405180830381855af49150503d80600081146149fb576040519150601f19603f3d011682016040523d82523d6000602084013e614a00565b606091505b5091509150614a1186838387614c02565b9695505050505050565b60607faf2a8dc7de0e027b17ddbe873c600be814993ef395f58475bc9ef0408f7ccf16614a4b6020840184615003565b614a5b6040850160208601615003565b614a6b6060860160408701615003565b614a7b6080870160608801615003565b6080870135614a9060c0890160a08a01615700565b614aa060e08a0160c08b01615700565b614ab16101008b0160e08c01615700565b614ac36101208c016101008d01615700565b60408051602081019b909b526001600160a01b03998a16908b015296881660608a015294871660808901529290951660a087015260c08601526001600160401b0393841660e08601528316610100850152821661012080850191909152911661014080840191909152908401356101608301528301356101808201526101a001614613565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b03831115614b755750600090506003614bf9565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614bc9573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116614bf257600060019250925050614bf9565b9150600090505b94509492505050565b60608315614c6c578251614c6557614c198561394f565b614c655760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611b59565b5081612cac565b612cac8383815115614c815781518083602001fd5b8060405162461bcd60e51b8152600401611b599190615d76565b600060208284031215614cad57600080fd5b5035919050565b6001600160a01b03169052565b6001600160a01b0381168114611bdf57600080fd5b8015158114611bdf57600080fd5b60008083601f840112614cf657600080fd5b5081356001600160401b03811115614d0d57600080fd5b6020830191508360208260051b850101111561485357600080fd5b60008060008060008060008060e0898b031215614d4457600080fd5b8835614d4f81614cc1565b97506020890135614d5f81614cd6565b9650604089013595506060890135945060808901356001600160401b03811115614d8857600080fd5b614d948b828c01614ce4565b90955093505060a0890135614da881614cd6565b915060c0890135614db881614cc1565b809150509295985092959890939650565b60008083601f840112614ddb57600080fd5b5081356001600160401b03811115614df257600080fd5b60208301915083602082850101111561485357600080fd5b6000806000808486036101c0811215614e2257600080fd5b61018080821215614e3257600080fd5b86955085013590506001600160401b03811115614e4e57600080fd5b614e5a87828801614dc9565b9094509250506101a0850135614e6f81614cc1565b939692955090935050565b60008060008060008060808789031215614e9357600080fd5b863595506020870135614ea581614cc1565b945060408701356001600160401b0380821115614ec157600080fd5b614ecd8a838b01614ce4565b90965094506060890135915080821115614ee657600080fd5b50614ef389828a01614dc9565b979a9699509497509295939492505050565b65ffffffffffff81168114611bdf57600080fd5b600080600060608486031215614f2e57600080fd5b833592506020840135614f4081614f05565b91506040840135614f5081614cc1565b809150509250925092565b60006101c08284031215614f6e57600080fd5b50919050565b80356001600160801b0381168114614f8b57600080fd5b919050565b6000806000806000858703610360811215614faa57600080fd5b86359550614fbb8860208901614f5b565b94506101406101df1982011215614fd157600080fd5b506101e086019250610320860135614fe881614cd6565b9150614ff76103408701614f74565b90509295509295909350565b60006020828403121561501557600080fd5b813561387f81614cc1565b6000806040838503121561503357600080fd5b50508035926020909101359150565b60008060006060848603121561505757600080fd5b83359250602084013561506981614cd6565b915061507760408501614f74565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b03811182821017156150b8576150b8615080565b60405290565b604051601f8201601f191681016001600160401b03811182821017156150e6576150e6615080565b604052919050565b6000806040838503121561510157600080fd5b823561510c81614cc1565b91506020838101356001600160401b038082111561512957600080fd5b818601915086601f83011261513d57600080fd5b81358181111561514f5761514f615080565b615161601f8201601f191685016150be565b9150808252878482850101111561517757600080fd5b80848401858401376000848284010152508093505050509250929050565b600080604083850312156151a857600080fd5b8235915060208301356151ba81614cd6565b809150509250929050565b600080604083850312156151d857600080fd5b8235915060208301356151ba81614cc1565b6000806000806000808688036101c081121561520557600080fd5b6101608082121561521557600080fd5b88975087013590506001600160401b038082111561523257600080fd5b61523e8a838b01614dc9565b9097509550610180890135915061525482614cc1565b9093506101a0880135908082111561526b57600080fd5b50614ef389828a01614ce4565b60006101c0828403121561528b57600080fd5b611bfa8383614f5b565b65ffffffffffff169052565b60006101c0820190506152b5828451614cb4565b60208301516152c76020840182615295565b5060408301516152da6040840182615295565b5060608301516152ed6060840182614cb4565b5060808301516153006080840182615295565b5060a083015161531360a0840182615295565b5060c083015161532660c0840182614cb4565b5060e083015161533960e0840182615295565b506101008084015161534d82850182615295565b5050610120838101516001600160c01b0316908301526101408084015161537682850182615295565b505061016083810151151590830152610180808401511515908301526101a092830151929091019190915290565b6001600160a01b0391909116815260200190565b6001600160401b0391909116815260200190565b6020808252825182820181905260009190848201906040850190845b81811015615404578351835292840192918401916001016153e8565b50909695505050505050565b80356001600160601b0381168114614f8b57600080fd5b60008060008084860361010081121561543f57600080fd5b60c081121561544d57600080fd5b50615456615096565b853561546181614cc1565b815261546f60208701615410565b6020820152604086013561548281614cc1565b6040820152606086013561549581614cd6565b606082015260808601356154a881614cd6565b608082015260a08601356154bb81614cd6565b60a082015293506154ce60c08601615410565b925060e08501356001600160401b038111156154e957600080fd5b6154f587828801614dc9565b95989497509550505050565b6000806040838503121561551457600080fd5b823561551f81614cc1565b946020939093013593505050565b600080600080600060a0868803121561554557600080fd5b853561555081614cc1565b9450602086013561556081614cc1565b9350604086013561557081614cc1565b9250606086013561558081614cc1565b949793965091946080013592915050565b6000806000806000608086880312156155a957600080fd5b8535945060208601356155bb81614cc1565b9350604086013563ffffffff811681146155d457600080fd5b925060608601356001600160401b038111156155ef57600080fd5b6155fb88828901614dc9565b969995985093965092949392505050565b60006020828403121561561e57600080fd5b815161387f81614cc1565b9182526001600160a01b0316602082015260400190565b60006020828403121561565257600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03929092168252602082015260400190565b81835260006001600160fb1b038311156156a157600080fd5b8260051b8083602087013760009401602001938452509192915050565b6001600160a01b03841681526040602082018190526000906156e39083018486615688565b95945050505050565b602081526000612cac602083018486615688565b60006020828403121561571257600080fd5b81356001600160401b038116811461387f57600080fd5b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561575957615759615729565b500290565b60008282101561577057615770615729565b500390565b80516001600160a01b0390811683526020808301516001600160601b0316908401526040808301519091169083015260608082015115159083015260808082015115159083015260a0908101511515910152565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8781526001600160a01b03871660208201526101406040820181905260009061581e838201888a615688565b905061582d6060840187615775565b8281036101208401526158418185876157c9565b9a9950505050505050505050565b600065ffffffffffff80831681851680830382111561587057615870615729565b01949350505050565b60006020828403121561588b57600080fd5b813561ffff8116811461387f57600080fd5b6000602082840312156158af57600080fd5b813561387f81614f05565b6000602082840312156158cc57600080fd5b813560ff8116811461387f57600080fd5b6001600160c01b0381168114611bdf57600080fd5b60006020828403121561590457600080fd5b813561387f816158dd565b60006020828403121561592157600080fd5b813561387f81614cd6565b6020808252602c90820152600080516020615dca83398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c90820152600080516020615dca83398151915260408201526b6163746976652070726f787960a01b606082015260800190565b60006000198214156159b4576159b4615729565b5060010190565b60008135611bfd81614cc1565b60008135611bfd81614f05565b60008135611bfd816158dd565b60008135611bfd81614cd6565b615a186159fb836159bb565b82546001600160a01b0319166001600160a01b0391909116178255565b615a4f615a27602084016159c8565b82805465ffffffffffff60a01b191660a09290921b65ffffffffffff60a01b16919091179055565b615a82615a5e604084016159c8565b8280546001600160d01b031660d09290921b6001600160d01b031916919091179055565b60018101615a956159fb606085016159bb565b615aa4615a27608085016159c8565b615ab3615a5e60a085016159c8565b5060028101615ac76159fb60c085016159bb565b615ad6615a2760e085016159c8565b615ae6615a5e61010085016159c8565b5060038101615b18615afb61012085016159d5565b82546001600160c01b0319166001600160c01b0391909116178255565b615b50615b2861014085016159c8565b82805465ffffffffffff60c01b191660c09290921b65ffffffffffff60c01b16919091179055565b615b7e615b6061016085016159e2565b82805460ff60f01b191691151560f01b60ff60f01b16919091179055565b615bb2615b8e61018085016159e2565b8280546001600160f81b031691151560f81b6001600160f81b031916919091179055565b506101a082013560048201555050565b8381526040602082015260006156e36040830184866157c9565b60008219821115615bef57615bef615729565b500190565b8681526001600160a01b038616602082015263ffffffff851660408201526000610140615c246060840187615775565b80610120840152615c3881840185876157c9565b9998505050505050505050565b60005b83811015615c60578181015183820152602001615c48565b838111156141335750506000910152565b60008351615c83818460208801615c45565b835190830190615870818360208801615c45565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215615cf457600080fd5b815161387f81614cd6565b60006001600160c01b0382811684821681151582840482111615615d2557615d25615729565b02949350505050565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60008251615d6c818460208701615c45565b9190910192915050565b6020815260008251806020840152615d95816040850160208701615c45565b601f01601f1916919091016040019291505056fee0bf8a4af82e2af496af5f4957e2767f8b52e51a77caedd2f30a1843872d1b7c46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564981414aed4973b05aa301314dc13a5a4077f24490497b98bc270852581c1c578aaca5cb46300e4b20595b143bc883119e775ef88ff77f45fa989ca323576f06ba164736f6c634300080a000a
Deployed Bytecode
0x6080604052600436106101aa5760003560e01c806304105018146101af57806306056f83146102705780630680475b146102855780630dbb18a1146102985780631d9165aa146102d357806323bc2078146102e65780632cf9adc8146102f95780633659cfe6146103195780633716e28414610339578063391a6d28146103695780634d66747b146103895780634f1ef286146103a957806352169be8146103bc57806352d1902d146103dc57806353274246146103f1578063572b6c0514610438578063619b8589146104585780636c1b7abd14610576578063715018a61461058957806377a856ea1461059e5780637e5811fc146105be5780638a320d64146105de5780638da5cb5b146109ce57806399bcbf21146109f05780639e2dc50014610a03578063a0f7652314610a51578063ae709ae314610aaa578063b052d17c14610ad7578063b414ae2f14610af7578063c462507e14610b24578063e28be14414610b8b578063e2f66b1e14610bab578063ee9147f514610bcb578063f2fde38b14610beb578063f4a4034514610c0b578063f7013ef614610c2b578063fc2c997114610c4b575b600080fd5b3480156101bb57600080fd5b506102206101ca366004614c9b565b60a960205260009081526040902080546001909101546001600160a01b03808316926001600160601b03600160a01b9182900416929182169160ff918104821691600160a81b8204811691600160b01b90041686565b604080516001600160a01b0397881681526001600160601b039096166020870152959093169484019490945215156060830152911515608082015290151560a082015260c0015b60405180910390f35b61028361027e366004614d28565b610c5e565b005b610283610293366004614e0a565b610fd3565b3480156102a457600080fd5b506102c56102b3366004614c9b565b60a16020526000908152604090205481565b604051908152602001610267565b6102836102e1366004614e7a565b6111bc565b6102836102f4366004614f19565b61144b565b34801561030557600080fd5b50610283610314366004614f90565b611675565b34801561032557600080fd5b50610283610334366004615003565b611b10565b34801561034557600080fd5b50610359610354366004615020565b611be2565b6040519015158152602001610267565b34801561037557600080fd5b50610283610384366004615042565b611c03565b34801561039557600080fd5b506102836103a4366004614c9b565b611d12565b6102836103b73660046150ee565b611e45565b3480156103c857600080fd5b506102836103d7366004615195565b611eff565b3480156103e857600080fd5b506102c561203f565b3480156103fd57600080fd5b506102c561040c3660046151c5565b600082815260a1602090815260408083206001600160a01b038516845260010190915290205492915050565b34801561044457600080fd5b50610359610453366004615003565b6120ed565b34801561046457600080fd5b506104f8610473366004614c9b565b609d602052600090815260409020805460018201546002830154600384015460048501546005860154600687015460078801546008909801546001600160a01b039788169896881697909516959394929391926001600160401b0380831693600160401b8404821693600160801b8104831693600160c01b9091049092169160ff168c565b604080516001600160a01b039d8e1681529b8d1660208d015299909b16988a01989098526060890196909652608088019490945260a08701929092526001600160401b0390811660c087015290811660e08601529081166101008501521661012083015261014082015260ff90911661016082015261018001610267565b6102836105843660046151ea565b612101565b34801561059557600080fd5b506102836122dc565b3480156105aa57600080fd5b506102836105b9366004615278565b6122f0565b3480156105ca57600080fd5b506102836105d9366004614c9b565b6124e2565b3480156105ea57600080fd5b506109c16105f9366004614c9b565b604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a0810191909152600060a76000848152602001908152602001600020604051806101c00160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016000820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160008201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160018201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016002820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016002820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160028201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016003820160009054906101000a90046001600160c01b03166001600160c01b03166001600160c01b031681526020016003820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160038201601e9054906101000a900460ff1615151515815260200160038201601f9054906101000a900460ff161515151581526020016004820154815250509050604051806101c0016040528082600001516001600160a01b03168152602001826020015165ffffffffffff168152602001826040015165ffffffffffff16815260200182606001516001600160a01b03168152602001826080015165ffffffffffff1681526020018260a0015165ffffffffffff1681526020018260c001516001600160a01b031681526020018260e0015165ffffffffffff16815260200182610100015165ffffffffffff1681526020018261012001516001600160c01b0316815260200182610140015165ffffffffffff1681526020018261016001511515815260200182610180015115158152602001826101a00151815250915050919050565b60405161026791906152a1565b3480156109da57600080fd5b506109e3612583565b60405161026791906153a4565b6102836109fe366004614e0a565b612592565b348015610a0f57600080fd5b50610a44610a1e3660046151c5565b609f6020908152600092835260408084209091529082529020546001600160401b031681565b60405161026791906153b8565b348015610a5d57600080fd5b50610a8b610a6c366004614c9b565b600090815260a860205260409020546001811615159160809190911c90565b6040805192151583526001600160801b03909116602083015201610267565b348015610ab657600080fd5b50610aca610ac5366004614c9b565b61270a565b60405161026791906153cc565b348015610ae357600080fd5b50610283610af2366004615003565b612724565b348015610b0357600080fd5b506102c5610b12366004614c9b565b60a26020526000908152604090205481565b348015610b3057600080fd5b50610b67610b3f366004614c9b565b609e6020526000908152604090205460ff808216916101008104821691620100009091041683565b6040805160ff94851681529284166020840152921691810191909152606001610267565b348015610b9757600080fd5b50610283610ba6366004615427565b612770565b348015610bb757600080fd5b50610359610bc6366004615003565b612aab565b348015610bd757600080fd5b50610283610be6366004615501565b612ab8565b348015610bf757600080fd5b50610283610c06366004615003565b612b03565b348015610c1757600080fd5b50610359610c26366004614e0a565b612b79565b348015610c3757600080fd5b50610283610c4636600461552d565b612cb4565b610283610c59366004615591565b612e55565b6000610c68613182565b9050838015610c75578096505b816001600160a01b03168a6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce1919061560c565b6001600160a01b03161480610d075750896001600160a01b0316826001600160a01b0316145b15610fb8578815610dce578660011415610d925760405163b859c93560e01b81526001600160a01b038b169063b859c93590610d49908b908790600401615629565b6020604051808303816000875af1158015610d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8c9190615640565b50610f1e565b604051631b30808d60e01b8152600481018990526001600160a01b038481166024830152604482018990528b1690631b30808d90606401610d49565b8660011415610e87578315610e5b57896001600160a01b0316630d640e818488886000818110610e0057610e00615659565b905060200201356040518363ffffffff1660e01b8152600401610e2492919061566f565b600060405180830381600087803b158015610e3e57600080fd5b505af1158015610e52573d6000803e3d6000fd5b50505050610f1e565b60405163184a94d560e01b81526001600160a01b038b169063184a94d590610d499086906004016153a4565b8315610ebd57604051636371fbe760e01b81526001600160a01b038b1690636371fbe790610e249086908a908a906004016156be565b604051630b7d2a8960e31b81526001600160a01b038b1690635be9544890610eeb9086908b9060040161566f565b600060405180830381600087803b158015610f0557600080fd5b505af1158015610f19573d6000803e3d6000fd5b505050505b8315610f6c57896001600160a01b03167f4e84cd8521d66b0c0a2d95e21910942e1616948e140df953825b0cb02c32a5e98787604051610f5f9291906156ec565b60405180910390a2610fc7565b878915158b6001600160a01b03167f4c0491da007181c9465d71c51f64ba4f8eb23133900a4bb2dae027b0c2252c3f8a604051610fab91815260200190565b60405180910390a4610fc7565b610fc76282b42960e81b613191565b50505050505050505050565b6000610fdd613182565b9050610feb8585858461319b565b6001600160a01b0381166110056060870160408801615003565b6001600160a01b03161415801561103d57506110276060860160408701615003565b6001600160a01b0316826001600160a01b031614155b15611052576110526343d0477760e01b613191565b61106260c0860160a08701615700565b6001600160401b0316600114156110fe576110836040860160208701615003565b6001600160a01b031663b859c935866101000135846040518363ffffffff1660e01b81526004016110b5929190615629565b6020604051808303816000875af11580156110d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f89190615640565b506111b5565b61110e6040860160208701615003565b6001600160a01b0316631b30808d6101008701358461113360c08a0160a08b01615700565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b0390911660248301526001600160401b031660448201526064016020604051808303816000875af115801561118f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b39190615640565b505b5050505050565b600086815260a96020908152604091829020825160c08101845281546001600160a01b0380821683526001600160601b03600160a01b9283900416948301949094526001909201549283169381019390935260ff908204811615156060840152600160a81b8204811615156080840152600160b01b9091041615801560a0830152611251576112516337e9321960e21b613191565b806080015161126a5761126a633bed786f60e21b613191565b60a65484906000906112829063ffffffff841661573f565b90508034101561129c5761129c63207226af60e01b613191565b60408301516001600160a01b031663552bf8d16112b9833461575e565b8b8b8b8b898c8c6040518963ffffffff1660e01b81526004016112e297969594939291906157f2565b6000604051808303818588803b1580156112fb57600080fd5b505af115801561130f573d6000803e3d6000fd5b50505050508163ffffffff16600114156113a05782516001600160a01b0316630d640e8189898960008161134557611345615659565b905060200201356040518363ffffffff1660e01b815260040161136992919061566f565b600060405180830381600087803b15801561138357600080fd5b505af1158015611397573d6000803e3d6000fd5b50505050611406565b8251604051636371fbe760e01b81526001600160a01b0390911690636371fbe7906113d3908b908b908b906004016156be565b600060405180830381600087803b1580156113ed57600080fd5b505af1158015611401573d6000803e3d6000fd5b505050505b6001151583600001516001600160a01b03168a600080516020615daa8339815191528a8a6040516114389291906156ec565b60405180910390a4505050505050505050565b6000611455613182565b905081600085815260a76020908152604080832081516101c08101835281546001600160a01b03808216835265ffffffffffff600160a01b808404821697850197909752600160d01b928390048116958401959095526001840154808216606085015286810486166080850152829004851660a08401819052600285015491821660c0850152958104851660e084015204831661010082015260038201546001600160c01b038116610120830152600160c01b810490931661014082015260ff600160f01b840481161515610160830152600160f81b9093049092161515610180830152600401546101a0820152919061155090879061584f565b6000888152609f602090815260408083206001600160a01b03881684529091528120549192509061158b9088906001600160401b031661584f565b6101a0840151909150156115a9576115a963e044e60f60e01b613191565b82610180015180156115c457506001600160a01b0385163214155b156115d9576115d9630977d34b60e01b613191565b600088815260a760209081526040808320600101805465ffffffffffff808816600160d01b026001600160d01b0390921691909117909155609f83528184206001600160a01b038916855290925290912080546001600160401b0319169183169190911790556101608301511561165d57611658888489898686613328565b61166b565b61166b88848989868661345c565b5050505050505050565b600085815260a760205260408120546001600160a01b031690611696613182565b9050806001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611704919061560c565b6001600160a01b0316148061172a5750816001600160a01b0316816001600160a01b0316145b15611af857600061173e6020870187615879565b61ffff16111561178e57611758604087016020880161589d565b600088815260a760205260409020805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b60006117a06040870160208801615879565b61ffff1611156117ed576117ba606087016040880161589d565b600088815260a760205260409020805465ffffffffffff92909216600160d01b026001600160d01b039092169190911790555b60006117ff6060870160408801615879565b61ffff161115611849576118196080870160608801615003565b600088815260a76020526040902060010180546001600160a01b0319166001600160a01b03929092169190911790555b600061185b6080870160608801615879565b61ffff1611156118ae5761187560a087016080880161589d565b600088815260a760205260409020600101805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b60006118c060a0870160808801615879565b61ffff161115611914576118db610100870160e0880161589d565b600088815260a760205260409020600201805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b600061192660c0870160a08801615879565b61ffff161115611978576119426101208701610100880161589d565b600088815260a760205260409020600201805465ffffffffffff92909216600160d01b026001600160d01b039092169190911790555b600061198a60e0870160c088016158ba565b60ff1611156119d5576119a5610140870161012088016158f2565b600088815260a76020526040902060030180546001600160c01b0319166001600160c01b03929092169190911790555b60006119e8610100870160e088016158ba565b60ff161115611a0c57600087815260a7602052604090206101a08701356004909101555b6000611a20610120870161010088016158ba565b60ff161115611a6957611a3b6101a08701610180880161590f565b600088815260a7602052604090206003018054911515600160f81b026001600160f81b039092169190911790555b6000611a7d610140870161012088016158ba565b60ff161115611ac857611a908484613511565b600088815260a860205260408082209290925590516001600160801b03851691861515918a91600080516020615e5183398151915291a45b60405187907fe772ce44f6b7edf20d62f174efc62c5a18484d62a710bd48d57af1afd140811c90600090a2611b07565b611b076282b42960e81b613191565b50505050505050565b306001600160a01b037f0000000000000000000000007cb2cecfcffdcce0bf69366e52caec6bd719cd44161415611b625760405162461bcd60e51b8152600401611b599061592c565b60405180910390fd5b7f0000000000000000000000007cb2cecfcffdcce0bf69366e52caec6bd719cd446001600160a01b0316611b94613536565b6001600160a01b031614611bba5760405162461bcd60e51b8152600401611b5990615966565b611bc381613552565b60408051600080825260208201909252611bdf9183919061355a565b50565b600082815260a060205260408120611bfa90836136c5565b90505b92915050565b600083815260a760205260408120546001600160a01b031690611c24613182565b9050806001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c92919061560c565b6001600160a01b03161480611cb85750816001600160a01b0316816001600160a01b0316145b15611d0357611cc78484613511565b600086815260a860205260408082209290925590516001600160801b03851691861515918891600080516020615e5183398151915291a46111b5565b6111b56282b42960e81b613191565b600081815260a760205260408120546001600160a01b031690611d33613182565b9050806001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da1919061560c565b6001600160a01b03161480611dc75750816001600160a01b0316816001600160a01b0316145b15611e3157600083815260a76020908152604080832083815560018101849055600281018490556003810184905560040183905560a89091528082208290555184917fc838617e2997901e8e4856126ebd46593aef10fb97d78f88b4635c9420f6731691a2505050565b611e406282b42960e81b613191565b505050565b306001600160a01b037f0000000000000000000000007cb2cecfcffdcce0bf69366e52caec6bd719cd44161415611e8e5760405162461bcd60e51b8152600401611b599061592c565b7f0000000000000000000000007cb2cecfcffdcce0bf69366e52caec6bd719cd446001600160a01b0316611ec0613536565b6001600160a01b031614611ee65760405162461bcd60e51b8152600401611b5990615966565b611eef82613552565b611efb8282600161355a565b5050565b6000611f09613182565b600084815260a960205260409020549091506001600160a01b031680611f3957611f39633bed786f60e21b613191565b816001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa5919061560c565b6001600160a01b03161480611fcb5750806001600160a01b0316826001600160a01b0316145b15611ffb57600084815260a960205260409020600101805460ff60b01b1916600160b01b8515150217905561200a565b61200a6282b42960e81b613191565b6040518315159085907fa5a0d9b368dd777972caaaa919c8ca3243792928d90f1b032a1bab6b243a73ab90600090a350505050565b6000306001600160a01b037f0000000000000000000000007cb2cecfcffdcce0bf69366e52caec6bd719cd4416146120da5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401611b59565b50600080516020615dea83398151915290565b606a546001600160a01b0391821691161490565b600061210b613182565b90508161211b88888884866136d1565b6001600160a01b03821661213560608a0160408b01615003565b6001600160a01b03161415801561216d57506121576060890160408a01615003565b6001600160a01b0316856001600160a01b031614155b15612182576121826343d0477760e01b613191565b80600114156122185761219b6040890160208a01615003565b6001600160a01b0316630d640e8186868660008181106121bd576121bd615659565b905060200201356040518363ffffffff1660e01b81526004016121e192919061566f565b600060405180830381600087803b1580156121fb57600080fd5b505af115801561220f573d6000803e3d6000fd5b5050505061228a565b6122286040890160208a01615003565b6001600160a01b0316636371fbe78686866040518463ffffffff1660e01b8152600401612257939291906156be565b600060405180830381600087803b15801561227157600080fd5b505af1158015612285573d6000803e3d6000fd5b505050505b600061229c60408a0160208b01615003565b6001600160a01b0316896101400135600080516020615daa83398151915287876040516122ca9291906156ec565b60405180910390a45050505050505050565b6122e46137b1565b6122ee6000613820565b565b60006122fa613182565b90506001600160a01b0381166123136020840184615003565b6001600160a01b031614806123a657506001600160a01b03811661233a6020840184615003565b6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239b919061560c565b6001600160a01b0316145b156124d35760006123bd60c0840160a0850161589d565b65ffffffffffff1611156123db576123db63875fc25f60e01b613191565b60a380549060006123eb836159a0565b909155505060a354600090815260a760205260409020829061240d82826159ef565b5061242290506101808301610160840161590f565b1561248a576124346020830183615003565b6001600160a01b031661244f6101608401610140850161589d565b65ffffffffffff1660a3547fa712e8b25b3d4d043988e80f0a4087773b1c7e29e4115a4256e86aebe91c9be960405160405180910390a45050565b6124976020830183615003565b6001600160a01b031660a3547f7258df9bfe0a9fb9cf1285396575e6472f56ca38b4851afcb725c82726fd67ff60405160405180910390a35050565b611efb6282b42960e81b613191565b609c546001600160a01b03166124f6613182565b6001600160a01b031614612513576125136282b42960e81b613191565b609c5460405160009182916001600160a01b039091169084908381818185875af1925050503d8060008114612564576040519150601f19603f3d011682016040523d82523d6000602084013e612569565b606091505b509150915081611e4057611e40637cd69c3960e11b613191565b6038546001600160a01b031690565b600061259c613182565b90506125aa8585858461319b565b6001600160a01b0381166125c46060870160408801615003565b6001600160a01b0316141580156125fc57506125e66060860160408701615003565b6001600160a01b0316826001600160a01b031614155b15612611576126116343d0477760e01b613191565b61262160c0860160a08701615700565b6001600160401b03166001141561266d576126426040860160208701615003565b6001600160a01b031663184a94d5836040518263ffffffff1660e01b81526004016110b591906153a4565b61267d6040860160208701615003565b6001600160a01b0316635be954488361269c60c0890160a08a01615700565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160401b03166024820152604401600060405180830381600087803b1580156126eb57600080fd5b505af11580156126ff573d6000803e3d6000fd5b505050505050505050565b600081815260a060205260409020606090611bfd90613872565b61272c6137b1565b6001600160a01b03811661274a5761274a6340f3a16b60e01b613191565b61275560a482613886565b1561276557611efb60a48261389b565b611efb60a4826138b0565b600061277a613182565b85516020808801516040808a01516060808c015183516001600160601b031997831b8816818801526001600160a01b031960a096871b811660348301529390921b9096168184015294151560f81b60548601529189901b90911660558401528051808403604101815260619093019052815191012090915085600001516001600160a01b0316826001600160a01b0316148061288c5750816001600160a01b031686600001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561285d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612881919061560c565b6001600160a01b0316145b156129ba57600081815260a960205260409020546001600160a01b0316156128be576128be63250675bd60e21b613191565b85516001600160a01b031615806128e0575060408601516001600160a01b0316155b806128f85750856060015180156128f8575085608001515b80612901575080155b1561291657612916633bed786f60e21b613191565b600060a0870181815282825260a960209081526040928390208951918a01516001600160a01b03928316600160a01b6001600160601b039092168202178255938a01516001909101805460608c015160808d01519551939094166001600160a81b0319909116179215159094029190911761ffff60a81b1916600160a81b9215159290920260ff60b01b191691909117600160b01b911515919091021790556129c9565b6129c96282b42960e81b613191565b85604001516001600160a01b0316631a8d37928286866040518463ffffffff1660e01b81526004016129fd93929190615bc2565b600060405180830381600087803b158015612a1757600080fd5b505af1158015612a2b573d6000803e3d6000fd5b5050505085600001516001600160a01b031686604001516001600160a01b0316827f6ec667d7188a57a345b217226db199b2b1e98d2ccdb2eaa555af7ad19324303789602001518a60600151604051612a9b9291906001600160601b039290921682521515602082015260400190565b60405180910390a4505050505050565b6000611bfd60a483613886565b612ac06137b1565b6001600160a01b038216612add57612add6282b42960e81b613191565b609c80546001600160a01b0319166001600160a01b03939093169290921790915560a655565b612b0b6137b1565b6001600160a01b038116612b705760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401611b59565b611bdf81613820565b600080612b878686866138c5565b9050612b9460a482613886565b8015612bc05750610160860135600090815260a060205260409020612bbe906101408801356136c5565b155b8015612bd157508561012001354211155b8015612c24575060c08601351580612c245750610160860135600090815260a1602052604090205460c0870180359190612c0e9060a08a01615700565b6001600160401b0316612c219190615bdc565b11155b8015612ca8575060e08601351580612ca85750610160860135600090815260a1602052604080822060e089013592600190910191612c689060608b01908b01615003565b6001600160a01b03168152602081019190915260400160002054612c9260c0890160a08a01615700565b6001600160401b0316612ca59190615bdc565b11155b9150505b949350505050565b600054610100900460ff1615808015612cd45750600054600160ff909116105b80612cf55750612ce33061394f565b158015612cf5575060005460ff166001145b612d585760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401611b59565b6000805460ff191660011790558015612d7b576000805461ff0019166101001790555b609c80546001600160a01b0319166001600160a01b038816179055604080518082018252600b81526a26b4b73a26b0b730b3b2b960a91b602080830191909152825180840190935260058352640312e302e360dc1b90830152612ddd9161395e565b612de6846139df565b612dee613a28565b612df785613820565b612e0260a4846138b0565b5060a682905580156111b3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050565b600085815260a96020908152604091829020825160c08101845281546001600160a01b0380821683526001600160601b03600160a01b9283900416948301949094526001909201549283169381019390935260ff908204811615156060840152600160a81b8204811615156080840152600160b01b9091041615801560a0830152612eea57612eea6337e9321960e21b613191565b806080015115612f0457612f04633bed786f60e21b613191565b600060a6548563ffffffff16612f1a919061573f565b905080341015612f3457612f3463207226af60e01b613191565b6000612f40823461575e565b905082604001516001600160a01b031663f5d0e4af828a8a8a888b8b6040518863ffffffff1660e01b8152600401612f7d96959493929190615bf4565b6000604051808303818588803b158015612f9657600080fd5b505af1158015612faa573d6000803e3d6000fd5b50505050508260600151156130a5578563ffffffff1660011415613053578251602084015160405163b859c93560e01b81526001600160601b0390911660048201526001600160a01b0389811660248301529091169063b859c935906044015b6020604051808303816000875af1158015613029573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061304d9190615640565b5061314d565b82516020840151604051631b30808d60e01b81526001600160601b0390911660048201526001600160a01b03898116602483015263ffffffff8916604483015290911690631b30808d9060640161300a565b8563ffffffff16600114156130e357825160405163184a94d560e01b81526001600160a01b039091169063184a94d59061300a908a906004016153a4565b8251604051630b7d2a8960e31b81526001600160a01b0390911690635be954489061311a908a9063ffffffff8b169060040161566f565b600060405180830381600087803b15801561313457600080fd5b505af1158015613148573d6000803e3d6000fd5b505050505b825160405163ffffffff881681526001916001600160a01b0316908a90600080516020615e31833981519152906020016122ca565b600061318c613a57565b905090565b8060005260046000fd5b6131a6848484613a79565b60006131b860c0860160a08701615700565b6001600160401b031660a6546131ce919061573f565b905060006131df6020870187615003565b6001600160a01b03161480156131f9575060008560800135115b15613250576000608086013561321560c0880160a08901615700565b6001600160401b0316613228919061573f565b905061324a818361323f60808a0160608b01615003565b896101600135613c43565b506132cc565b6080850135156132b4576000608086013561327160c0880160a08901615700565b6001600160401b0316613284919061573f565b905061324a818361329b60808a0160608b01615003565b866132a960208c018c615003565b8b6101600135613d1f565b348111156132cc576132cc63207226af60e01b613191565b60006132de6040870160208801615003565b6001600160a01b0316610160870135600080516020615e3183398151915261330c60c08a0160a08b01615700565b60405161331991906153b8565b60405180910390a45050505050565b6133358686868585613e08565b8365ffffffffffff16600114156133d157845161014086015160405163b859c93560e01b815265ffffffffffff90911660048201526001600160a01b0385811660248301529091169063b859c935906044015b6020604051808303816000875af11580156133a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cb9190615640565b506111b3565b8451610140860151604051631b30808d60e01b815265ffffffffffff91821660048201526001600160a01b0386811660248301529187166044820152911690631b30808d906064016020604051808303816000875af1158015613438573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b079190615640565b6134698686868585613e08565b8365ffffffffffff16600114156134a957845160405163184a94d560e01b81526001600160a01b039091169063184a94d5906133889086906004016153a4565b8451604051630b7d2a8960e31b81526001600160a01b03858116600483015265ffffffffffff8716602483015290911690635be9544890604401600060405180830381600087803b1580156134fd57600080fd5b505af1158015610fc7573d6000803e3d6000fd5b600080831561351e576001175b6001600160801b0319608084901b1617905092915050565b600080516020615dea833981519152546001600160a01b031690565b611bdf6137b1565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561358d57611e4083614074565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156135e7575060408051601f3d908101601f191682019092526135e491810190615640565b60015b61364a5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401611b59565b600080516020615dea83398151915281146136b95760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401611b59565b50611e4083838361410e565b6000611bfa8383614139565b6136dd85858585614151565b60008260a6546136ed919061573f565b905060006136fe6020880188615003565b6001600160a01b0316148015613718575060008660800135115b1561374f57600061372d60808801358561573f565b90506133cb818361374460808b0160608c01615003565b8a6101400135613c43565b60808601351561379957600061376960808801358561573f565b90506133cb818361378060808b0160608c01615003565b8661378e60208d018d615003565b8c6101400135613d1f565b348111156111b3576111b363207226af60e01b613191565b6137b9613182565b6001600160a01b03166137ca612583565b6001600160a01b0316146122ee5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611b59565b603880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6060600061387f83614375565b9392505050565b6000611bfa836001600160a01b038416614139565b6000611bfa836001600160a01b0384166143d1565b6000611bfa836001600160a01b0384166144c4565b6000612cac83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613949925061390f915088905061450e565b61391d886101600135614629565b60405160200161392e929190615c71565b6040516020818303038152906040528051906020012061463e565b90614685565b6001600160a01b03163b151590565b600054610100900460ff166139855760405162461bcd60e51b8152600401611b5990615c97565b815160208084019190912082519183019190912060038290556004819055466002557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6139d38184846146a9565b60015560055550505050565b600054610100900460ff16613a065760405162461bcd60e51b8152600401611b5990615c97565b606a80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16613a4f5760405162461bcd60e51b8152600401611b5990615c97565b6122ee6146f2565b6000613a62336120ed565b15613a74575060131936013560601c90565b503390565b6000613a868484846138c5565b90506000613a9a60c0860160a08701615700565b610160860135600090815260a16020526040902054613ac2916001600160401b031690615bdc565b90506000613ad660c0870160a08801615700565b6001600160401b031660a1600088610160013581526020019081526020016000206001016000886040016020810190613b0f9190615003565b6001600160a01b03166001600160a01b0316815260200190815260200160002054613b3a9190615bdc565b9050613b4760a484613886565b1580613b715750610160860135600090815260a060205260409020613b71906101408801356136c5565b80613b80575085610120013542115b80613b9c57508560c0013582118015613b9c575060c086013515155b80613bb857508560e0013581118015613bb8575060e086013515155b15613bcd57613bcd633b4f091f60e21b613191565b610160860135600090815260a060205260409020613bf090610140880135614729565b50610160860135600090815260a160205260408082208481558392600190910191613c219060608b01908b01615003565b6001600160a01b03168152602081019190915260400160002055505050505050565b34613c4e8486615bdc565b14613c6357613c63637e2897ef60e11b613191565b600080836001600160a01b03168660405160006040518083038185875af1925050503d8060008114613cb1576040519150601f19603f3d011682016040523d82523d6000602084013e613cb6565b606091505b509150915081613cd057613cd0637cd69c3960e11b613191565b60408051878152612710602082015284916001600160a01b038716917f9363885e28e7ba67b096932f9f00dff44742731d6cb4fa26ccd4424e78e41e13910160405180910390a3505050505050565b348514613d3657613d3663207226af60e01b613191565b6040516323b872dd60e01b81526001600160a01b0384811660048301528581166024830152604482018890528316906323b872dd906064016020604051808303816000875af1158015613d8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613db19190615ce2565b50604080516001600160a01b0385811682526020820189905261271092820192909252829180871691908516907fc899cbcc4511003ff90131e8b89605738e9a7f4925273377ae479a673cf5038c90606001612a9b565b8165ffffffffffff16846080015165ffffffffffff16108015613e365750608084015165ffffffffffff1615155b80613e6c57508065ffffffffffff1684610100015165ffffffffffff16108015613e6c575061010084015165ffffffffffff1615155b80613ec4575042846020015165ffffffffffff16118015613e985750602084015165ffffffffffff1615155b80613ec45750836040015165ffffffffffff1642118015613ec45750604084015165ffffffffffff1615155b80613ed5575065ffffffffffff8316155b80613f0957508360e0015165ffffffffffff168365ffffffffffff16118015613f09575060e084015165ffffffffffff1615155b15613f1e57613f1e63072b86df60e21b613191565b600085815260a8602052604090205460011615613f4557613f45636be9245d60e11b613191565b60008365ffffffffffff1660a654613f5d919061573f565b90508460c001516001600160a01b03166000148015613f8a575060008561012001516001600160c01b0316115b15613fce5760008561012001518565ffffffffffff16613faa9190615cff565b6001600160c01b03169050613fc8818388606001518a60001b613c43565b5061403d565b6101208501516001600160c01b0316156140255760008561012001518565ffffffffffff16613ffd9190615cff565b6001600160c01b03169050613fc88183886060015161401a613182565b60c08b01518c613d1f565b3481111561403d5761403d63207226af60e01b613191565b845160405165ffffffffffff861681526001916001600160a01b0316908890600080516020615e3183398151915290602001612a9b565b61407d8161394f565b6140df5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401611b59565b600080516020615dea83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61411783614735565b6000825111806141245750805b15611e40576141338383614775565b50505050565b60009081526001919091016020526040902054151590565b600061415e85858561479a565b610140860135600090815260a1602052604081205491925090614182908490615bdc565b905060008360a16000896101400135815260200190815260200160002060010160008960400160208101906141b79190615003565b6001600160a01b03166001600160a01b03168152602001908152602001600020546141e29190615bdc565b90506141ef60a484613886565b1580614212575061420660c0880160a08901615700565b6001600160401b031684115b8061423b5750610140870135600090815260a06020526040902061423b906101208901356136c5565b8061425f575061425361012088016101008901615700565b6001600160401b031642115b806142a3575061427560e0880160c08901615700565b6001600160401b0316821180156142a3575061429760e0880160c08901615700565b6001600160401b031615155b806142e957506142ba610100880160e08901615700565b6001600160401b0316811180156142e957506142dd610100880160e08901615700565b6001600160401b031615155b156142fe576142fe633b4f091f60e21b613191565b610140870135600090815260a06020526040902061432190610120890135614729565b50610140870135600090815260a1602052604080822084815583926001909101916143529060608c01908c01615003565b6001600160a01b0316815260208101919091526040016000205550505050505050565b6060816000018054806020026020016040519081016040528092919081815260200182805480156143c557602002820191906000526020600020905b8154815260200190600101908083116143b1575b50505050509050919050565b600081815260018301602052604081205480156144ba5760006143f560018361575e565b85549091506000906144099060019061575e565b905081811461446e57600086600001828154811061442957614429615659565b906000526020600020015490508087600001848154811061444c5761444c615659565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061447f5761447f615d2e565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611bfd565b6000915050611bfd565b60006144d08383614139565b61450657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611bfd565b506000611bfd565b60607f75d70c323d802883252e6285d4bb7cc6fcb7faca7fe3ab1d9e9f260aaa4c342461453e6020840184615003565b61454e6040850160208601615003565b61455e6060860160408701615003565b61456e6080870160608801615003565b608087013561458360c0890160a08a01615700565b6040805160208101989098526001600160a01b03968716908801529385166060870152918416608086015290921660a084015260c0808401929092526001600160401b031660e080840191909152908401356101008084019190915290840135610120808401919091529084013561014080840191909152908401356101608301528301356101808201526101a0015b6040516020818303038152906040529050919050565b60608160405160200161461391815260200190565b60006146486147f0565b60405161190160f01b6020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050919050565b60008060006146948585614814565b915091506146a18161485a565b509392505050565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b600054610100900460ff166147195760405162461bcd60e51b8152600401611b5990615c97565b6122ee614724613182565b613820565b6000611bfa83836144c4565b61473e81614074565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060611bfa8383604051806060016040528060278152602001615e0a602791396149a3565b6000612cac83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061394992506147e49150889050614a1b565b8051906020012061463e565b6000600254461415614803575060015490565b61318c6005546003546004546146a9565b60008082516041141561484b5760208301516040840151606085015160001a61483f87828585614b48565b94509450505050614853565b506000905060025b9250929050565b600081600481111561486e5761486e615d44565b14156148775750565b600181600481111561488b5761488b615d44565b14156148d45760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401611b59565b60028160048111156148e8576148e8615d44565b14156149365760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401611b59565b600381600481111561494a5761494a615d44565b1415611bdf5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401611b59565b6060600080856001600160a01b0316856040516149c09190615d5a565b600060405180830381855af49150503d80600081146149fb576040519150601f19603f3d011682016040523d82523d6000602084013e614a00565b606091505b5091509150614a1186838387614c02565b9695505050505050565b60607faf2a8dc7de0e027b17ddbe873c600be814993ef395f58475bc9ef0408f7ccf16614a4b6020840184615003565b614a5b6040850160208601615003565b614a6b6060860160408701615003565b614a7b6080870160608801615003565b6080870135614a9060c0890160a08a01615700565b614aa060e08a0160c08b01615700565b614ab16101008b0160e08c01615700565b614ac36101208c016101008d01615700565b60408051602081019b909b526001600160a01b03998a16908b015296881660608a015294871660808901529290951660a087015260c08601526001600160401b0393841660e08601528316610100850152821661012080850191909152911661014080840191909152908401356101608301528301356101808201526101a001614613565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b03831115614b755750600090506003614bf9565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614bc9573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116614bf257600060019250925050614bf9565b9150600090505b94509492505050565b60608315614c6c578251614c6557614c198561394f565b614c655760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611b59565b5081612cac565b612cac8383815115614c815781518083602001fd5b8060405162461bcd60e51b8152600401611b599190615d76565b600060208284031215614cad57600080fd5b5035919050565b6001600160a01b03169052565b6001600160a01b0381168114611bdf57600080fd5b8015158114611bdf57600080fd5b60008083601f840112614cf657600080fd5b5081356001600160401b03811115614d0d57600080fd5b6020830191508360208260051b850101111561485357600080fd5b60008060008060008060008060e0898b031215614d4457600080fd5b8835614d4f81614cc1565b97506020890135614d5f81614cd6565b9650604089013595506060890135945060808901356001600160401b03811115614d8857600080fd5b614d948b828c01614ce4565b90955093505060a0890135614da881614cd6565b915060c0890135614db881614cc1565b809150509295985092959890939650565b60008083601f840112614ddb57600080fd5b5081356001600160401b03811115614df257600080fd5b60208301915083602082850101111561485357600080fd5b6000806000808486036101c0811215614e2257600080fd5b61018080821215614e3257600080fd5b86955085013590506001600160401b03811115614e4e57600080fd5b614e5a87828801614dc9565b9094509250506101a0850135614e6f81614cc1565b939692955090935050565b60008060008060008060808789031215614e9357600080fd5b863595506020870135614ea581614cc1565b945060408701356001600160401b0380821115614ec157600080fd5b614ecd8a838b01614ce4565b90965094506060890135915080821115614ee657600080fd5b50614ef389828a01614dc9565b979a9699509497509295939492505050565b65ffffffffffff81168114611bdf57600080fd5b600080600060608486031215614f2e57600080fd5b833592506020840135614f4081614f05565b91506040840135614f5081614cc1565b809150509250925092565b60006101c08284031215614f6e57600080fd5b50919050565b80356001600160801b0381168114614f8b57600080fd5b919050565b6000806000806000858703610360811215614faa57600080fd5b86359550614fbb8860208901614f5b565b94506101406101df1982011215614fd157600080fd5b506101e086019250610320860135614fe881614cd6565b9150614ff76103408701614f74565b90509295509295909350565b60006020828403121561501557600080fd5b813561387f81614cc1565b6000806040838503121561503357600080fd5b50508035926020909101359150565b60008060006060848603121561505757600080fd5b83359250602084013561506981614cd6565b915061507760408501614f74565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b03811182821017156150b8576150b8615080565b60405290565b604051601f8201601f191681016001600160401b03811182821017156150e6576150e6615080565b604052919050565b6000806040838503121561510157600080fd5b823561510c81614cc1565b91506020838101356001600160401b038082111561512957600080fd5b818601915086601f83011261513d57600080fd5b81358181111561514f5761514f615080565b615161601f8201601f191685016150be565b9150808252878482850101111561517757600080fd5b80848401858401376000848284010152508093505050509250929050565b600080604083850312156151a857600080fd5b8235915060208301356151ba81614cd6565b809150509250929050565b600080604083850312156151d857600080fd5b8235915060208301356151ba81614cc1565b6000806000806000808688036101c081121561520557600080fd5b6101608082121561521557600080fd5b88975087013590506001600160401b038082111561523257600080fd5b61523e8a838b01614dc9565b9097509550610180890135915061525482614cc1565b9093506101a0880135908082111561526b57600080fd5b50614ef389828a01614ce4565b60006101c0828403121561528b57600080fd5b611bfa8383614f5b565b65ffffffffffff169052565b60006101c0820190506152b5828451614cb4565b60208301516152c76020840182615295565b5060408301516152da6040840182615295565b5060608301516152ed6060840182614cb4565b5060808301516153006080840182615295565b5060a083015161531360a0840182615295565b5060c083015161532660c0840182614cb4565b5060e083015161533960e0840182615295565b506101008084015161534d82850182615295565b5050610120838101516001600160c01b0316908301526101408084015161537682850182615295565b505061016083810151151590830152610180808401511515908301526101a092830151929091019190915290565b6001600160a01b0391909116815260200190565b6001600160401b0391909116815260200190565b6020808252825182820181905260009190848201906040850190845b81811015615404578351835292840192918401916001016153e8565b50909695505050505050565b80356001600160601b0381168114614f8b57600080fd5b60008060008084860361010081121561543f57600080fd5b60c081121561544d57600080fd5b50615456615096565b853561546181614cc1565b815261546f60208701615410565b6020820152604086013561548281614cc1565b6040820152606086013561549581614cd6565b606082015260808601356154a881614cd6565b608082015260a08601356154bb81614cd6565b60a082015293506154ce60c08601615410565b925060e08501356001600160401b038111156154e957600080fd5b6154f587828801614dc9565b95989497509550505050565b6000806040838503121561551457600080fd5b823561551f81614cc1565b946020939093013593505050565b600080600080600060a0868803121561554557600080fd5b853561555081614cc1565b9450602086013561556081614cc1565b9350604086013561557081614cc1565b9250606086013561558081614cc1565b949793965091946080013592915050565b6000806000806000608086880312156155a957600080fd5b8535945060208601356155bb81614cc1565b9350604086013563ffffffff811681146155d457600080fd5b925060608601356001600160401b038111156155ef57600080fd5b6155fb88828901614dc9565b969995985093965092949392505050565b60006020828403121561561e57600080fd5b815161387f81614cc1565b9182526001600160a01b0316602082015260400190565b60006020828403121561565257600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03929092168252602082015260400190565b81835260006001600160fb1b038311156156a157600080fd5b8260051b8083602087013760009401602001938452509192915050565b6001600160a01b03841681526040602082018190526000906156e39083018486615688565b95945050505050565b602081526000612cac602083018486615688565b60006020828403121561571257600080fd5b81356001600160401b038116811461387f57600080fd5b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561575957615759615729565b500290565b60008282101561577057615770615729565b500390565b80516001600160a01b0390811683526020808301516001600160601b0316908401526040808301519091169083015260608082015115159083015260808082015115159083015260a0908101511515910152565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8781526001600160a01b03871660208201526101406040820181905260009061581e838201888a615688565b905061582d6060840187615775565b8281036101208401526158418185876157c9565b9a9950505050505050505050565b600065ffffffffffff80831681851680830382111561587057615870615729565b01949350505050565b60006020828403121561588b57600080fd5b813561ffff8116811461387f57600080fd5b6000602082840312156158af57600080fd5b813561387f81614f05565b6000602082840312156158cc57600080fd5b813560ff8116811461387f57600080fd5b6001600160c01b0381168114611bdf57600080fd5b60006020828403121561590457600080fd5b813561387f816158dd565b60006020828403121561592157600080fd5b813561387f81614cd6565b6020808252602c90820152600080516020615dca83398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c90820152600080516020615dca83398151915260408201526b6163746976652070726f787960a01b606082015260800190565b60006000198214156159b4576159b4615729565b5060010190565b60008135611bfd81614cc1565b60008135611bfd81614f05565b60008135611bfd816158dd565b60008135611bfd81614cd6565b615a186159fb836159bb565b82546001600160a01b0319166001600160a01b0391909116178255565b615a4f615a27602084016159c8565b82805465ffffffffffff60a01b191660a09290921b65ffffffffffff60a01b16919091179055565b615a82615a5e604084016159c8565b8280546001600160d01b031660d09290921b6001600160d01b031916919091179055565b60018101615a956159fb606085016159bb565b615aa4615a27608085016159c8565b615ab3615a5e60a085016159c8565b5060028101615ac76159fb60c085016159bb565b615ad6615a2760e085016159c8565b615ae6615a5e61010085016159c8565b5060038101615b18615afb61012085016159d5565b82546001600160c01b0319166001600160c01b0391909116178255565b615b50615b2861014085016159c8565b82805465ffffffffffff60c01b191660c09290921b65ffffffffffff60c01b16919091179055565b615b7e615b6061016085016159e2565b82805460ff60f01b191691151560f01b60ff60f01b16919091179055565b615bb2615b8e61018085016159e2565b8280546001600160f81b031691151560f81b6001600160f81b031916919091179055565b506101a082013560048201555050565b8381526040602082015260006156e36040830184866157c9565b60008219821115615bef57615bef615729565b500190565b8681526001600160a01b038616602082015263ffffffff851660408201526000610140615c246060840187615775565b80610120840152615c3881840185876157c9565b9998505050505050505050565b60005b83811015615c60578181015183820152602001615c48565b838111156141335750506000910152565b60008351615c83818460208801615c45565b835190830190615870818360208801615c45565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600060208284031215615cf457600080fd5b815161387f81614cd6565b60006001600160c01b0382811684821681151582840482111615615d2557615d25615729565b02949350505050565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60008251615d6c818460208701615c45565b9190910192915050565b6020815260008251806020840152615d95816040850160208701615c45565b601f01601f1916919091016040019291505056fee0bf8a4af82e2af496af5f4957e2767f8b52e51a77caedd2f30a1843872d1b7c46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564981414aed4973b05aa301314dc13a5a4077f24490497b98bc270852581c1c578aaca5cb46300e4b20595b143bc883119e775ef88ff77f45fa989ca323576f06ba164736f6c634300080a000a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.