Source Code
Overview
APE Balance
APE Value
$0.00Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
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 "./interfaces/IMintFeeOracle.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";
import { GelatoRelayContext } from "@gelatonetwork/relay-context/contracts/GelatoRelayContext.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,
GelatoRelayContext
{
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 Throw when the sender is not an authorized gasless relayer
*/
error UnauthorizedGaslessRelayer();
/**
* @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 Mint fee oracle
*/
address private _mintFeeOracle;
/**
* @notice Gasless mechanic address
*/
address private _gaslessMechanicAddress;
/**
* @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 Emitted when the platform mint fee is updated
* @param newPlatformMintFee New platform mint fee
*/
event PlatformMintFeeUpdated(uint256 indexed newPlatformMintFee);
/**
* @notice Emit when creator is paid out
* @param currency Currency creator reward is in
* @param rewardRecipient Creator reward recipient
* @param amount Amount of payout
*/
event CreatorRewardPayout(
bytes32 indexed vectorId,
address indexed currency,
address indexed rewardRecipient,
uint256 amount
);
/**
* @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.updateCurrency > 0) {
_abridgedVectors[vectorId].currency = uint160(_newVector.currency);
}
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-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);
}
/* solhint-disable code-complexity */
/**
* @notice See {IMechanicMintManager-mechanicMintNum}
*/
function mechanicMintNum(
bytes32 mechanicVectorId,
address recipient,
uint32 numToMint,
bytes memory data
) external payable {
MechanicVectorMetadata memory _mechanicVectorMetadata = mechanicVectorMetadata[mechanicVectorId];
address msgSender = _msgSender();
if (_mechanicVectorMetadata.paused) {
_revert(MechanicPaused.selector);
}
if (_mechanicVectorMetadata.isChoose) {
_revert(InvalidMechanic.selector);
}
// constant gasless mechanic address
if (_mechanicVectorMetadata.mechanic == _gaslessMechanicAddress) {
if (!_isGelatoRelay(msgSender)) {
_revert(UnauthorizedGaslessRelayer.selector);
}
IMechanic(_mechanicVectorMetadata.mechanic).processNumMint(
mechanicVectorId,
recipient,
numToMint,
msgSender,
_mechanicVectorMetadata,
abi.encode(_getFee(), _getFeeCollector(), data)
);
} else {
uint256 _platformFee = IMintFeeOracle(_mintFeeOracle).getMechanicMintFee(
mechanicVectorId,
numToMint,
_mechanicVectorMetadata.mechanic,
msgSender,
_mechanicVectorMetadata.contractAddress
);
if (msg.value < _platformFee) {
_revert(MintFeeTooLow.selector);
}
IMechanic(_mechanicVectorMetadata.mechanic).processNumMint{ value: msg.value - _platformFee }(
mechanicVectorId,
recipient,
numToMint,
msgSender,
_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 memory data
) external payable {
MechanicVectorMetadata memory _mechanicVectorMetadata = mechanicVectorMetadata[mechanicVectorId];
address msgSender = _msgSender();
if (_mechanicVectorMetadata.paused) {
_revert(MechanicPaused.selector);
}
if (!_mechanicVectorMetadata.isChoose) {
_revert(InvalidMechanic.selector);
}
uint32 numToMint = uint32(tokenIds.length);
// constant gasless mechanic address
if (_mechanicVectorMetadata.mechanic == _gaslessMechanicAddress) {
if (!_isGelatoRelay(msgSender)) {
_revert(UnauthorizedGaslessRelayer.selector);
}
IMechanic(_mechanicVectorMetadata.mechanic).processChooseMint(
mechanicVectorId,
recipient,
tokenIds,
msgSender,
_mechanicVectorMetadata,
abi.encode(_getFee(), _getFeeCollector(), data)
);
} else {
uint256 _platformFee = IMintFeeOracle(_mintFeeOracle).getMechanicMintFee(
mechanicVectorId,
numToMint,
_mechanicVectorMetadata.mechanic,
msgSender,
_mechanicVectorMetadata.contractAddress
);
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,
msgSender,
_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) {
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;
if (claim.claimer != msgSender && mintRecipient != claim.claimer) {
_revert(UnsafeMintRecipient.selector);
}
_verifyAndUpdateSeriesClaim(claim, claimSignature, numTokensToMint);
_processClassicVectorPayments(
claim.offchainVectorId,
numTokensToMint,
msgSender,
claim.currency,
claim.pricePerToken,
claim.paymentRecipient,
claim.contractAddress
);
emit ChooseTokenMint(claim.offchainVectorId, claim.contractAddress, false, tokenIds);
// mint NFT(s)
if (numTokensToMint == 1) {
IERC721GeneralMint(claim.contractAddress).mintSpecificTokenToOneRecipient(mintRecipient, tokenIds[0]);
} else {
IERC721GeneralMint(claim.contractAddress).mintSpecificTokensToOneRecipient(mintRecipient, tokenIds);
}
}
/**
* @notice Mint on a collection with sequentially minted token IDs 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 gatedNumMint(
Claim calldata claim,
bytes calldata claimSignature,
address mintRecipient,
bool isEditionBased
) external payable {
address msgSender = _msgSender();
if (claim.claimer != msgSender && mintRecipient != claim.claimer) {
_revert(UnsafeMintRecipient.selector);
}
_verifyAndUpdateClaim(claim, claimSignature);
_processClassicVectorPayments(
claim.offchainVectorId,
claim.numTokensToMint,
msgSender,
claim.currency,
claim.pricePerToken,
claim.paymentRecipient,
claim.contractAddress
);
emit NumTokenMint(claim.offchainVectorId, claim.contractAddress, false, claim.numTokensToMint);
if (isEditionBased) {
if (claim.numTokensToMint == 1) {
IERC721EditionMint(claim.contractAddress).mintOneToRecipient(claim.editionId, mintRecipient);
} else {
IERC721EditionMint(claim.contractAddress).mintAmountToRecipient(
claim.editionId,
mintRecipient,
claim.numTokensToMint
);
}
} else {
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();
AbridgedVectorData memory _vector = _abridgedVectors[vectorId];
uint48 newNumClaimedViaVector = _vector.totalClaimedViaVector + numTokensToMint;
uint48 newNumClaimedForUser = uint48(userClaims[vectorId][mintRecipient]) + numTokensToMint;
if (_vector.requireDirectEOA && msgSender != tx.origin) {
_revert(SenderNotDirectEOA.selector);
}
_abridgedVectors[vectorId].totalClaimedViaVector = newNumClaimedViaVector;
userClaims[vectorId][mintRecipient] = uint64(newNumClaimedForUser);
if (_vector.editionBasedCollection) {
_vectorMintEdition721(
vectorId,
_vector,
numTokensToMint,
mintRecipient,
msgSender,
newNumClaimedViaVector,
newNumClaimedForUser
);
} else {
_vectorMintGeneral721(
vectorId,
_vector,
numTokensToMint,
mintRecipient,
msgSender,
newNumClaimedViaVector,
newNumClaimedForUser
);
}
}
/**
* @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 updatePlatformAndMintFeeOracle(
address payable newPlatform,
address newOracle,
address gaslessMechanic
) external onlyOwner {
if (newPlatform == address(0)) {
_revert(Unauthorized.selector);
}
if (_platform != newPlatform) {
_platform = newPlatform;
}
if (_mintFeeOracle != newOracle) {
_mintFeeOracle = newOracle;
}
if (_gaslessMechanicAddress != gaslessMechanic) {
_gaslessMechanicAddress = gaslessMechanic;
}
}
/**
* @notice Returns if an address is a platform executor
*/
function isPlatformExecutor(address _executor) external view returns (bool) {
return _platformExecutors.contains(_executor);
}
/**
* @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 msg.sender; // temporary
}
/**
* @notice Used for meta-transactions
*/
function _msgData() internal view override(ContextUpgradeable, ERC2771ContextUpgradeable) returns (bytes calldata) {
return msg.data; // temporary
}
/**
* @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 && claim.maxPerTxn != 0) ||
_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
* @param msgSender Minter
*/
function _processVectorMint(
uint256 _vectorId,
AbridgedVectorData memory _vector,
uint48 numTokensToMint,
uint48 newNumClaimedViaVector,
uint48 newNumClaimedForUser,
address msgSender
) 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);
}
_processClassicVectorPayments(
bytes32(_vectorId),
uint256(numTokensToMint),
msgSender,
address(_vector.currency),
_vector.pricePerToken,
payable(address(_vector.paymentRecipient)),
address(_vector.contractAddress)
);
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 msgSender Minter
* @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,
address msgSender,
uint48 newNumClaimedViaVector,
uint48 newNumClaimedForUser
) private {
_processVectorMint(
_vectorId,
_vector,
numTokensToMint,
newNumClaimedViaVector,
newNumClaimedForUser,
msgSender
);
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 msgSender Minter
* @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,
address msgSender,
uint48 newNumClaimedViaVector,
uint48 newNumClaimedForUser
) private {
_processVectorMint(
_vectorId,
_vector,
numTokensToMint,
newNumClaimedViaVector,
newNumClaimedForUser,
msgSender
);
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
* @param totalAmount Total amount being paid
* @param recipient Creator recipient of payment
* @param vectorId ID of vector (on-chain or off-chain)
*/
function _processNativeGasTokenPayment(uint256 totalAmount, address payable recipient, bytes32 vectorId) private {
(bool sentToRecipient, ) = recipient.call{ value: totalAmount }("");
if (!sentToRecipient) {
_revert(EtherSendFailed.selector);
}
emit NativeGasTokenPayment(recipient, vectorId, totalAmount, 10000);
}
/**
* @notice Process payment in ERC20
* @param totalAmount Total amount being paid
* @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,
address recipient,
address payer,
address currency,
bytes32 vectorId
) private {
IERC20(currency).transferFrom(payer, recipient, totalAmount);
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);
}
/* solhint-disable code-complexity */
/**
* @notice Process payments (sale + mint fee) for classic vectors (direct + gated)
* @param vectorId Vector ID
* @param numToMint Number of tokens being minted
* @param msgSender Minter
* @param currency Sale currency
* @param salePrice Sale price
* @param salePaymentRecipient Sale payment recipient
* @param collectionContract Collection NFT contract address
*/
function _processClassicVectorPayments(
bytes32 vectorId,
uint256 numToMint,
address msgSender,
address currency,
uint256 salePrice,
address payable salePaymentRecipient,
address collectionContract
) private {
(uint256 mintFeeCap, bool is1155) = IMintFeeOracle(_mintFeeOracle).getClassicVectorMintFeeCap(
vectorId,
numToMint,
msgSender,
currency,
collectionContract
);
uint256 mintFeeEtherValue = currency == address(0) ? mintFeeCap : 0;
uint256 saleAmount = numToMint * salePrice;
_processClassicVectorPaymentsInner(vectorId, saleAmount, mintFeeEtherValue, currency, salePaymentRecipient);
_processClassicVectorMintFee(
mintFeeCap,
msgSender,
currency,
salePaymentRecipient,
vectorId,
mintFeeEtherValue,
salePrice == 0,
is1155
);
}
/**
* @notice Process payments (sale + mint fee) for classic vectors (direct + gated)
* @param vectorId Vector ID
* @param saleAmount Sale amount
* @param mintFeeEtherValue Mint fee in ether (if existent)
* @param currency Sale currency
* @param salePaymentRecipient Sale payment recipient
*/
function _processClassicVectorPaymentsInner(
bytes32 vectorId,
uint256 saleAmount,
uint256 mintFeeEtherValue,
address currency,
address payable salePaymentRecipient
) private returns (uint256, bool, uint256) {
if (currency == address(0)) {
if (mintFeeEtherValue + saleAmount != msg.value) {
_revert(InvalidPaymentAmount.selector);
}
if (saleAmount > 0) {
// pay in native gas token
_processNativeGasTokenPayment(saleAmount, salePaymentRecipient, vectorId);
}
} else if (saleAmount > 0) {
// pay in ERC20
// tx.origin instead of msgSender for referrals
_processERC20Payment(saleAmount, salePaymentRecipient, tx.origin, currency, vectorId);
}
}
/**
* @notice Helper util to process the classic vector mint fee
*/
function _processClassicVectorMintFee(
uint256 mintFeeCap,
address msgSender,
address currency,
address salePaymentRecipient,
bytes32 vectorId,
uint256 mintFeeEtherValue,
bool isSaleFree,
bool is1155
) private {
if (mintFeeCap > 0) {
if (currency != address(0)) {
// send erc20 mint fee cap to the mint fee oracle
// tx.origin instead of msgSender for referrals
IERC20(currency).transferFrom(tx.origin, _mintFeeOracle, mintFeeCap);
}
uint256 creatorPayout = IMintFeeOracle(_mintFeeOracle).processClassicVectorMintFeeCap{
value: mintFeeEtherValue
}(vectorId, isSaleFree, salePaymentRecipient, currency, mintFeeCap, msgSender, is1155);
if (creatorPayout != 0) {
emit CreatorRewardPayout(vectorId, currency, salePaymentRecipient, creatorPayout);
}
}
}
/* solhint-enable code-complexity */
/**
* @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
pragma solidity ^0.8.1;
import {GELATO_RELAY, GELATO_RELAY_ZKSYNC} from "../constants/GelatoRelay.sol";
abstract contract GelatoRelayBase {
modifier onlyGelatoRelay() {
require(_isGelatoRelay(msg.sender), "onlyGelatoRelay");
_;
}
function _isGelatoRelay(address _forwarder) internal view returns (bool) {
return
block.chainid == 324 || block.chainid == 280
? _forwarder == GELATO_RELAY_ZKSYNC
: _forwarder == GELATO_RELAY;
}
}// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; address constant GELATO_RELAY = 0xaBcC9b596420A9E9172FD5938620E265a0f9Df92; address constant GELATO_RELAY_ERC2771 = 0xb539068872230f20456CF38EC52EF2f91AF4AE49; address constant GELATO_RELAY_CONCURRENT_ERC2771 = 0x8598806401A63Ddf52473F1B3C55bC9E33e2d73b; address constant GELATO_RELAY_ZKSYNC = 0xB16a1DbE755f992636705fDbb3A8678a657EB3ea; address constant GELATO_RELAY_ERC2771_ZKSYNC = 0x22DCC39b2AC376862183dd35A1664798dafC7Da6; // solhint-disable-next-line max-line-length address constant GELATO_RELAY_CONCURRENT_ERC2771_ZKSYNC = 0xBa4082F4961c8Fb76231995C967CD9aa40f321b5;
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; address constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
import {GelatoRelayBase} from "./base/GelatoRelayBase.sol";
import {TokenUtils} from "./lib/TokenUtils.sol";
uint256 constant _FEE_COLLECTOR_START = 72; // offset: address + address + uint256
uint256 constant _FEE_TOKEN_START = 52; // offset: address + uint256
uint256 constant _FEE_START = 32; // offset: uint256
// WARNING: Do not use this free fn by itself, always inherit GelatoRelayContext
// solhint-disable-next-line func-visibility, private-vars-leading-underscore
function _getFeeCollectorRelayContext() pure returns (address feeCollector) {
assembly {
feeCollector := shr(
96,
calldataload(sub(calldatasize(), _FEE_COLLECTOR_START))
)
}
}
// WARNING: Do not use this free fn by itself, always inherit GelatoRelayContext
// solhint-disable-next-line func-visibility, private-vars-leading-underscore
function _getFeeTokenRelayContext() pure returns (address feeToken) {
assembly {
feeToken := shr(96, calldataload(sub(calldatasize(), _FEE_TOKEN_START)))
}
}
// WARNING: Do not use this free fn by itself, always inherit GelatoRelayContext
// solhint-disable-next-line func-visibility, private-vars-leading-underscore
function _getFeeRelayContext() pure returns (uint256 fee) {
assembly {
fee := calldataload(sub(calldatasize(), _FEE_START))
}
}
/**
* @dev Context variant with feeCollector, feeToken and fee appended to msg.data
* Expects calldata encoding:
* abi.encodePacked( _data,
* _feeCollector,
* _feeToken,
* _fee);
* Therefore, we're expecting 20 + 20 + 32 = 72 bytes to be appended to normal msgData
* 32bytes start offsets from calldatasize:
* feeCollector: - 72 bytes
* feeToken: - 52 bytes
* fee: - 32 bytes
*/
/// @dev Do not use with GelatoRelayFeeCollector - pick only one
abstract contract GelatoRelayContext is GelatoRelayBase {
using TokenUtils for address;
// DANGER! Only use with onlyGelatoRelay `_isGelatoRelay` before transferring
function _transferRelayFee() internal {
_getFeeToken().transfer(_getFeeCollector(), _getFee());
}
// DANGER! Only use with onlyGelatoRelay `_isGelatoRelay` before transferring
function _transferRelayFeeCapped(uint256 _maxFee) internal {
uint256 fee = _getFee();
require(
fee <= _maxFee,
"GelatoRelayContext._transferRelayFeeCapped: maxFee"
);
_getFeeToken().transfer(_getFeeCollector(), fee);
}
function _getMsgData() internal view returns (bytes calldata) {
return
_isGelatoRelay(msg.sender)
? msg.data[:msg.data.length - _FEE_COLLECTOR_START]
: msg.data;
}
// Only use with GelatoRelayBase onlyGelatoRelay or `_isGelatoRelay` checks
function _getFeeCollector() internal pure returns (address) {
return _getFeeCollectorRelayContext();
}
// Only use with previous onlyGelatoRelay or `_isGelatoRelay` checks
function _getFeeToken() internal pure returns (address) {
return _getFeeTokenRelayContext();
}
// Only use with previous onlyGelatoRelay or `_isGelatoRelay` checks
function _getFee() internal pure returns (uint256) {
return _getFeeRelayContext();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;
import {NATIVE_TOKEN} from "../constants/Tokens.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {
IERC20Permit
} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";
import {
SafeERC20
} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
library TokenUtils {
using SafeERC20 for IERC20;
using SafeERC20 for IERC20Permit;
modifier onlyERC20(address _token) {
require(_token != NATIVE_TOKEN, "TokenUtils.onlyERC20");
_;
}
function permit(
address _token,
address _owner,
address _spender,
uint256 _value,
uint256 _deadline,
uint8 _v,
bytes32 _r,
bytes32 _s
) internal onlyERC20(_token) {
IERC20Permit(_token).safePermit(
_owner,
_spender,
_value,
_deadline,
_v,
_r,
_s
);
}
function transfer(
address _token,
address _to,
uint256 _amount
) internal {
if (_amount == 0) return;
_token == NATIVE_TOKEN
? Address.sendValue(payable(_to), _amount)
: IERC20(_token).safeTransfer(_to, _amount);
}
function transferFrom(
address _token,
address _from,
address _to,
uint256 _amount
) internal onlyERC20(_token) {
if (_amount == 0) return;
IERC20(_token).safeTransferFrom(_from, _to, _amount);
}
function getBalance(address token, address user)
internal
view
returns (uint256)
{
return
token == NATIVE_TOKEN
? user.balance
: IERC20(token).balanceOf(user);
}
}// 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/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// 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.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// 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 updateCurrency If 1, update currency
* @param updateRequireDirectEOA If 1, update requireDirectEOA
* @param updateMetadata If 1, update MintVector metadata
*/
struct UpdateAbridgedVectorConfig {
uint16 updateStartTimestamp;
uint16 updateEndTimestamp;
uint16 updatePaymentRecipient;
uint16 updateMaxTotalClaimableViaVector;
uint16 updateTokenLimitPerTx;
uint16 updateMaxUserClaimableViaVector;
uint8 updatePricePerToken;
uint8 updateCurrency;
uint8 updateRequireDirectEOA;
uint8 updateMetadata;
}
/**
* @notice Creates on-chain vector
* @param _vector Vector to create
*/
function createAbridgedVector(AbridgedVectorData memory _vector) external;
/**
* @notice Updates on-chain vector
* @param vectorId ID of vector to update
* @param _newVector New vector details
* @param updateConfig Number encoding what fields to update
* @param pause Pause / unpause vector
* @param flexibleData Flexible data in vector metadata
*/
function updateAbridgedVector(
uint256 vectorId,
AbridgedVector calldata _newVector,
UpdateAbridgedVectorConfig calldata updateConfig,
bool pause,
uint128 flexibleData
) external;
/**
* @notice Pauses or unpauses an on-chain mint vector
* @param vectorId ID of abridged vector to pause
* @param pause True to pause, False to unpause
* @param flexibleData Flexible data that can be interpreted differently
*/
function setAbridgedVectorMetadata(uint256 vectorId, bool pause, uint128 flexibleData) external;
/**
* @notice Get on-chain abridged vector
* @param vectorId ID of abridged vector to get
*/
function getAbridgedVector(uint256 vectorId) external view returns (AbridgedVector memory);
/**
* @notice Get on-chain abridged vector metadata
* @param vectorId ID of abridged vector to get
*/
function getAbridgedVectorMetadata(uint256 vectorId) external view returns (bool, uint128);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
/**
* @title MintManager interface for a mint fee oracle
* @author highlight.xyz
*/
interface IMintFeeOracle {
/**
* @notice Process the mint fee for a classic mv
* @param vectorId Vector ID
* @param payoutCreatorReward Payout creator reward
* @param vectorPaymentRecipient Vector payment recipient
* @param currency Mint fee currency currency
* @param amount Sale amount
* @param minter Minter address
* @param is1155 If collection contract is an 1155
*/
function processClassicVectorMintFeeCap(
bytes32 vectorId,
bool payoutCreatorReward,
address vectorPaymentRecipient,
address currency,
uint256 amount,
address minter,
bool is1155
) external payable returns (uint256);
/**
* @notice Get the mint fee cap for a classic mv
* @param vectorId Vector ID (bytes32)
* @param numToMint Number of tokens to mint in this transaction
* @param minter Minter address
* @param currency Sale currency
* @param collectionContract Collection NFT contract
*/
function getClassicVectorMintFeeCap(
bytes32 vectorId,
uint256 numToMint,
address minter,
address currency,
address collectionContract
) external view returns (uint256, bool);
/**
* @notice Get the mint fee for a mechanic mint mv
* @param vectorId Vector ID
* @param numToMint Number of tokens to mint in this transaction
* @param mechanic Address of mechanic facilitating mint
* @param minter Address minting
* @param collectionContract Collection NFT contract
*/
function getMechanicMintFee(
bytes32 vectorId,
uint32 numToMint,
address mechanic,
address minter,
address collectionContract
) external view returns (uint256);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.10;
/**
* @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 minter Account that called mint on the MintManager
* @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,
address minter,
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 minter Account that called mint on the MintManager
* @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,
address minter,
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":"UnauthorizedGaslessRelayer","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":"bytes32","name":"vectorId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"currency","type":"address"},{"indexed":true,"internalType":"address","name":"rewardRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CreatorRewardPayout","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":"newPlatformMintFee","type":"uint256"}],"name":"PlatformMintFeeUpdated","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":[{"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"},{"internalType":"bool","name":"isEditionBased","type":"bool"}],"name":"gatedNumMint","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"},{"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":"updateCurrency","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":"address","name":"newOracle","type":"address"},{"internalType":"address","name":"gaslessMechanic","type":"address"}],"name":"updatePlatformAndMintFeeOracle","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
60a06040523060805234801561001457600080fd5b50608051615f946200004d600039600081816119ee01528181611a3701528181611bf001528181611c300152611de10152615f946000f3fe6080604052600436106101895760003560e01c8063041050181461018e57806306056f831461024f5780630dbb18a1146102645780631d9165aa1461029f57806323bc2078146102b25780632cf9adc8146102c55780633659cfe6146102e55780633716e28414610305578063391a6d28146103355780634f1ef2861461035557806352169be81461036857806352d1902d14610388578063532742461461039d57806356292ab5146103e4578063572b6c0514610404578063619b8589146104335780636c1b7abd14610551578063715018a61461056457806377a856ea146105795780637ced595c146105995780637e5811fc146105ac5780638a320d64146105cc5780638da5cb5b146109bc5780639e2dc500146109de578063a0f7652314610a2c578063b052d17c14610a85578063b414ae2f14610aa5578063c462507e14610ad2578063e28be14414610b39578063e2f66b1e14610b59578063f2fde38b14610b79578063f4a4034514610b99578063f7013ef614610bb9578063fc2c997114610bd9575b600080fd5b34801561019a57600080fd5b506101ff6101a9366004614cd1565b60a960205260009081526040902080546001909101546001600160a01b03808316926001600160601b03600160a01b9182900416929182169160ff918104821691600160a81b8204811691600160b01b90041686565b604080516001600160a01b0397881681526001600160601b039096166020870152959093169484019490945215156060830152911515608082015290151560a082015260c0015b60405180910390f35b61026261025d366004614d5e565b610bec565b005b34801561027057600080fd5b5061029161027f366004614cd1565b60a16020526000908152604090205481565b604051908152602001610246565b6102626102ad366004614ec9565b610f56565b6102626102c0366004614f62565b61132d565b3480156102d157600080fd5b506102626102e0366004614fd9565b611533565b3480156102f157600080fd5b5061026261030036600461504c565b6119e3565b34801561031157600080fd5b50610325610320366004615070565b611ab5565b6040519015158152602001610246565b34801561034157600080fd5b50610262610350366004615092565b611ad6565b6102626103633660046150d0565b611be5565b34801561037457600080fd5b5061026261038336600461511f565b611c9f565b34801561039457600080fd5b50610291611dd4565b3480156103a957600080fd5b506102916103b836600461514f565b600082815260a1602090815260408083206001600160a01b038516845260010190915290205492915050565b3480156103f057600080fd5b506102626103ff366004615174565b611e82565b34801561041057600080fd5b5061032561041f36600461504c565b606a546001600160a01b0391821691161490565b34801561043f57600080fd5b506104d361044e366004614cd1565b609d602052600090815260409020805460018201546002830154600384015460048501546005860154600687015460078801546008909801546001600160a01b039788169896881697909516959394929391926001600160401b0380831693600160401b8404821693600160801b8104831693600160c01b9091049092169160ff168c565b604080516001600160a01b039d8e1681529b8d1660208d015299909b16988a01989098526060890196909652608088019490945260a08701929092526001600160401b0390811660c087015290811660e08601529081166101008501521661012083015261014082015260ff90911661016082015261018001610246565b61026261055f3660046151e5565b611f3f565b34801561057057600080fd5b5061026261214d565b34801561058557600080fd5b50610262610594366004615285565b612161565b6102626105a73660046152b5565b61233f565b3480156105b857600080fd5b506102626105c7366004614cd1565b612671565b3480156105d857600080fd5b506109af6105e7366004614cd1565b604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a0810191909152600060a76000848152602001908152602001600020604051806101c00160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016000820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160008201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160018201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016002820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016002820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160028201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016003820160009054906101000a90046001600160c01b03166001600160c01b03166001600160c01b031681526020016003820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160038201601e9054906101000a900460ff1615151515815260200160038201601f9054906101000a900460ff161515151581526020016004820154815250509050604051806101c0016040528082600001516001600160a01b03168152602001826020015165ffffffffffff168152602001826040015165ffffffffffff16815260200182606001516001600160a01b03168152602001826080015165ffffffffffff1681526020018260a0015165ffffffffffff1681526020018260c001516001600160a01b031681526020018260e0015165ffffffffffff16815260200182610100015165ffffffffffff1681526020018261012001516001600160c01b0316815260200182610140015165ffffffffffff1681526020018261016001511515815260200182610180015115158152602001826101a00151815250915050919050565b6040516102469190615340565b3480156109c857600080fd5b506109d161270b565b6040516102469190615443565b3480156109ea57600080fd5b50610a1f6109f936600461514f565b609f6020908152600092835260408084209091529082529020546001600160401b031681565b6040516102469190615457565b348015610a3857600080fd5b50610a66610a47366004614cd1565b600090815260a860205260409020546001811615159160809190911c90565b6040805192151583526001600160801b03909116602083015201610246565b348015610a9157600080fd5b50610262610aa036600461504c565b61271a565b348015610ab157600080fd5b50610291610ac0366004614cd1565b60a26020526000908152604090205481565b348015610ade57600080fd5b50610b15610aed366004614cd1565b609e6020526000908152604090205460ff808216916101008104821691620100009091041683565b6040805160ff94851681529284166020840152921691810191909152606001610246565b348015610b4557600080fd5b50610262610b54366004615482565b612766565b348015610b6557600080fd5b50610325610b7436600461504c565b612a8b565b348015610b8557600080fd5b50610262610b9436600461504c565b612a98565b348015610ba557600080fd5b50610325610bb436600461555c565b612b0e565b348015610bc557600080fd5b50610262610bd43660046155c5565b612c49565b610262610be7366004615629565b612dea565b33838015610bf8578096505b816001600160a01b03168a6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c64919061569d565b6001600160a01b03161480610c8a5750896001600160a01b0316826001600160a01b0316145b15610f3b578815610d51578660011415610d155760405163b859c93560e01b81526001600160a01b038b169063b859c93590610ccc908b9087906004016156ba565b6020604051808303816000875af1158015610ceb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0f91906156d1565b50610ea1565b604051631b30808d60e01b8152600481018990526001600160a01b038481166024830152604482018990528b1690631b30808d90606401610ccc565b8660011415610e0a578315610dde57896001600160a01b0316630d640e818488886000818110610d8357610d836156ea565b905060200201356040518363ffffffff1660e01b8152600401610da7929190615700565b600060405180830381600087803b158015610dc157600080fd5b505af1158015610dd5573d6000803e3d6000fd5b50505050610ea1565b60405163184a94d560e01b81526001600160a01b038b169063184a94d590610ccc908690600401615443565b8315610e4057604051636371fbe760e01b81526001600160a01b038b1690636371fbe790610da79086908a908a9060040161574f565b604051630b7d2a8960e31b81526001600160a01b038b1690635be9544890610e6e9086908b90600401615700565b600060405180830381600087803b158015610e8857600080fd5b505af1158015610e9c573d6000803e3d6000fd5b505050505b8315610eef57896001600160a01b03167f4e84cd8521d66b0c0a2d95e21910942e1616948e140df953825b0cb02c32a5e98787604051610ee292919061577d565b60405180910390a2610f4a565b878915158b6001600160a01b03167f4c0491da007181c9465d71c51f64ba4f8eb23133900a4bb2dae027b0c2252c3f8a604051610f2e91815260200190565b60405180910390a4610f4a565b610f4a6282b42960e81b613259565b50505050505050505050565b600085815260a96020908152604091829020825160c08101845281546001600160a01b0380821683526001600160601b03600160a01b9283900416948301949094526001909201549283169381019390935260ff908204811615156060840152600160a81b8204811615156080840152600160b01b9091041615801560a08301523390610fed57610fed6337e9321960e21b613259565b816080015161100657611006633bed786f60e21b613259565b60ab54604083015185916001600160a01b03918216911614156110e45761102c82613263565b6110405761104063ac3274ef60e01b613259565b82604001516001600160a01b031663c4804ce28989898987896110616132c5565b6110696132d3565b8d60405160200161107c939291906157e9565b6040516020818303038152906040526040518863ffffffff1660e01b81526004016110ad9796959493929190615867565b600060405180830381600087803b1580156110c757600080fd5b505af11580156110db573d6000803e3d6000fd5b505050506111f7565b60aa5460408085015185519151634b48652b60e11b81526000936001600160a01b031692639690ca5692611122928e928892918a91906004016158cc565b602060405180830381865afa15801561113f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116391906156d1565b90508034101561117d5761117d63207226af60e01b613259565b60408401516001600160a01b031663c4804ce261119a8334615916565b8b8b8b8b898b8d6040518963ffffffff1660e01b81526004016111c39796959493929190615867565b6000604051808303818588803b1580156111dc57600080fd5b505af11580156111f0573d6000803e3d6000fd5b5050505050505b8063ffffffff16600114156112835782516001600160a01b0316630d640e81888888600081611228576112286156ea565b905060200201356040518363ffffffff1660e01b815260040161124c929190615700565b600060405180830381600087803b15801561126657600080fd5b505af115801561127a573d6000803e3d6000fd5b505050506112e9565b8251604051636371fbe760e01b81526001600160a01b0390911690636371fbe7906112b6908a908a908a9060040161574f565b600060405180830381600087803b1580156112d057600080fd5b505af11580156112e4573d6000803e3d6000fd5b505050505b6001151583600001516001600160a01b031689600080516020615ec1833981519152898960405161131b92919061577d565b60405180910390a45050505050505050565b600033600085815260a76020908152604080832081516101c08101835281546001600160a01b03808216835265ffffffffffff600160a01b808404821697850197909752600160d01b928390048116958401959095526001840154808216606085015286810486166080850152829004851660a08401819052600285015491821660c0850152958104851660e084015204831661010082015260038201546001600160c01b038116610120830152600160c01b810490931661014082015260ff600160f01b840481161515610160830152600160f81b9093049092161515610180830152600401546101a082015292935061142990869061592d565b6000878152609f602090815260408083206001600160a01b0389168452909152812054919250906114649087906001600160401b031661592d565b9050826101800151801561148157506001600160a01b0384163214155b1561149657611496630977d34b60e01b613259565b600087815260a760209081526040808320600101805465ffffffffffff808816600160d01b026001600160d01b0390921691909117909155609f83528184206001600160a01b038a16855290925290912080546001600160401b0319169183169190911790556101608301511561151b57611516878488888887876132df565b61152a565b61152a87848888888787613414565b50505050505050565b600085815260a760205260408120546001600160a01b031690339050806001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611597573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bb919061569d565b6001600160a01b031614806115e15750816001600160a01b0316816001600160a01b0316145b156119d45760006115f56020870187615957565b61ffff1611156116455761160f604087016020880161597b565b600088815260a760205260409020805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b60006116576040870160208801615957565b61ffff1611156116a457611671606087016040880161597b565b600088815260a760205260409020805465ffffffffffff92909216600160d01b026001600160d01b039092169190911790555b60006116b66060870160408801615957565b61ffff161115611700576116d0608087016060880161504c565b600088815260a76020526040902060010180546001600160a01b0319166001600160a01b03929092169190911790555b60006117126080870160608801615957565b61ffff1611156117655761172c60a087016080880161597b565b600088815260a760205260409020600101805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b600061177760a0870160808801615957565b61ffff1611156117cb57611792610100870160e0880161597b565b600088815260a760205260409020600201805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b60006117dd60c0870160a08801615957565b61ffff16111561182f576117f96101208701610100880161597b565b600088815260a760205260409020600201805465ffffffffffff92909216600160d01b026001600160d01b039092169190911790555b600061184160e0870160c08801615998565b60ff16111561188c5761185c610140870161012088016159d0565b600088815260a76020526040902060030180546001600160c01b0319166001600160c01b03929092169190911790555b600061189f610100870160e08801615998565b60ff1611156118e8576118b860e0870160c0880161504c565b600088815260a76020526040902060020180546001600160a01b0319166001600160a01b03929092169190911790555b60006118fc61012087016101008801615998565b60ff161115611945576119176101a0870161018088016159ed565b600088815260a7602052604090206003018054911515600160f81b026001600160f81b039092169190911790555b600061195961014087016101208801615998565b60ff1611156119a45761196c84846134d7565b600088815260a860205260408082209290925590516001600160801b03851691861515918a91600080516020615f6883398151915291a45b60405187907fe772ce44f6b7edf20d62f174efc62c5a18484d62a710bd48d57af1afd140811c90600090a261152a565b61152a6282b42960e81b613259565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415611a355760405162461bcd60e51b8152600401611a2c90615a0a565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611a676134fc565b6001600160a01b031614611a8d5760405162461bcd60e51b8152600401611a2c90615a44565b611a9681613518565b60408051600080825260208201909252611ab291839190613520565b50565b600082815260a060205260408120611acd908361368b565b90505b92915050565b600083815260a760205260408120546001600160a01b031690339050806001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5e919061569d565b6001600160a01b03161480611b845750816001600160a01b0316816001600160a01b0316145b15611bcf57611b9384846134d7565b600086815260a860205260408082209290925590516001600160801b03851691861515918891600080516020615f6883398151915291a4611bde565b611bde6282b42960e81b613259565b5050505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415611c2e5760405162461bcd60e51b8152600401611a2c90615a0a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611c606134fc565b6001600160a01b031614611c865760405162461bcd60e51b8152600401611a2c90615a44565b611c8f82613518565b611c9b82826001613520565b5050565b600082815260a9602052604090205433906001600160a01b031680611cce57611cce633bed786f60e21b613259565b816001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d3a919061569d565b6001600160a01b03161480611d605750806001600160a01b0316826001600160a01b0316145b15611d9057600084815260a960205260409020600101805460ff60b01b1916600160b01b85151502179055611d9f565b611d9f6282b42960e81b613259565b6040518315159085907fa5a0d9b368dd777972caaaa919c8ca3243792928d90f1b032a1bab6b243a73ab90600090a350505050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611e6f5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401611a2c565b50600080516020615f0183398151915290565b611e8a613697565b6001600160a01b038316611ea757611ea76282b42960e81b613259565b609c546001600160a01b03848116911614611ed857609c80546001600160a01b0319166001600160a01b0385161790555b60aa546001600160a01b03838116911614611f095760aa80546001600160a01b0319166001600160a01b0384161790555b60ab546001600160a01b03828116911614611f3a5760ab80546001600160a01b0319166001600160a01b0383161790555b505050565b338181611f5260608a0160408b0161504c565b6001600160a01b031614158015611f8a5750611f746060890160408a0161504c565b6001600160a01b0316856001600160a01b031614155b15611f9f57611f9f6343d0477760e01b613259565b611fab888888846136f6565b611ff36101408901358284611fc360208d018d61504c565b8c608001358d6060016020810190611fdb919061504c565b8e6020016020810190611fee919061504c565b61393c565b600061200560408a0160208b0161504c565b6001600160a01b0316896101400135600080516020615ec1833981519152878760405161203392919061577d565b60405180910390a480600114156120d1576120546040890160208a0161504c565b6001600160a01b0316630d640e818686866000818110612076576120766156ea565b905060200201356040518363ffffffff1660e01b815260040161209a929190615700565b600060405180830381600087803b1580156120b457600080fd5b505af11580156120c8573d6000803e3d6000fd5b50505050612143565b6120e16040890160208a0161504c565b6001600160a01b0316636371fbe78686866040518463ffffffff1660e01b81526004016121109392919061574f565b600060405180830381600087803b15801561212a57600080fd5b505af115801561213e573d6000803e3d6000fd5b505050505b5050505050505050565b612155613697565b61215f6000613a1d565b565b3380612170602084018461504c565b6001600160a01b0316148061220357506001600160a01b038116612197602084018461504c565b6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f8919061569d565b6001600160a01b0316145b1561233057600061221a60c0840160a0850161597b565b65ffffffffffff1611156122385761223863875fc25f60e01b613259565b60a3805490600061224883615a7e565b909155505060a354600090815260a760205260409020829061226a8282615acd565b5061227f9050610180830161016084016159ed565b156122e757612291602083018361504c565b6001600160a01b03166122ac6101608401610140850161597b565b65ffffffffffff1660a3547fa712e8b25b3d4d043988e80f0a4087773b1c7e29e4115a4256e86aebe91c9be960405160405180910390a45050565b6122f4602083018361504c565b6001600160a01b031660a3547f7258df9bfe0a9fb9cf1285396575e6472f56ca38b4851afcb725c82726fd67ff60405160405180910390a35050565b611c9b6282b42960e81b613259565b3380612351606088016040890161504c565b6001600160a01b0316141580156123895750612373606087016040880161504c565b6001600160a01b0316836001600160a01b031614155b1561239e5761239e6343d0477760e01b613259565b6123a9868686613a6f565b6123fd6101608701356123c260c0890160a08a01615ca0565b6001600160401b0316836123d960208b018b61504c565b60808b018035906123ed9060608e0161504c565b611fee60408e0160208f0161504c565b600061240f604088016020890161504c565b6001600160a01b0316610160880135600080516020615f4883398151915261243d60c08b0160a08c01615ca0565b60405161244a9190615457565b60405180910390a4811561257b5761246860c0870160a08801615ca0565b6001600160401b03166001141561250457612489604087016020880161504c565b6001600160a01b031663b859c935876101000135856040518363ffffffff1660e01b81526004016124bb9291906156ba565b6020604051808303816000875af11580156124da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124fe91906156d1565b50612669565b612514604087016020880161504c565b6001600160a01b0316631b30808d6101008801358561253960c08b0160a08c01615ca0565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b0390911660248301526001600160401b031660448201526064016124bb565b61258b60c0870160a08801615ca0565b6001600160401b0316600114156125d7576125ac604087016020880161504c565b6001600160a01b031663184a94d5846040518263ffffffff1660e01b81526004016124bb9190615443565b6125e7604087016020880161504c565b6001600160a01b0316635be954488461260660c08a0160a08b01615ca0565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160401b03166024820152604401600060405180830381600087803b15801561265557600080fd5b505af1158015610f4a573d6000803e3d6000fd5b505050505050565b609c546001600160a01b0316336001600160a01b03161461269b5761269b6282b42960e81b613259565b609c5460405160009182916001600160a01b039091169084908381818185875af1925050503d80600081146126ec576040519150601f19603f3d011682016040523d82523d6000602084013e6126f1565b606091505b509150915081611f3a57611f3a637cd69c3960e11b613259565b6038546001600160a01b031690565b612722613697565b6001600160a01b038116612740576127406340f3a16b60e01b613259565b61274b60a482613c39565b1561275b57611c9b60a482613c4e565b611c9b60a482613c63565b83516020808601516040808801516060808a015183516001600160601b031997831b8816818801526001600160a01b031960a096871b811660348301529390921b9096168184015294151560f81b60548601529187901b90911660558401528051808403604101815260619093019052815191012084513391906001600160a01b031682148061286c5750816001600160a01b031686600001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561283d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612861919061569d565b6001600160a01b0316145b1561299a57600081815260a960205260409020546001600160a01b03161561289e5761289e63250675bd60e21b613259565b85516001600160a01b031615806128c0575060408601516001600160a01b0316155b806128d85750856060015180156128d8575085608001515b806128e1575080155b156128f6576128f6633bed786f60e21b613259565b600060a0870181815282825260a960209081526040928390208951918a01516001600160a01b03928316600160a01b6001600160601b039092168202178255938a01516001909101805460608c015160808d01519551939094166001600160a81b0319909116179215159094029190911761ffff60a81b1916600160a81b9215159290920260ff60b01b191691909117600160b01b911515919091021790556129a9565b6129a96282b42960e81b613259565b85604001516001600160a01b0316631a8d37928286866040518463ffffffff1660e01b81526004016129dd93929190615cc9565b600060405180830381600087803b1580156129f757600080fd5b505af1158015612a0b573d6000803e3d6000fd5b5050505085600001516001600160a01b031686604001516001600160a01b0316827f6ec667d7188a57a345b217226db199b2b1e98d2ccdb2eaa555af7ad19324303789602001518a60600151604051612a7b9291906001600160601b039290921682521515602082015260400190565b60405180910390a4505050505050565b6000611ad060a483613c39565b612aa0613697565b6001600160a01b038116612b055760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401611a2c565b611ab281613a1d565b600080612b1c868686613c78565b9050612b2960a482613c39565b8015612b555750610160860135600090815260a060205260409020612b539061014088013561368b565b155b8015612b6657508561012001354211155b8015612bb9575060c08601351580612bb95750610160860135600090815260a1602052604090205460c0870180359190612ba39060a08a01615ca0565b6001600160401b0316612bb69190615cff565b11155b8015612c3d575060e08601351580612c3d5750610160860135600090815260a1602052604080822060e089013592600190910191612bfd9060608b01908b0161504c565b6001600160a01b03168152602081019190915260400160002054612c2760c0890160a08a01615ca0565b6001600160401b0316612c3a9190615cff565b11155b9150505b949350505050565b600054610100900460ff1615808015612c695750600054600160ff909116105b80612c8a5750612c7830613d02565b158015612c8a575060005460ff166001145b612ced5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401611a2c565b6000805460ff191660011790558015612d10576000805461ff0019166101001790555b609c80546001600160a01b0319166001600160a01b038816179055604080518082018252600b81526a26b4b73a26b0b730b3b2b960a91b602080830191909152825180840190935260058352640312e302e360dc1b90830152612d7291613d11565b612d7b84613d92565b612d83613ddb565b612d8c85613a1d565b612d9760a484613c63565b5060a68290558015612669576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050565b600084815260a96020908152604091829020825160c08101845281546001600160a01b0380821683526001600160601b03600160a01b9283900416948301949094526001909201549283169381019390935260ff908204811615156060840152600160a81b8204811615156080840152600160b01b9091041615801560a08301523390612e8157612e816337e9321960e21b613259565b816080015115612e9b57612e9b633bed786f60e21b613259565b60ab5460408301516001600160a01b0390811691161415612f7557612ebf81613263565b612ed357612ed363ac3274ef60e01b613259565b81604001516001600160a01b0316639cc163e58787878587612ef36132c5565b612efb6132d3565b8b604051602001612f0e939291906157e9565b6040516020818303038152906040526040518763ffffffff1660e01b8152600401612f3e96959493929190615d17565b600060405180830381600087803b158015612f5857600080fd5b505af1158015612f6c573d6000803e3d6000fd5b50505050613086565b60aa5460408084015184519151634b48652b60e11b81526000936001600160a01b031692639690ca5692612fb3928c928b92918991906004016158cc565b602060405180830381865afa158015612fd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff491906156d1565b90508034101561300e5761300e63207226af60e01b613259565b60408301516001600160a01b0316639cc163e561302b8334615916565b89898987898b6040518863ffffffff1660e01b815260040161305296959493929190615d17565b6000604051808303818588803b15801561306b57600080fd5b505af115801561307f573d6000803e3d6000fd5b5050505050505b81606001511561317c578363ffffffff166001141561312a578151602083015160405163b859c93560e01b81526001600160601b0390911660048201526001600160a01b0387811660248301529091169063b859c935906044015b6020604051808303816000875af1158015613100573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061312491906156d1565b50613224565b81516020830151604051631b30808d60e01b81526001600160601b0390911660048201526001600160a01b03878116602483015263ffffffff8716604483015290911690631b30808d906064016130e1565b8363ffffffff16600114156131ba57815160405163184a94d560e01b81526001600160a01b039091169063184a94d5906130e1908890600401615443565b8151604051630b7d2a8960e31b81526001600160a01b0390911690635be95448906131f190889063ffffffff891690600401615700565b600060405180830381600087803b15801561320b57600080fd5b505af115801561321f573d6000803e3d6000fd5b505050505b815160405163ffffffff861681526001916001600160a01b0316908890600080516020615f4883398151915290602001612a7b565b8060005260046000fd5b6000466101441480613276575046610118145b61329f576001600160a01b03821673abcc9b596420a9e9172fd5938620e265a0f9df9214611ad0565b6001600160a01b03821673b16a1dbe755f992636705fdbb3a8678a657eb3ea1492915050565b601f1936013590565b905090565b60471936013560601c90565b6132ed878787858588613e0a565b8465ffffffffffff166001141561338957855161014087015160405163b859c93560e01b815265ffffffffffff90911660048201526001600160a01b0386811660248301529091169063b859c935906044015b6020604051808303816000875af115801561335f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061338391906156d1565b5061152a565b8551610140870151604051631b30808d60e01b815265ffffffffffff91821660048201526001600160a01b0387811660248301529188166044820152911690631b30808d906064016020604051808303816000875af11580156133f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061214391906156d1565b613422878787858588613e0a565b8465ffffffffffff166001141561346257855160405163184a94d560e01b81526001600160a01b039091169063184a94d590613340908790600401615443565b8551604051630b7d2a8960e31b81526001600160a01b03868116600483015265ffffffffffff8816602483015290911690635be9544890604401600060405180830381600087803b1580156134b657600080fd5b505af11580156134ca573d6000803e3d6000fd5b5050505050505050505050565b60008083156134e4576001175b6001600160801b0319608084901b1617905092915050565b600080516020615f01833981519152546001600160a01b031690565b611ab2613697565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561355357611f3a83613fb2565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156135ad575060408051601f3d908101601f191682019092526135aa918101906156d1565b60015b6136105760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401611a2c565b600080516020615f01833981519152811461367f5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401611a2c565b50611f3a83838361404c565b6000611acd8383614077565b336136a061270b565b6001600160a01b03161461215f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611a2c565b600061370385858561408f565b610140860135600090815260a1602052604081205491925090613727908490615cff565b905060008360a160008961014001358152602001908152602001600020600101600089604001602081019061375c919061504c565b6001600160a01b03166001600160a01b03168152602001908152602001600020546137879190615cff565b905061379460a484613c39565b15806137d957506137ab60c0880160a08901615ca0565b6001600160401b0316841180156137d957506137cd60c0880160a08901615ca0565b6001600160401b031615155b806138025750610140870135600090815260a0602052604090206138029061012089013561368b565b80613826575061381a61012088016101008901615ca0565b6001600160401b031642115b8061386a575061383c60e0880160c08901615ca0565b6001600160401b03168211801561386a575061385e60e0880160c08901615ca0565b6001600160401b031615155b806138b05750613881610100880160e08901615ca0565b6001600160401b0316811180156138b057506138a4610100880160e08901615ca0565b6001600160401b031615155b156138c5576138c5633b4f091f60e21b613259565b610140870135600090815260a0602052604090206138e8906101208901356140e5565b50610140870135600090815260a1602052604080822084815583926001909101916139199060608c01908c0161504c565b6001600160a01b0316815260208101919091526040016000205550505050505050565b60aa546040516376c1989360e01b815260048101899052602481018890526001600160a01b0387811660448301528681166064830152838116608483015260009283929116906376c198939060a4016040805180830381865afa1580156139a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139cb9190615d6f565b909250905060006001600160a01b038716156139e85760006139ea565b825b905060006139f8878b615d94565b9050613a078b82848b8a6140f1565b5050506134ca848a8a898f878d6000148a614157565b603880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000613a7c848484613c78565b90506000613a9060c0860160a08701615ca0565b610160860135600090815260a16020526040902054613ab8916001600160401b031690615cff565b90506000613acc60c0870160a08801615ca0565b6001600160401b031660a1600088610160013581526020019081526020016000206001016000886040016020810190613b05919061504c565b6001600160a01b03166001600160a01b0316815260200190815260200160002054613b309190615cff565b9050613b3d60a484613c39565b1580613b675750610160860135600090815260a060205260409020613b679061014088013561368b565b80613b76575085610120013542115b80613b9257508560c0013582118015613b92575060c086013515155b80613bae57508560e0013581118015613bae575060e086013515155b15613bc357613bc3633b4f091f60e21b613259565b610160860135600090815260a060205260409020613be6906101408801356140e5565b50610160860135600090815260a160205260408082208481558392600190910191613c179060608b01908b0161504c565b6001600160a01b03168152602081019190915260400160002055505050505050565b6000611acd836001600160a01b038416614077565b6000611acd836001600160a01b0384166142e8565b6000611acd836001600160a01b0384166143db565b6000612c4183838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613cfc9250613cc29150889050614425565b613cd0886101600135614540565b604051602001613ce1929190615db3565b60405160208183030381529060405280519060200120614555565b9061459c565b6001600160a01b03163b151590565b600054610100900460ff16613d385760405162461bcd60e51b8152600401611a2c90615dd9565b815160208084019190912082519183019190912060038290556004819055466002557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f613d868184846145c0565b60015560055550505050565b600054610100900460ff16613db95760405162461bcd60e51b8152600401611a2c90615dd9565b606a80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16613e025760405162461bcd60e51b8152600401611a2c90615dd9565b61215f614609565b8265ffffffffffff16856080015165ffffffffffff16108015613e385750608085015165ffffffffffff1615155b80613e6e57508165ffffffffffff1685610100015165ffffffffffff16108015613e6e575061010085015165ffffffffffff1615155b80613ec6575042856020015165ffffffffffff16118015613e9a5750602085015165ffffffffffff1615155b80613ec65750846040015165ffffffffffff1642118015613ec65750604085015165ffffffffffff1615155b80613ed7575065ffffffffffff8416155b80613f0b57508460e0015165ffffffffffff168465ffffffffffff16118015613f0b575060e085015165ffffffffffff1615155b15613f2057613f2063072b86df60e21b613259565b600086815260a8602052604090205460011615613f4757613f47636be9245d60e11b613259565b613f7b8660001b8565ffffffffffff16838860c001518961012001516001600160c01b03168a606001518b6000015161393c565b845160405165ffffffffffff861681526001916001600160a01b0316908890600080516020615f4883398151915290602001612a7b565b613fbb81613d02565b61401d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401611a2c565b600080516020615f0183398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61405583614639565b6000825111806140625750805b15611f3a576140718383614679565b50505050565b60009081526001919091016020526040902054151590565b6000612c4183838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613cfc92506140d9915088905061469e565b80519060200120614555565b6000611acd83836143db565b600080806001600160a01b038516614139573461410e8888615cff565b1461412357614123637e2897ef60e11b613259565b86156141345761413487858a6147cb565b61414c565b861561414c5761414c878532888c614883565b955095509592505050565b8715612143576001600160a01b038616156141e55760aa546040516323b872dd60e01b81526001600160a01b03808916926323b872dd926141a092329216908d90600401615e24565b6020604051808303816000875af11580156141bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141e39190615e48565b505b60aa54604051636f18e93f60e01b81526004810186905283151560248201526001600160a01b0387811660448301528881166064830152608482018b905289811660a483015283151560c48301526000921690636f18e93f90869060e40160206040518083038185885af1158015614261573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061428691906156d1565b905080156142dd57856001600160a01b0316876001600160a01b0316867f27dcd1d67ca97c55aa198d8494458949bbbddae9336ef0969fc655edb5d2180a846040516142d491815260200190565b60405180910390a45b505050505050505050565b600081815260018301602052604081205480156143d157600061430c600183615916565b855490915060009061432090600190615916565b9050818114614385576000866000018281548110614340576143406156ea565b9060005260206000200154905080876000018481548110614363576143636156ea565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061439657614396615e65565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611ad0565b6000915050611ad0565b60006143e78383614077565b61441d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611ad0565b506000611ad0565b60607f75d70c323d802883252e6285d4bb7cc6fcb7faca7fe3ab1d9e9f260aaa4c3424614455602084018461504c565b614465604085016020860161504c565b614475606086016040870161504c565b614485608087016060880161504c565b608087013561449a60c0890160a08a01615ca0565b6040805160208101989098526001600160a01b03968716908801529385166060870152918416608086015290921660a084015260c0808401929092526001600160401b031660e080840191909152908401356101008084019190915290840135610120808401919091529084013561014080840191909152908401356101608301528301356101808201526101a0015b6040516020818303038152906040529050919050565b60608160405160200161452a91815260200190565b600061455f614953565b60405161190160f01b6020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050919050565b60008060006145ab8585614977565b915091506145b8816149bd565b509392505050565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b600054610100900460ff166146305760405162461bcd60e51b8152600401611a2c90615dd9565b61215f33613a1d565b61464281613fb2565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060611acd8383604051806060016040528060278152602001615f2160279139614b06565b60607faf2a8dc7de0e027b17ddbe873c600be814993ef395f58475bc9ef0408f7ccf166146ce602084018461504c565b6146de604085016020860161504c565b6146ee606086016040870161504c565b6146fe608087016060880161504c565b608087013561471360c0890160a08a01615ca0565b61472360e08a0160c08b01615ca0565b6147346101008b0160e08c01615ca0565b6147466101208c016101008d01615ca0565b60408051602081019b909b526001600160a01b03998a16908b015296881660608a015294871660808901529290951660a087015260c08601526001600160401b0393841660e08601528316610100850152821661012080850191909152911661014080840191909152908401356101608301528301356101808201526101a00161452a565b6000826001600160a01b03168460405160006040518083038185875af1925050503d8060008114614818576040519150601f19603f3d011682016040523d82523d6000602084013e61481d565b606091505b505090508061483657614836637cd69c3960e11b613259565b60408051858152612710602082015283916001600160a01b038616917f9363885e28e7ba67b096932f9f00dff44742731d6cb4fa26ccd4424e78e41e13910160405180910390a350505050565b6040516323b872dd60e01b81526001600160a01b038316906323b872dd906148b390869088908a90600401615e24565b6020604051808303816000875af11580156148d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148f69190615e48565b50604080516001600160a01b03858116825260208201889052612710828401529151839287811692908616917fc899cbcc4511003ff90131e8b89605738e9a7f4925273377ae479a673cf5038c9181900360600190a45050505050565b6000600254461415614966575060015490565b6132ce6005546003546004546145c0565b6000808251604114156149ae5760208301516040840151606085015160001a6149a287828585614b7e565b945094505050506149b6565b506000905060025b9250929050565b60008160048111156149d1576149d1615e7b565b14156149da5750565b60018160048111156149ee576149ee615e7b565b1415614a375760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401611a2c565b6002816004811115614a4b57614a4b615e7b565b1415614a995760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401611a2c565b6003816004811115614aad57614aad615e7b565b1415611ab25760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401611a2c565b6060600080856001600160a01b031685604051614b239190615e91565b600060405180830381855af49150503d8060008114614b5e576040519150601f19603f3d011682016040523d82523d6000602084013e614b63565b606091505b5091509150614b7486838387614c38565b9695505050505050565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b03831115614bab5750600090506003614c2f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614bff573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116614c2857600060019250925050614c2f565b9150600090505b94509492505050565b60608315614ca2578251614c9b57614c4f85613d02565b614c9b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611a2c565b5081612c41565b612c418383815115614cb75781518083602001fd5b8060405162461bcd60e51b8152600401611a2c9190615ead565b600060208284031215614ce357600080fd5b5035919050565b6001600160a01b03169052565b6001600160a01b0381168114611ab257600080fd5b8015158114611ab257600080fd5b60008083601f840112614d2c57600080fd5b5081356001600160401b03811115614d4357600080fd5b6020830191508360208260051b85010111156149b657600080fd5b60008060008060008060008060e0898b031215614d7a57600080fd5b8835614d8581614cf7565b97506020890135614d9581614d0c565b9650604089013595506060890135945060808901356001600160401b03811115614dbe57600080fd5b614dca8b828c01614d1a565b90955093505060a0890135614dde81614d0c565b915060c0890135614dee81614cf7565b809150509295985092959890939650565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715614e3757614e37614dff565b60405290565b600082601f830112614e4e57600080fd5b81356001600160401b0380821115614e6857614e68614dff565b604051601f8301601f19908116603f01168101908282118183101715614e9057614e90614dff565b81604052838152866020858801011115614ea957600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060808688031215614ee157600080fd5b853594506020860135614ef381614cf7565b935060408601356001600160401b0380821115614f0f57600080fd5b614f1b89838a01614d1a565b90955093506060880135915080821115614f3457600080fd5b50614f4188828901614e3d565b9150509295509295909350565b65ffffffffffff81168114611ab257600080fd5b600080600060608486031215614f7757600080fd5b833592506020840135614f8981614f4e565b91506040840135614f9981614cf7565b809150509250925092565b60006101c08284031215614fb757600080fd5b50919050565b80356001600160801b0381168114614fd457600080fd5b919050565b6000806000806000858703610360811215614ff357600080fd5b863595506150048860208901614fa4565b94506101406101df198201121561501a57600080fd5b506101e08601925061032086013561503181614d0c565b91506150406103408701614fbd565b90509295509295909350565b60006020828403121561505e57600080fd5b813561506981614cf7565b9392505050565b6000806040838503121561508357600080fd5b50508035926020909101359150565b6000806000606084860312156150a757600080fd5b8335925060208401356150b981614d0c565b91506150c760408501614fbd565b90509250925092565b600080604083850312156150e357600080fd5b82356150ee81614cf7565b915060208301356001600160401b0381111561510957600080fd5b61511585828601614e3d565b9150509250929050565b6000806040838503121561513257600080fd5b82359150602083013561514481614d0c565b809150509250929050565b6000806040838503121561516257600080fd5b82359150602083013561514481614cf7565b60008060006060848603121561518957600080fd5b833561519481614cf7565b92506020840135614f8981614cf7565b60008083601f8401126151b657600080fd5b5081356001600160401b038111156151cd57600080fd5b6020830191508360208285010111156149b657600080fd5b6000806000806000808688036101c081121561520057600080fd5b6101608082121561521057600080fd5b88975087013590506001600160401b038082111561522d57600080fd5b6152398a838b016151a4565b9097509550610180890135915061524f82614cf7565b9093506101a0880135908082111561526657600080fd5b5061527389828a01614d1a565b979a9699509497509295939492505050565b60006101c0828403121561529857600080fd5b611acd8383614fa4565b60006101808284031215614fb757600080fd5b60008060008060006101e086880312156152ce57600080fd5b6152d887876152a2565b94506101808601356001600160401b038111156152f457600080fd5b615300888289016151a4565b9095509350506101a086013561531581614cf7565b91506101c086013561532681614d0c565b809150509295509295909350565b65ffffffffffff169052565b60006101c082019050615354828451614cea565b60208301516153666020840182615334565b5060408301516153796040840182615334565b50606083015161538c6060840182614cea565b50608083015161539f6080840182615334565b5060a08301516153b260a0840182615334565b5060c08301516153c560c0840182614cea565b5060e08301516153d860e0840182615334565b50610100808401516153ec82850182615334565b5050610120838101516001600160c01b0316908301526101408084015161541582850182615334565b505061016083810151151590830152610180808401511515908301526101a092830151929091019190915290565b6001600160a01b0391909116815260200190565b6001600160401b0391909116815260200190565b80356001600160601b0381168114614fd457600080fd5b60008060008084860361010081121561549a57600080fd5b60c08112156154a857600080fd5b506154b1614e15565b85356154bc81614cf7565b81526154ca6020870161546b565b602082015260408601356154dd81614cf7565b604082015260608601356154f081614d0c565b6060820152608086013561550381614d0c565b608082015260a086013561551681614d0c565b60a0820152935061552960c0860161546b565b925060e08501356001600160401b0381111561554457600080fd5b615550878288016151a4565b95989497509550505050565b6000806000806101c0858703121561557357600080fd5b61557d86866152a2565b93506101808501356001600160401b0381111561559957600080fd5b6155a5878288016151a4565b9094509250506101a08501356155ba81614cf7565b939692955090935050565b600080600080600060a086880312156155dd57600080fd5b85356155e881614cf7565b945060208601356155f881614cf7565b9350604086013561560881614cf7565b9250606086013561561881614cf7565b949793965091946080013592915050565b6000806000806080858703121561563f57600080fd5b84359350602085013561565181614cf7565b9250604085013563ffffffff8116811461566a57600080fd5b915060608501356001600160401b0381111561568557600080fd5b61569187828801614e3d565b91505092959194509250565b6000602082840312156156af57600080fd5b815161506981614cf7565b9182526001600160a01b0316602082015260400190565b6000602082840312156156e357600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03929092168252602082015260400190565b81835260006001600160fb1b0383111561573257600080fd5b8260051b8083602087013760009401602001938452509192915050565b6001600160a01b03841681526040602082018190526000906157749083018486615719565b95945050505050565b602081526000612c41602083018486615719565b60005b838110156157ac578181015183820152602001615794565b838111156140715750506000910152565b600081518084526157d5816020860160208601615791565b601f01601f19169290920160200192915050565b8381526001600160a01b0383166020820152606060408201819052600090615774908301846157bd565b80516001600160a01b0390811683526020808301516001600160601b0316908401526040808301519091169083015260608082015115159083015260808082015115159083015260a0908101511515910152565b8781526001600160a01b03878116602083015261016060408301819052600091615894848301898b615719565b908716606085015290506158ab6080840186615813565b8281036101408401526158be81856157bd565b9a9950505050505050505050565b94855263ffffffff9390931660208501526001600160a01b0391821660408501528116606084015216608082015260a00190565b634e487b7160e01b600052601160045260246000fd5b60008282101561592857615928615900565b500390565b600065ffffffffffff80831681851680830382111561594e5761594e615900565b01949350505050565b60006020828403121561596957600080fd5b813561ffff8116811461506957600080fd5b60006020828403121561598d57600080fd5b813561506981614f4e565b6000602082840312156159aa57600080fd5b813560ff8116811461506957600080fd5b6001600160c01b0381168114611ab257600080fd5b6000602082840312156159e257600080fd5b8135615069816159bb565b6000602082840312156159ff57600080fd5b813561506981614d0c565b6020808252602c90820152600080516020615ee183398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c90820152600080516020615ee183398151915260408201526b6163746976652070726f787960a01b606082015260800190565b6000600019821415615a9257615a92615900565b5060010190565b60008135611ad081614cf7565b60008135611ad081614f4e565b60008135611ad0816159bb565b60008135611ad081614d0c565b615af6615ad983615a99565b82546001600160a01b0319166001600160a01b0391909116178255565b615b2d615b0560208401615aa6565b82805465ffffffffffff60a01b191660a09290921b65ffffffffffff60a01b16919091179055565b615b60615b3c60408401615aa6565b8280546001600160d01b031660d09290921b6001600160d01b031916919091179055565b60018101615b73615ad960608501615a99565b615b82615b0560808501615aa6565b615b91615b3c60a08501615aa6565b5060028101615ba5615ad960c08501615a99565b615bb4615b0560e08501615aa6565b615bc4615b3c6101008501615aa6565b5060038101615bf6615bd96101208501615ab3565b82546001600160c01b0319166001600160c01b0391909116178255565b615c2e615c066101408501615aa6565b82805465ffffffffffff60c01b191660c09290921b65ffffffffffff60c01b16919091179055565b615c5c615c3e6101608501615ac0565b82805460ff60f01b191691151560f01b60ff60f01b16919091179055565b615c90615c6c6101808501615ac0565b8280546001600160f81b031691151560f81b6001600160f81b031916919091179055565b506101a082013560048201555050565b600060208284031215615cb257600080fd5b81356001600160401b038116811461506957600080fd5b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008219821115615d1257615d12615900565b500190565b8681526001600160a01b03868116602083015263ffffffff86166040830152841660608201526000610160615d4f6080840186615813565b80610140840152615d62818401856157bd565b9998505050505050505050565b60008060408385031215615d8257600080fd5b82519150602083015161514481614d0c565b6000816000190483118215151615615dae57615dae615900565b500290565b60008351615dc5818460208801615791565b83519083019061594e818360208801615791565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060208284031215615e5a57600080fd5b815161506981614d0c565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60008251615ea3818460208701615791565b9190910192915050565b602081526000611acd60208301846157bd56fee0bf8a4af82e2af496af5f4957e2767f8b52e51a77caedd2f30a1843872d1b7c46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564981414aed4973b05aa301314dc13a5a4077f24490497b98bc270852581c1c578aaca5cb46300e4b20595b143bc883119e775ef88ff77f45fa989ca323576f06ba164736f6c634300080a000a
Deployed Bytecode
0x6080604052600436106101895760003560e01c8063041050181461018e57806306056f831461024f5780630dbb18a1146102645780631d9165aa1461029f57806323bc2078146102b25780632cf9adc8146102c55780633659cfe6146102e55780633716e28414610305578063391a6d28146103355780634f1ef2861461035557806352169be81461036857806352d1902d14610388578063532742461461039d57806356292ab5146103e4578063572b6c0514610404578063619b8589146104335780636c1b7abd14610551578063715018a61461056457806377a856ea146105795780637ced595c146105995780637e5811fc146105ac5780638a320d64146105cc5780638da5cb5b146109bc5780639e2dc500146109de578063a0f7652314610a2c578063b052d17c14610a85578063b414ae2f14610aa5578063c462507e14610ad2578063e28be14414610b39578063e2f66b1e14610b59578063f2fde38b14610b79578063f4a4034514610b99578063f7013ef614610bb9578063fc2c997114610bd9575b600080fd5b34801561019a57600080fd5b506101ff6101a9366004614cd1565b60a960205260009081526040902080546001909101546001600160a01b03808316926001600160601b03600160a01b9182900416929182169160ff918104821691600160a81b8204811691600160b01b90041686565b604080516001600160a01b0397881681526001600160601b039096166020870152959093169484019490945215156060830152911515608082015290151560a082015260c0015b60405180910390f35b61026261025d366004614d5e565b610bec565b005b34801561027057600080fd5b5061029161027f366004614cd1565b60a16020526000908152604090205481565b604051908152602001610246565b6102626102ad366004614ec9565b610f56565b6102626102c0366004614f62565b61132d565b3480156102d157600080fd5b506102626102e0366004614fd9565b611533565b3480156102f157600080fd5b5061026261030036600461504c565b6119e3565b34801561031157600080fd5b50610325610320366004615070565b611ab5565b6040519015158152602001610246565b34801561034157600080fd5b50610262610350366004615092565b611ad6565b6102626103633660046150d0565b611be5565b34801561037457600080fd5b5061026261038336600461511f565b611c9f565b34801561039457600080fd5b50610291611dd4565b3480156103a957600080fd5b506102916103b836600461514f565b600082815260a1602090815260408083206001600160a01b038516845260010190915290205492915050565b3480156103f057600080fd5b506102626103ff366004615174565b611e82565b34801561041057600080fd5b5061032561041f36600461504c565b606a546001600160a01b0391821691161490565b34801561043f57600080fd5b506104d361044e366004614cd1565b609d602052600090815260409020805460018201546002830154600384015460048501546005860154600687015460078801546008909801546001600160a01b039788169896881697909516959394929391926001600160401b0380831693600160401b8404821693600160801b8104831693600160c01b9091049092169160ff168c565b604080516001600160a01b039d8e1681529b8d1660208d015299909b16988a01989098526060890196909652608088019490945260a08701929092526001600160401b0390811660c087015290811660e08601529081166101008501521661012083015261014082015260ff90911661016082015261018001610246565b61026261055f3660046151e5565b611f3f565b34801561057057600080fd5b5061026261214d565b34801561058557600080fd5b50610262610594366004615285565b612161565b6102626105a73660046152b5565b61233f565b3480156105b857600080fd5b506102626105c7366004614cd1565b612671565b3480156105d857600080fd5b506109af6105e7366004614cd1565b604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a0810191909152600060a76000848152602001908152602001600020604051806101c00160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016000820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160008201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016001820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016001820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160018201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016002820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b031681526020016002820160149054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160028201601a9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020016003820160009054906101000a90046001600160c01b03166001600160c01b03166001600160c01b031681526020016003820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160038201601e9054906101000a900460ff1615151515815260200160038201601f9054906101000a900460ff161515151581526020016004820154815250509050604051806101c0016040528082600001516001600160a01b03168152602001826020015165ffffffffffff168152602001826040015165ffffffffffff16815260200182606001516001600160a01b03168152602001826080015165ffffffffffff1681526020018260a0015165ffffffffffff1681526020018260c001516001600160a01b031681526020018260e0015165ffffffffffff16815260200182610100015165ffffffffffff1681526020018261012001516001600160c01b0316815260200182610140015165ffffffffffff1681526020018261016001511515815260200182610180015115158152602001826101a00151815250915050919050565b6040516102469190615340565b3480156109c857600080fd5b506109d161270b565b6040516102469190615443565b3480156109ea57600080fd5b50610a1f6109f936600461514f565b609f6020908152600092835260408084209091529082529020546001600160401b031681565b6040516102469190615457565b348015610a3857600080fd5b50610a66610a47366004614cd1565b600090815260a860205260409020546001811615159160809190911c90565b6040805192151583526001600160801b03909116602083015201610246565b348015610a9157600080fd5b50610262610aa036600461504c565b61271a565b348015610ab157600080fd5b50610291610ac0366004614cd1565b60a26020526000908152604090205481565b348015610ade57600080fd5b50610b15610aed366004614cd1565b609e6020526000908152604090205460ff808216916101008104821691620100009091041683565b6040805160ff94851681529284166020840152921691810191909152606001610246565b348015610b4557600080fd5b50610262610b54366004615482565b612766565b348015610b6557600080fd5b50610325610b7436600461504c565b612a8b565b348015610b8557600080fd5b50610262610b9436600461504c565b612a98565b348015610ba557600080fd5b50610325610bb436600461555c565b612b0e565b348015610bc557600080fd5b50610262610bd43660046155c5565b612c49565b610262610be7366004615629565b612dea565b33838015610bf8578096505b816001600160a01b03168a6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c64919061569d565b6001600160a01b03161480610c8a5750896001600160a01b0316826001600160a01b0316145b15610f3b578815610d51578660011415610d155760405163b859c93560e01b81526001600160a01b038b169063b859c93590610ccc908b9087906004016156ba565b6020604051808303816000875af1158015610ceb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0f91906156d1565b50610ea1565b604051631b30808d60e01b8152600481018990526001600160a01b038481166024830152604482018990528b1690631b30808d90606401610ccc565b8660011415610e0a578315610dde57896001600160a01b0316630d640e818488886000818110610d8357610d836156ea565b905060200201356040518363ffffffff1660e01b8152600401610da7929190615700565b600060405180830381600087803b158015610dc157600080fd5b505af1158015610dd5573d6000803e3d6000fd5b50505050610ea1565b60405163184a94d560e01b81526001600160a01b038b169063184a94d590610ccc908690600401615443565b8315610e4057604051636371fbe760e01b81526001600160a01b038b1690636371fbe790610da79086908a908a9060040161574f565b604051630b7d2a8960e31b81526001600160a01b038b1690635be9544890610e6e9086908b90600401615700565b600060405180830381600087803b158015610e8857600080fd5b505af1158015610e9c573d6000803e3d6000fd5b505050505b8315610eef57896001600160a01b03167f4e84cd8521d66b0c0a2d95e21910942e1616948e140df953825b0cb02c32a5e98787604051610ee292919061577d565b60405180910390a2610f4a565b878915158b6001600160a01b03167f4c0491da007181c9465d71c51f64ba4f8eb23133900a4bb2dae027b0c2252c3f8a604051610f2e91815260200190565b60405180910390a4610f4a565b610f4a6282b42960e81b613259565b50505050505050505050565b600085815260a96020908152604091829020825160c08101845281546001600160a01b0380821683526001600160601b03600160a01b9283900416948301949094526001909201549283169381019390935260ff908204811615156060840152600160a81b8204811615156080840152600160b01b9091041615801560a08301523390610fed57610fed6337e9321960e21b613259565b816080015161100657611006633bed786f60e21b613259565b60ab54604083015185916001600160a01b03918216911614156110e45761102c82613263565b6110405761104063ac3274ef60e01b613259565b82604001516001600160a01b031663c4804ce28989898987896110616132c5565b6110696132d3565b8d60405160200161107c939291906157e9565b6040516020818303038152906040526040518863ffffffff1660e01b81526004016110ad9796959493929190615867565b600060405180830381600087803b1580156110c757600080fd5b505af11580156110db573d6000803e3d6000fd5b505050506111f7565b60aa5460408085015185519151634b48652b60e11b81526000936001600160a01b031692639690ca5692611122928e928892918a91906004016158cc565b602060405180830381865afa15801561113f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116391906156d1565b90508034101561117d5761117d63207226af60e01b613259565b60408401516001600160a01b031663c4804ce261119a8334615916565b8b8b8b8b898b8d6040518963ffffffff1660e01b81526004016111c39796959493929190615867565b6000604051808303818588803b1580156111dc57600080fd5b505af11580156111f0573d6000803e3d6000fd5b5050505050505b8063ffffffff16600114156112835782516001600160a01b0316630d640e81888888600081611228576112286156ea565b905060200201356040518363ffffffff1660e01b815260040161124c929190615700565b600060405180830381600087803b15801561126657600080fd5b505af115801561127a573d6000803e3d6000fd5b505050506112e9565b8251604051636371fbe760e01b81526001600160a01b0390911690636371fbe7906112b6908a908a908a9060040161574f565b600060405180830381600087803b1580156112d057600080fd5b505af11580156112e4573d6000803e3d6000fd5b505050505b6001151583600001516001600160a01b031689600080516020615ec1833981519152898960405161131b92919061577d565b60405180910390a45050505050505050565b600033600085815260a76020908152604080832081516101c08101835281546001600160a01b03808216835265ffffffffffff600160a01b808404821697850197909752600160d01b928390048116958401959095526001840154808216606085015286810486166080850152829004851660a08401819052600285015491821660c0850152958104851660e084015204831661010082015260038201546001600160c01b038116610120830152600160c01b810490931661014082015260ff600160f01b840481161515610160830152600160f81b9093049092161515610180830152600401546101a082015292935061142990869061592d565b6000878152609f602090815260408083206001600160a01b0389168452909152812054919250906114649087906001600160401b031661592d565b9050826101800151801561148157506001600160a01b0384163214155b1561149657611496630977d34b60e01b613259565b600087815260a760209081526040808320600101805465ffffffffffff808816600160d01b026001600160d01b0390921691909117909155609f83528184206001600160a01b038a16855290925290912080546001600160401b0319169183169190911790556101608301511561151b57611516878488888887876132df565b61152a565b61152a87848888888787613414565b50505050505050565b600085815260a760205260408120546001600160a01b031690339050806001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611597573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bb919061569d565b6001600160a01b031614806115e15750816001600160a01b0316816001600160a01b0316145b156119d45760006115f56020870187615957565b61ffff1611156116455761160f604087016020880161597b565b600088815260a760205260409020805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b60006116576040870160208801615957565b61ffff1611156116a457611671606087016040880161597b565b600088815260a760205260409020805465ffffffffffff92909216600160d01b026001600160d01b039092169190911790555b60006116b66060870160408801615957565b61ffff161115611700576116d0608087016060880161504c565b600088815260a76020526040902060010180546001600160a01b0319166001600160a01b03929092169190911790555b60006117126080870160608801615957565b61ffff1611156117655761172c60a087016080880161597b565b600088815260a760205260409020600101805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b600061177760a0870160808801615957565b61ffff1611156117cb57611792610100870160e0880161597b565b600088815260a760205260409020600201805465ffffffffffff92909216600160a01b0265ffffffffffff60a01b199092169190911790555b60006117dd60c0870160a08801615957565b61ffff16111561182f576117f96101208701610100880161597b565b600088815260a760205260409020600201805465ffffffffffff92909216600160d01b026001600160d01b039092169190911790555b600061184160e0870160c08801615998565b60ff16111561188c5761185c610140870161012088016159d0565b600088815260a76020526040902060030180546001600160c01b0319166001600160c01b03929092169190911790555b600061189f610100870160e08801615998565b60ff1611156118e8576118b860e0870160c0880161504c565b600088815260a76020526040902060020180546001600160a01b0319166001600160a01b03929092169190911790555b60006118fc61012087016101008801615998565b60ff161115611945576119176101a0870161018088016159ed565b600088815260a7602052604090206003018054911515600160f81b026001600160f81b039092169190911790555b600061195961014087016101208801615998565b60ff1611156119a45761196c84846134d7565b600088815260a860205260408082209290925590516001600160801b03851691861515918a91600080516020615f6883398151915291a45b60405187907fe772ce44f6b7edf20d62f174efc62c5a18484d62a710bd48d57af1afd140811c90600090a261152a565b61152a6282b42960e81b613259565b306001600160a01b037f0000000000000000000000009acdfe8020c3c191f7aa158e1c155f12e55c9717161415611a355760405162461bcd60e51b8152600401611a2c90615a0a565b60405180910390fd5b7f0000000000000000000000009acdfe8020c3c191f7aa158e1c155f12e55c97176001600160a01b0316611a676134fc565b6001600160a01b031614611a8d5760405162461bcd60e51b8152600401611a2c90615a44565b611a9681613518565b60408051600080825260208201909252611ab291839190613520565b50565b600082815260a060205260408120611acd908361368b565b90505b92915050565b600083815260a760205260408120546001600160a01b031690339050806001600160a01b0316826001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5e919061569d565b6001600160a01b03161480611b845750816001600160a01b0316816001600160a01b0316145b15611bcf57611b9384846134d7565b600086815260a860205260408082209290925590516001600160801b03851691861515918891600080516020615f6883398151915291a4611bde565b611bde6282b42960e81b613259565b5050505050565b306001600160a01b037f0000000000000000000000009acdfe8020c3c191f7aa158e1c155f12e55c9717161415611c2e5760405162461bcd60e51b8152600401611a2c90615a0a565b7f0000000000000000000000009acdfe8020c3c191f7aa158e1c155f12e55c97176001600160a01b0316611c606134fc565b6001600160a01b031614611c865760405162461bcd60e51b8152600401611a2c90615a44565b611c8f82613518565b611c9b82826001613520565b5050565b600082815260a9602052604090205433906001600160a01b031680611cce57611cce633bed786f60e21b613259565b816001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d3a919061569d565b6001600160a01b03161480611d605750806001600160a01b0316826001600160a01b0316145b15611d9057600084815260a960205260409020600101805460ff60b01b1916600160b01b85151502179055611d9f565b611d9f6282b42960e81b613259565b6040518315159085907fa5a0d9b368dd777972caaaa919c8ca3243792928d90f1b032a1bab6b243a73ab90600090a350505050565b6000306001600160a01b037f0000000000000000000000009acdfe8020c3c191f7aa158e1c155f12e55c97171614611e6f5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401611a2c565b50600080516020615f0183398151915290565b611e8a613697565b6001600160a01b038316611ea757611ea76282b42960e81b613259565b609c546001600160a01b03848116911614611ed857609c80546001600160a01b0319166001600160a01b0385161790555b60aa546001600160a01b03838116911614611f095760aa80546001600160a01b0319166001600160a01b0384161790555b60ab546001600160a01b03828116911614611f3a5760ab80546001600160a01b0319166001600160a01b0383161790555b505050565b338181611f5260608a0160408b0161504c565b6001600160a01b031614158015611f8a5750611f746060890160408a0161504c565b6001600160a01b0316856001600160a01b031614155b15611f9f57611f9f6343d0477760e01b613259565b611fab888888846136f6565b611ff36101408901358284611fc360208d018d61504c565b8c608001358d6060016020810190611fdb919061504c565b8e6020016020810190611fee919061504c565b61393c565b600061200560408a0160208b0161504c565b6001600160a01b0316896101400135600080516020615ec1833981519152878760405161203392919061577d565b60405180910390a480600114156120d1576120546040890160208a0161504c565b6001600160a01b0316630d640e818686866000818110612076576120766156ea565b905060200201356040518363ffffffff1660e01b815260040161209a929190615700565b600060405180830381600087803b1580156120b457600080fd5b505af11580156120c8573d6000803e3d6000fd5b50505050612143565b6120e16040890160208a0161504c565b6001600160a01b0316636371fbe78686866040518463ffffffff1660e01b81526004016121109392919061574f565b600060405180830381600087803b15801561212a57600080fd5b505af115801561213e573d6000803e3d6000fd5b505050505b5050505050505050565b612155613697565b61215f6000613a1d565b565b3380612170602084018461504c565b6001600160a01b0316148061220357506001600160a01b038116612197602084018461504c565b6001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f8919061569d565b6001600160a01b0316145b1561233057600061221a60c0840160a0850161597b565b65ffffffffffff1611156122385761223863875fc25f60e01b613259565b60a3805490600061224883615a7e565b909155505060a354600090815260a760205260409020829061226a8282615acd565b5061227f9050610180830161016084016159ed565b156122e757612291602083018361504c565b6001600160a01b03166122ac6101608401610140850161597b565b65ffffffffffff1660a3547fa712e8b25b3d4d043988e80f0a4087773b1c7e29e4115a4256e86aebe91c9be960405160405180910390a45050565b6122f4602083018361504c565b6001600160a01b031660a3547f7258df9bfe0a9fb9cf1285396575e6472f56ca38b4851afcb725c82726fd67ff60405160405180910390a35050565b611c9b6282b42960e81b613259565b3380612351606088016040890161504c565b6001600160a01b0316141580156123895750612373606087016040880161504c565b6001600160a01b0316836001600160a01b031614155b1561239e5761239e6343d0477760e01b613259565b6123a9868686613a6f565b6123fd6101608701356123c260c0890160a08a01615ca0565b6001600160401b0316836123d960208b018b61504c565b60808b018035906123ed9060608e0161504c565b611fee60408e0160208f0161504c565b600061240f604088016020890161504c565b6001600160a01b0316610160880135600080516020615f4883398151915261243d60c08b0160a08c01615ca0565b60405161244a9190615457565b60405180910390a4811561257b5761246860c0870160a08801615ca0565b6001600160401b03166001141561250457612489604087016020880161504c565b6001600160a01b031663b859c935876101000135856040518363ffffffff1660e01b81526004016124bb9291906156ba565b6020604051808303816000875af11580156124da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124fe91906156d1565b50612669565b612514604087016020880161504c565b6001600160a01b0316631b30808d6101008801358561253960c08b0160a08c01615ca0565b6040516001600160e01b031960e086901b16815260048101939093526001600160a01b0390911660248301526001600160401b031660448201526064016124bb565b61258b60c0870160a08801615ca0565b6001600160401b0316600114156125d7576125ac604087016020880161504c565b6001600160a01b031663184a94d5846040518263ffffffff1660e01b81526004016124bb9190615443565b6125e7604087016020880161504c565b6001600160a01b0316635be954488461260660c08a0160a08b01615ca0565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160401b03166024820152604401600060405180830381600087803b15801561265557600080fd5b505af1158015610f4a573d6000803e3d6000fd5b505050505050565b609c546001600160a01b0316336001600160a01b03161461269b5761269b6282b42960e81b613259565b609c5460405160009182916001600160a01b039091169084908381818185875af1925050503d80600081146126ec576040519150601f19603f3d011682016040523d82523d6000602084013e6126f1565b606091505b509150915081611f3a57611f3a637cd69c3960e11b613259565b6038546001600160a01b031690565b612722613697565b6001600160a01b038116612740576127406340f3a16b60e01b613259565b61274b60a482613c39565b1561275b57611c9b60a482613c4e565b611c9b60a482613c63565b83516020808601516040808801516060808a015183516001600160601b031997831b8816818801526001600160a01b031960a096871b811660348301529390921b9096168184015294151560f81b60548601529187901b90911660558401528051808403604101815260619093019052815191012084513391906001600160a01b031682148061286c5750816001600160a01b031686600001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561283d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612861919061569d565b6001600160a01b0316145b1561299a57600081815260a960205260409020546001600160a01b03161561289e5761289e63250675bd60e21b613259565b85516001600160a01b031615806128c0575060408601516001600160a01b0316155b806128d85750856060015180156128d8575085608001515b806128e1575080155b156128f6576128f6633bed786f60e21b613259565b600060a0870181815282825260a960209081526040928390208951918a01516001600160a01b03928316600160a01b6001600160601b039092168202178255938a01516001909101805460608c015160808d01519551939094166001600160a81b0319909116179215159094029190911761ffff60a81b1916600160a81b9215159290920260ff60b01b191691909117600160b01b911515919091021790556129a9565b6129a96282b42960e81b613259565b85604001516001600160a01b0316631a8d37928286866040518463ffffffff1660e01b81526004016129dd93929190615cc9565b600060405180830381600087803b1580156129f757600080fd5b505af1158015612a0b573d6000803e3d6000fd5b5050505085600001516001600160a01b031686604001516001600160a01b0316827f6ec667d7188a57a345b217226db199b2b1e98d2ccdb2eaa555af7ad19324303789602001518a60600151604051612a7b9291906001600160601b039290921682521515602082015260400190565b60405180910390a4505050505050565b6000611ad060a483613c39565b612aa0613697565b6001600160a01b038116612b055760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401611a2c565b611ab281613a1d565b600080612b1c868686613c78565b9050612b2960a482613c39565b8015612b555750610160860135600090815260a060205260409020612b539061014088013561368b565b155b8015612b6657508561012001354211155b8015612bb9575060c08601351580612bb95750610160860135600090815260a1602052604090205460c0870180359190612ba39060a08a01615ca0565b6001600160401b0316612bb69190615cff565b11155b8015612c3d575060e08601351580612c3d5750610160860135600090815260a1602052604080822060e089013592600190910191612bfd9060608b01908b0161504c565b6001600160a01b03168152602081019190915260400160002054612c2760c0890160a08a01615ca0565b6001600160401b0316612c3a9190615cff565b11155b9150505b949350505050565b600054610100900460ff1615808015612c695750600054600160ff909116105b80612c8a5750612c7830613d02565b158015612c8a575060005460ff166001145b612ced5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401611a2c565b6000805460ff191660011790558015612d10576000805461ff0019166101001790555b609c80546001600160a01b0319166001600160a01b038816179055604080518082018252600b81526a26b4b73a26b0b730b3b2b960a91b602080830191909152825180840190935260058352640312e302e360dc1b90830152612d7291613d11565b612d7b84613d92565b612d83613ddb565b612d8c85613a1d565b612d9760a484613c63565b5060a68290558015612669576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050505050565b600084815260a96020908152604091829020825160c08101845281546001600160a01b0380821683526001600160601b03600160a01b9283900416948301949094526001909201549283169381019390935260ff908204811615156060840152600160a81b8204811615156080840152600160b01b9091041615801560a08301523390612e8157612e816337e9321960e21b613259565b816080015115612e9b57612e9b633bed786f60e21b613259565b60ab5460408301516001600160a01b0390811691161415612f7557612ebf81613263565b612ed357612ed363ac3274ef60e01b613259565b81604001516001600160a01b0316639cc163e58787878587612ef36132c5565b612efb6132d3565b8b604051602001612f0e939291906157e9565b6040516020818303038152906040526040518763ffffffff1660e01b8152600401612f3e96959493929190615d17565b600060405180830381600087803b158015612f5857600080fd5b505af1158015612f6c573d6000803e3d6000fd5b50505050613086565b60aa5460408084015184519151634b48652b60e11b81526000936001600160a01b031692639690ca5692612fb3928c928b92918991906004016158cc565b602060405180830381865afa158015612fd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ff491906156d1565b90508034101561300e5761300e63207226af60e01b613259565b60408301516001600160a01b0316639cc163e561302b8334615916565b89898987898b6040518863ffffffff1660e01b815260040161305296959493929190615d17565b6000604051808303818588803b15801561306b57600080fd5b505af115801561307f573d6000803e3d6000fd5b5050505050505b81606001511561317c578363ffffffff166001141561312a578151602083015160405163b859c93560e01b81526001600160601b0390911660048201526001600160a01b0387811660248301529091169063b859c935906044015b6020604051808303816000875af1158015613100573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061312491906156d1565b50613224565b81516020830151604051631b30808d60e01b81526001600160601b0390911660048201526001600160a01b03878116602483015263ffffffff8716604483015290911690631b30808d906064016130e1565b8363ffffffff16600114156131ba57815160405163184a94d560e01b81526001600160a01b039091169063184a94d5906130e1908890600401615443565b8151604051630b7d2a8960e31b81526001600160a01b0390911690635be95448906131f190889063ffffffff891690600401615700565b600060405180830381600087803b15801561320b57600080fd5b505af115801561321f573d6000803e3d6000fd5b505050505b815160405163ffffffff861681526001916001600160a01b0316908890600080516020615f4883398151915290602001612a7b565b8060005260046000fd5b6000466101441480613276575046610118145b61329f576001600160a01b03821673abcc9b596420a9e9172fd5938620e265a0f9df9214611ad0565b6001600160a01b03821673b16a1dbe755f992636705fdbb3a8678a657eb3ea1492915050565b601f1936013590565b905090565b60471936013560601c90565b6132ed878787858588613e0a565b8465ffffffffffff166001141561338957855161014087015160405163b859c93560e01b815265ffffffffffff90911660048201526001600160a01b0386811660248301529091169063b859c935906044015b6020604051808303816000875af115801561335f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061338391906156d1565b5061152a565b8551610140870151604051631b30808d60e01b815265ffffffffffff91821660048201526001600160a01b0387811660248301529188166044820152911690631b30808d906064016020604051808303816000875af11580156133f0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061214391906156d1565b613422878787858588613e0a565b8465ffffffffffff166001141561346257855160405163184a94d560e01b81526001600160a01b039091169063184a94d590613340908790600401615443565b8551604051630b7d2a8960e31b81526001600160a01b03868116600483015265ffffffffffff8816602483015290911690635be9544890604401600060405180830381600087803b1580156134b657600080fd5b505af11580156134ca573d6000803e3d6000fd5b5050505050505050505050565b60008083156134e4576001175b6001600160801b0319608084901b1617905092915050565b600080516020615f01833981519152546001600160a01b031690565b611ab2613697565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561355357611f3a83613fb2565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156135ad575060408051601f3d908101601f191682019092526135aa918101906156d1565b60015b6136105760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401611a2c565b600080516020615f01833981519152811461367f5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401611a2c565b50611f3a83838361404c565b6000611acd8383614077565b336136a061270b565b6001600160a01b03161461215f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611a2c565b600061370385858561408f565b610140860135600090815260a1602052604081205491925090613727908490615cff565b905060008360a160008961014001358152602001908152602001600020600101600089604001602081019061375c919061504c565b6001600160a01b03166001600160a01b03168152602001908152602001600020546137879190615cff565b905061379460a484613c39565b15806137d957506137ab60c0880160a08901615ca0565b6001600160401b0316841180156137d957506137cd60c0880160a08901615ca0565b6001600160401b031615155b806138025750610140870135600090815260a0602052604090206138029061012089013561368b565b80613826575061381a61012088016101008901615ca0565b6001600160401b031642115b8061386a575061383c60e0880160c08901615ca0565b6001600160401b03168211801561386a575061385e60e0880160c08901615ca0565b6001600160401b031615155b806138b05750613881610100880160e08901615ca0565b6001600160401b0316811180156138b057506138a4610100880160e08901615ca0565b6001600160401b031615155b156138c5576138c5633b4f091f60e21b613259565b610140870135600090815260a0602052604090206138e8906101208901356140e5565b50610140870135600090815260a1602052604080822084815583926001909101916139199060608c01908c0161504c565b6001600160a01b0316815260208101919091526040016000205550505050505050565b60aa546040516376c1989360e01b815260048101899052602481018890526001600160a01b0387811660448301528681166064830152838116608483015260009283929116906376c198939060a4016040805180830381865afa1580156139a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139cb9190615d6f565b909250905060006001600160a01b038716156139e85760006139ea565b825b905060006139f8878b615d94565b9050613a078b82848b8a6140f1565b5050506134ca848a8a898f878d6000148a614157565b603880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000613a7c848484613c78565b90506000613a9060c0860160a08701615ca0565b610160860135600090815260a16020526040902054613ab8916001600160401b031690615cff565b90506000613acc60c0870160a08801615ca0565b6001600160401b031660a1600088610160013581526020019081526020016000206001016000886040016020810190613b05919061504c565b6001600160a01b03166001600160a01b0316815260200190815260200160002054613b309190615cff565b9050613b3d60a484613c39565b1580613b675750610160860135600090815260a060205260409020613b679061014088013561368b565b80613b76575085610120013542115b80613b9257508560c0013582118015613b92575060c086013515155b80613bae57508560e0013581118015613bae575060e086013515155b15613bc357613bc3633b4f091f60e21b613259565b610160860135600090815260a060205260409020613be6906101408801356140e5565b50610160860135600090815260a160205260408082208481558392600190910191613c179060608b01908b0161504c565b6001600160a01b03168152602081019190915260400160002055505050505050565b6000611acd836001600160a01b038416614077565b6000611acd836001600160a01b0384166142e8565b6000611acd836001600160a01b0384166143db565b6000612c4183838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613cfc9250613cc29150889050614425565b613cd0886101600135614540565b604051602001613ce1929190615db3565b60405160208183030381529060405280519060200120614555565b9061459c565b6001600160a01b03163b151590565b600054610100900460ff16613d385760405162461bcd60e51b8152600401611a2c90615dd9565b815160208084019190912082519183019190912060038290556004819055466002557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f613d868184846145c0565b60015560055550505050565b600054610100900460ff16613db95760405162461bcd60e51b8152600401611a2c90615dd9565b606a80546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff16613e025760405162461bcd60e51b8152600401611a2c90615dd9565b61215f614609565b8265ffffffffffff16856080015165ffffffffffff16108015613e385750608085015165ffffffffffff1615155b80613e6e57508165ffffffffffff1685610100015165ffffffffffff16108015613e6e575061010085015165ffffffffffff1615155b80613ec6575042856020015165ffffffffffff16118015613e9a5750602085015165ffffffffffff1615155b80613ec65750846040015165ffffffffffff1642118015613ec65750604085015165ffffffffffff1615155b80613ed7575065ffffffffffff8416155b80613f0b57508460e0015165ffffffffffff168465ffffffffffff16118015613f0b575060e085015165ffffffffffff1615155b15613f2057613f2063072b86df60e21b613259565b600086815260a8602052604090205460011615613f4757613f47636be9245d60e11b613259565b613f7b8660001b8565ffffffffffff16838860c001518961012001516001600160c01b03168a606001518b6000015161393c565b845160405165ffffffffffff861681526001916001600160a01b0316908890600080516020615f4883398151915290602001612a7b565b613fbb81613d02565b61401d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401611a2c565b600080516020615f0183398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61405583614639565b6000825111806140625750805b15611f3a576140718383614679565b50505050565b60009081526001919091016020526040902054151590565b6000612c4183838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613cfc92506140d9915088905061469e565b80519060200120614555565b6000611acd83836143db565b600080806001600160a01b038516614139573461410e8888615cff565b1461412357614123637e2897ef60e11b613259565b86156141345761413487858a6147cb565b61414c565b861561414c5761414c878532888c614883565b955095509592505050565b8715612143576001600160a01b038616156141e55760aa546040516323b872dd60e01b81526001600160a01b03808916926323b872dd926141a092329216908d90600401615e24565b6020604051808303816000875af11580156141bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141e39190615e48565b505b60aa54604051636f18e93f60e01b81526004810186905283151560248201526001600160a01b0387811660448301528881166064830152608482018b905289811660a483015283151560c48301526000921690636f18e93f90869060e40160206040518083038185885af1158015614261573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061428691906156d1565b905080156142dd57856001600160a01b0316876001600160a01b0316867f27dcd1d67ca97c55aa198d8494458949bbbddae9336ef0969fc655edb5d2180a846040516142d491815260200190565b60405180910390a45b505050505050505050565b600081815260018301602052604081205480156143d157600061430c600183615916565b855490915060009061432090600190615916565b9050818114614385576000866000018281548110614340576143406156ea565b9060005260206000200154905080876000018481548110614363576143636156ea565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061439657614396615e65565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050611ad0565b6000915050611ad0565b60006143e78383614077565b61441d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155611ad0565b506000611ad0565b60607f75d70c323d802883252e6285d4bb7cc6fcb7faca7fe3ab1d9e9f260aaa4c3424614455602084018461504c565b614465604085016020860161504c565b614475606086016040870161504c565b614485608087016060880161504c565b608087013561449a60c0890160a08a01615ca0565b6040805160208101989098526001600160a01b03968716908801529385166060870152918416608086015290921660a084015260c0808401929092526001600160401b031660e080840191909152908401356101008084019190915290840135610120808401919091529084013561014080840191909152908401356101608301528301356101808201526101a0015b6040516020818303038152906040529050919050565b60608160405160200161452a91815260200190565b600061455f614953565b60405161190160f01b6020820152602281019190915260428101839052606201604051602081830303815290604052805190602001209050919050565b60008060006145ab8585614977565b915091506145b8816149bd565b509392505050565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b600054610100900460ff166146305760405162461bcd60e51b8152600401611a2c90615dd9565b61215f33613a1d565b61464281613fb2565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060611acd8383604051806060016040528060278152602001615f2160279139614b06565b60607faf2a8dc7de0e027b17ddbe873c600be814993ef395f58475bc9ef0408f7ccf166146ce602084018461504c565b6146de604085016020860161504c565b6146ee606086016040870161504c565b6146fe608087016060880161504c565b608087013561471360c0890160a08a01615ca0565b61472360e08a0160c08b01615ca0565b6147346101008b0160e08c01615ca0565b6147466101208c016101008d01615ca0565b60408051602081019b909b526001600160a01b03998a16908b015296881660608a015294871660808901529290951660a087015260c08601526001600160401b0393841660e08601528316610100850152821661012080850191909152911661014080840191909152908401356101608301528301356101808201526101a00161452a565b6000826001600160a01b03168460405160006040518083038185875af1925050503d8060008114614818576040519150601f19603f3d011682016040523d82523d6000602084013e61481d565b606091505b505090508061483657614836637cd69c3960e11b613259565b60408051858152612710602082015283916001600160a01b038616917f9363885e28e7ba67b096932f9f00dff44742731d6cb4fa26ccd4424e78e41e13910160405180910390a350505050565b6040516323b872dd60e01b81526001600160a01b038316906323b872dd906148b390869088908a90600401615e24565b6020604051808303816000875af11580156148d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148f69190615e48565b50604080516001600160a01b03858116825260208201889052612710828401529151839287811692908616917fc899cbcc4511003ff90131e8b89605738e9a7f4925273377ae479a673cf5038c9181900360600190a45050505050565b6000600254461415614966575060015490565b6132ce6005546003546004546145c0565b6000808251604114156149ae5760208301516040840151606085015160001a6149a287828585614b7e565b945094505050506149b6565b506000905060025b9250929050565b60008160048111156149d1576149d1615e7b565b14156149da5750565b60018160048111156149ee576149ee615e7b565b1415614a375760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401611a2c565b6002816004811115614a4b57614a4b615e7b565b1415614a995760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401611a2c565b6003816004811115614aad57614aad615e7b565b1415611ab25760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401611a2c565b6060600080856001600160a01b031685604051614b239190615e91565b600060405180830381855af49150503d8060008114614b5e576040519150601f19603f3d011682016040523d82523d6000602084013e614b63565b606091505b5091509150614b7486838387614c38565b9695505050505050565b6000806fa2a8918ca85bafe22016d0b997e4df60600160ff1b03831115614bab5750600090506003614c2f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614bff573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116614c2857600060019250925050614c2f565b9150600090505b94509492505050565b60608315614ca2578251614c9b57614c4f85613d02565b614c9b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611a2c565b5081612c41565b612c418383815115614cb75781518083602001fd5b8060405162461bcd60e51b8152600401611a2c9190615ead565b600060208284031215614ce357600080fd5b5035919050565b6001600160a01b03169052565b6001600160a01b0381168114611ab257600080fd5b8015158114611ab257600080fd5b60008083601f840112614d2c57600080fd5b5081356001600160401b03811115614d4357600080fd5b6020830191508360208260051b85010111156149b657600080fd5b60008060008060008060008060e0898b031215614d7a57600080fd5b8835614d8581614cf7565b97506020890135614d9581614d0c565b9650604089013595506060890135945060808901356001600160401b03811115614dbe57600080fd5b614dca8b828c01614d1a565b90955093505060a0890135614dde81614d0c565b915060c0890135614dee81614cf7565b809150509295985092959890939650565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715614e3757614e37614dff565b60405290565b600082601f830112614e4e57600080fd5b81356001600160401b0380821115614e6857614e68614dff565b604051601f8301601f19908116603f01168101908282118183101715614e9057614e90614dff565b81604052838152866020858801011115614ea957600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060808688031215614ee157600080fd5b853594506020860135614ef381614cf7565b935060408601356001600160401b0380821115614f0f57600080fd5b614f1b89838a01614d1a565b90955093506060880135915080821115614f3457600080fd5b50614f4188828901614e3d565b9150509295509295909350565b65ffffffffffff81168114611ab257600080fd5b600080600060608486031215614f7757600080fd5b833592506020840135614f8981614f4e565b91506040840135614f9981614cf7565b809150509250925092565b60006101c08284031215614fb757600080fd5b50919050565b80356001600160801b0381168114614fd457600080fd5b919050565b6000806000806000858703610360811215614ff357600080fd5b863595506150048860208901614fa4565b94506101406101df198201121561501a57600080fd5b506101e08601925061032086013561503181614d0c565b91506150406103408701614fbd565b90509295509295909350565b60006020828403121561505e57600080fd5b813561506981614cf7565b9392505050565b6000806040838503121561508357600080fd5b50508035926020909101359150565b6000806000606084860312156150a757600080fd5b8335925060208401356150b981614d0c565b91506150c760408501614fbd565b90509250925092565b600080604083850312156150e357600080fd5b82356150ee81614cf7565b915060208301356001600160401b0381111561510957600080fd5b61511585828601614e3d565b9150509250929050565b6000806040838503121561513257600080fd5b82359150602083013561514481614d0c565b809150509250929050565b6000806040838503121561516257600080fd5b82359150602083013561514481614cf7565b60008060006060848603121561518957600080fd5b833561519481614cf7565b92506020840135614f8981614cf7565b60008083601f8401126151b657600080fd5b5081356001600160401b038111156151cd57600080fd5b6020830191508360208285010111156149b657600080fd5b6000806000806000808688036101c081121561520057600080fd5b6101608082121561521057600080fd5b88975087013590506001600160401b038082111561522d57600080fd5b6152398a838b016151a4565b9097509550610180890135915061524f82614cf7565b9093506101a0880135908082111561526657600080fd5b5061527389828a01614d1a565b979a9699509497509295939492505050565b60006101c0828403121561529857600080fd5b611acd8383614fa4565b60006101808284031215614fb757600080fd5b60008060008060006101e086880312156152ce57600080fd5b6152d887876152a2565b94506101808601356001600160401b038111156152f457600080fd5b615300888289016151a4565b9095509350506101a086013561531581614cf7565b91506101c086013561532681614d0c565b809150509295509295909350565b65ffffffffffff169052565b60006101c082019050615354828451614cea565b60208301516153666020840182615334565b5060408301516153796040840182615334565b50606083015161538c6060840182614cea565b50608083015161539f6080840182615334565b5060a08301516153b260a0840182615334565b5060c08301516153c560c0840182614cea565b5060e08301516153d860e0840182615334565b50610100808401516153ec82850182615334565b5050610120838101516001600160c01b0316908301526101408084015161541582850182615334565b505061016083810151151590830152610180808401511515908301526101a092830151929091019190915290565b6001600160a01b0391909116815260200190565b6001600160401b0391909116815260200190565b80356001600160601b0381168114614fd457600080fd5b60008060008084860361010081121561549a57600080fd5b60c08112156154a857600080fd5b506154b1614e15565b85356154bc81614cf7565b81526154ca6020870161546b565b602082015260408601356154dd81614cf7565b604082015260608601356154f081614d0c565b6060820152608086013561550381614d0c565b608082015260a086013561551681614d0c565b60a0820152935061552960c0860161546b565b925060e08501356001600160401b0381111561554457600080fd5b615550878288016151a4565b95989497509550505050565b6000806000806101c0858703121561557357600080fd5b61557d86866152a2565b93506101808501356001600160401b0381111561559957600080fd5b6155a5878288016151a4565b9094509250506101a08501356155ba81614cf7565b939692955090935050565b600080600080600060a086880312156155dd57600080fd5b85356155e881614cf7565b945060208601356155f881614cf7565b9350604086013561560881614cf7565b9250606086013561561881614cf7565b949793965091946080013592915050565b6000806000806080858703121561563f57600080fd5b84359350602085013561565181614cf7565b9250604085013563ffffffff8116811461566a57600080fd5b915060608501356001600160401b0381111561568557600080fd5b61569187828801614e3d565b91505092959194509250565b6000602082840312156156af57600080fd5b815161506981614cf7565b9182526001600160a01b0316602082015260400190565b6000602082840312156156e357600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6001600160a01b03929092168252602082015260400190565b81835260006001600160fb1b0383111561573257600080fd5b8260051b8083602087013760009401602001938452509192915050565b6001600160a01b03841681526040602082018190526000906157749083018486615719565b95945050505050565b602081526000612c41602083018486615719565b60005b838110156157ac578181015183820152602001615794565b838111156140715750506000910152565b600081518084526157d5816020860160208601615791565b601f01601f19169290920160200192915050565b8381526001600160a01b0383166020820152606060408201819052600090615774908301846157bd565b80516001600160a01b0390811683526020808301516001600160601b0316908401526040808301519091169083015260608082015115159083015260808082015115159083015260a0908101511515910152565b8781526001600160a01b03878116602083015261016060408301819052600091615894848301898b615719565b908716606085015290506158ab6080840186615813565b8281036101408401526158be81856157bd565b9a9950505050505050505050565b94855263ffffffff9390931660208501526001600160a01b0391821660408501528116606084015216608082015260a00190565b634e487b7160e01b600052601160045260246000fd5b60008282101561592857615928615900565b500390565b600065ffffffffffff80831681851680830382111561594e5761594e615900565b01949350505050565b60006020828403121561596957600080fd5b813561ffff8116811461506957600080fd5b60006020828403121561598d57600080fd5b813561506981614f4e565b6000602082840312156159aa57600080fd5b813560ff8116811461506957600080fd5b6001600160c01b0381168114611ab257600080fd5b6000602082840312156159e257600080fd5b8135615069816159bb565b6000602082840312156159ff57600080fd5b813561506981614d0c565b6020808252602c90820152600080516020615ee183398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c90820152600080516020615ee183398151915260408201526b6163746976652070726f787960a01b606082015260800190565b6000600019821415615a9257615a92615900565b5060010190565b60008135611ad081614cf7565b60008135611ad081614f4e565b60008135611ad0816159bb565b60008135611ad081614d0c565b615af6615ad983615a99565b82546001600160a01b0319166001600160a01b0391909116178255565b615b2d615b0560208401615aa6565b82805465ffffffffffff60a01b191660a09290921b65ffffffffffff60a01b16919091179055565b615b60615b3c60408401615aa6565b8280546001600160d01b031660d09290921b6001600160d01b031916919091179055565b60018101615b73615ad960608501615a99565b615b82615b0560808501615aa6565b615b91615b3c60a08501615aa6565b5060028101615ba5615ad960c08501615a99565b615bb4615b0560e08501615aa6565b615bc4615b3c6101008501615aa6565b5060038101615bf6615bd96101208501615ab3565b82546001600160c01b0319166001600160c01b0391909116178255565b615c2e615c066101408501615aa6565b82805465ffffffffffff60c01b191660c09290921b65ffffffffffff60c01b16919091179055565b615c5c615c3e6101608501615ac0565b82805460ff60f01b191691151560f01b60ff60f01b16919091179055565b615c90615c6c6101808501615ac0565b8280546001600160f81b031691151560f81b6001600160f81b031916919091179055565b506101a082013560048201555050565b600060208284031215615cb257600080fd5b81356001600160401b038116811461506957600080fd5b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b60008219821115615d1257615d12615900565b500190565b8681526001600160a01b03868116602083015263ffffffff86166040830152841660608201526000610160615d4f6080840186615813565b80610140840152615d62818401856157bd565b9998505050505050505050565b60008060408385031215615d8257600080fd5b82519150602083015161514481614d0c565b6000816000190483118215151615615dae57615dae615900565b500290565b60008351615dc5818460208801615791565b83519083019061594e818360208801615791565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600060208284031215615e5a57600080fd5b815161506981614d0c565b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60008251615ea3818460208701615791565b9190910192915050565b602081526000611acd60208301846157bd56fee0bf8a4af82e2af496af5f4957e2767f8b52e51a77caedd2f30a1843872d1b7c46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564981414aed4973b05aa301314dc13a5a4077f24490497b98bc270852581c1c578aaca5cb46300e4b20595b143bc883119e775ef88ff77f45fa989ca323576f06ba164736f6c634300080a000a
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.