Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
415374 | 40 hrs ago | Contract Creation | 0 ETH |
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
ZkSolc Version
v1.5.6
Optimization Enabled:
Yes with Mode z
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) { // referrals not allowed for erc20 payments on zksync protocol _processERC20Payment(saleAmount, salePaymentRecipient, msg.sender, 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 // referrals not allowed for erc20 payments on zksync protocol IERC20(currency).transferFrom(msg.sender, _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 // 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); } }
// 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: 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: 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: 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: 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: 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 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: 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: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../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 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 // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/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: 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) (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 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: 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: 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) (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.4) (utils/Context.sol) pragma solidity ^0.8.0; import {Initializable} from "../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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } /** * @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.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 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; 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.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) (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) (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 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 // 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/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.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (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) (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.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/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 } } }
{ "optimizer": { "enabled": true, "mode": "z" }, "outputSelection": { "*": { "*": [ "abi" ] } }, "detectMissingLibraries": false, "forceEVMLA": false, "enableEraVMExtensions": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"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
9c4d535b00000000000000000000000000000000000000000000000000000000000000000100075b8aa7bcbcc3200d8fbf173de1538cd63632bc9fc630c9c96f55bb91bc00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x00040000000000020025000000000002000000000f01034f0000006001100270000006a90410019700030000004f035500020000000f0355000006a90010019d00000001002001900000000003000416000000a0010000390000002002000039000000850000c13d000000800b0000390000004000b0043f000000040040008c00000dd50000413d00000000010f043b000000e00a100270000006ab00a0009c000000410d0000390000000401f003700000002405f003700000004402f003700000006403f00370000005fa0000613d000006ac00a0009c0000008406f00370000000a408f00370000000c407f00370000007360000613d000006ad00a0009c000000a10900003900000a060000613d000006ae00a0009c000009970000613d000006af00a0009c000000a70e000039000000910000613d000006b000a0009c000001c80000613d000006b100a0009c000002e10000613d000006b200a0009c000006ae0000613d000006b300a0009c000004e60000613d000006b400a0009c000001430000613d000006b500a0009c000001b20000613d000006b600a0009c000006a10000613d000006b700a0009c000006950000613d000006b800a0009c0000053b0000613d000006b900a0009c0000066c0000613d000006ba00a0009c000009630000613d000006bb00a0009c000001840cf00370000001a409f00370000007cd0000613d000006bc00a0009c000009480000613d000006bd00a0009c000004420000613d000006be00a0009c000003220000613d000006bf00a0009c000007bc0000613d000006c000a0009c000006c90000613d000006c100a0009c0000072f0000613d000006c200a0009c0000034d0000613d000006c300a0009c0000035c0000613d000006c400a0009c0000052c0000613d000006c500a0009c000006bf0000613d000006c600a0009c0000036d0000613d000006c700a0009c000003820000613d000006c800a0009c0000056b0000613d000006c900a0009c000006780000613d000006ca00a0009c000006260000613d000006cb00a0009c000005720000613d000006cc00a0009c000000000200041600000dd50000c13d000000240040008c00000dd50000413d000000000002004b00000dd50000c13d000000000101043b000000000010043f000000a9010000390001006d0000003d000018da0000013d0000000102100039000000000202041a000000000101041a000006cd03100197000000800030043f000000a001100270000000a00010043f000006cd01200197000000c00010043f0000072d002001980000000001000039000000010100c039000000e00010043f0000072e002001980000000001000039000000010100c039000001000010043f0000072f002001980000000001000039000000010100c039000001200010043f0000008001000039000000c00200003900000a150000013d000000400010043f000000000003004b00000dd50000c13d0000000001000410000000800010043f00000140000004430000016000100443000001000020044300000001010000390000012000100443000006aa0100004100001aa00001042e000000640040008c00000dd50000413d000100950000003d00001a800000013d000006f80010009c00000dd50000213d000000000102043b001000000001001d000006cd0010009c00000dd50000213d0000000001000415000e00000001001d0001009f0000003d000018d20000013d000000400200043d000f00000002001d000007230020009c000012360000213d0000000f05000029000001c002500039000000400020043f0000004002500039000000000301041a000000d0043002700000000000420435000000a002300270000006f80220019700000020045000390000000000240435000006cd0230019700000000002504350000000102100039000000000202041a0000006003500039000006cd042001970000000000430435000000a003200270000006f80330019700000080045000390000000000340435000000d006200270000000a00250003900000000006204350000000202100039000000000202041a0000010003500039000000d0042002700000000000430435000000c003500039000006cd042001970000000000430435000000a002200270000006f802200197000000e00350003900000000002304350000000302100039000000000202041a0000018003500039000006fb0020009c0000000004000039000000010400203900000000004304350000012003500039000006f9042001970000000000430435000006fa002001980000000003000039000000010300c0390000016004500039000d00000004001d0000000000340435000000c002200270000006f8022001970000014003500039000b00000003001d0000000000230435000001a0025000390000000401100039000000000101041a00000000001204350000001101000029000006f801100167000c00000006001d000000000016004b00000aad0000213d000a00000001001d0000001201000029000000000010043f0000009f01000039000100ec0000003d000018da0000013d000100ee0000003d00001a850000013d000000000101041a000006f801100197000900000001001d0000000a0010006c00000aad0000213d0000000c01000029000c00110010002d000100f70000003d000018d20000013d0000000c02000029000000d0022002100000000101100039000000000301041a0000070103300197000000000223019f000000000021041b0000001201000029000000000010043f0000009f01000039000000200010043f000000000100001900000040020000391a9f18910000040f000101070000003d00001a850000013d00000011030000290000000905300029000000000201041a0000072402200197000006f804500197000000000242019f000000000021041b00000000060004110000000d010000290000000001010433000000000001004b00000b750000c13d0000000001000415000d00000001001d00000012010000290000000f020000290000000c040000291a9f14ea0000040f0000000f010000290000000001010433001206cd0010019b0000001101000029000000010010008c00000bd60000c13d000000400200043d000006d8010000410000000000120435001100000002001d00000004012000390000001002000029000000000021043500000000010004140000001202000029000000040020008c000001320000613d000000240400003900000020060000390000001202000029000000110300002900000000050300191a9f123c0000040f000000000001004b00000a730000613d00000001010000310000001f02100039000000200300008a000000000332016f0000001102300029000101390000003d000019ec0000013d000006ce0020009c000012360000213d0000000100300190000012360000c13d000000400020043f000006d00010009c00000dd50000213d000000200010008c00000c010000813d00000dd50000013d000000440040008c00000dd50000413d000000000101043b001200000001001d000006cd0010009c00000dd50000213d000000000105043b000006ce0010009c00000dd50000213d0000002302100039000000000042004b00000dd50000813d000101510000003d000019c70000013d001000000001001d000101540000003d0000194d0000013d00000712020000411a9f18a50000040f001106cd0010019b0000000001000410000000110010006c0000000001000039000000010100c0391a9f131c0000040f0000071501000041000000000101041a000006cd01100197000000110010006c000000000100003900000001010060391a9f132b0000040f1a9f12ee0000040f0000071901000041000000000101041a000000ff0010019000000a650000c13d000000400500043d0000071a01000041000000000015043500000000010004140000001202000029000000040020008c000001780000613d000000040400003900000020060000390000000003050019001100000005001d00000011050000291a9f12600000040f0000001105000029000000000001004b000003190000613d00000001010000310000001f02100039000000200300008a000000000332016f00000000025300190001017f0000003d000019ec0000013d000006ce0020009c000012360000213d0000000100300190000012360000c13d000000400020043f000006d00010009c00000dd50000213d000000200010008c00000dd50000413d0000000001050433000007150010009c0001018c0000003d00001a620000013d000006a90010009c001100000001001d000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c70000800d0200003900000002030000390000071b040000410001019b0000003d00001a5e0000013d00000dd50000613d00000011010000290000071c0010009c000012360000213d00000011030000290000006001300039000000400010043f00000040013000390000071d02000041000000000021043500000020013000390000071e020000410000000000210435000000270100003900000000001304350000001001000029000000000401043300000000010004140000001202000029000000040020008c00000d1f0000c13d000000010100003900000d230000013d000000440040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000305043b000000000003004b0000000002000039000000010200c039001200000003001d000000000023004b00000dd50000c13d000000000101043b001100000001001d000000000010043f000000a901000039000101c40000003d000019090000013d000006cd0210019800000a240000c13d000007290100004100000d980000013d000003640040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000101043b001200000001001d0000032401f00370000000000201043b000000000002004b0000000001000039000000010100c039001100000002001d000000000012004b00000dd50000c13d0000034401f00370000000000101043b001000000001001d0000071f0010009c00000dd50000213d000101de0000003d000018d20000013d000000000201041a000006eb01000041000000800010043f0000000001000414000006cd02200197000000040020008c000001e80000613d000101e70000003d000019d80000013d00000a730000613d0000000004020019000101eb0000003d000019560000013d000006ea0020009c000012360000213d0000008002200039000f00000002001d000000400020043f000006d00010009c000000000200041100000dd50000213d000000200010008c00000dd50000413d000000800100043d000006cd0010009c00000dd50000213d000000000021004b000001fc0000613d000000000042004b00000d970000c13d0000000201000367000e000000010353000001e401100370000000000101043b0000ffff0010008c00000dd50000213d000000000001004b000002110000613d0000000e0100035f0000004401100370000000000101043b000d00000001001d000006f80010009c00000dd50000213d0001020c0000003d000019330000013d0000070002200197000000000301041a000006ff03300197000000000223019f000000000021041b0000000e0100035f0000020401100370000000000101043b0000ffff0010008c00000dd50000213d000000000001004b000002240000613d0000000e0100035f0000006401100370000000000101043b000d00000001001d000006f80010009c00000dd50000213d000102200000003d000019e20000013d000000000301041a0000070103300197000000000223019f000000000021041b0000000e0100035f0000022401100370000000000101043b0000ffff0010008c00000dd50000213d000000000001004b000002380000613d0000000e0100035f0000008401100370000000000101043b000d00000001001d000006cd0010009c00000dd50000213d000102330000003d000018d20000013d0000000101100039000000000201041a000006de022001970000000d022001af000000000021041b0000000e0100035f0000024401100370000000000101043b0000ffff0010008c00000dd50000213d000000000001004b0000024d0000613d0000000e0100035f000000a401100370000000000101043b000d00000001001d000006f80010009c00000dd50000213d000102470000003d000019330000013d00000700022001970000000101100039000000000301041a000006ff03300197000000000223019f000000000021041b0000000e0100035f0000026401100370000000000101043b0000ffff0010008c00000dd50000213d000000000001004b000002620000613d0000000e0100035f0000010401100370000000000101043b000d00000001001d000006f80010009c00000dd50000213d0001025c0000003d000019330000013d00000700022001970000000201100039000000000301041a000006ff03300197000000000223019f000000000021041b0000000e0100035f0000028401100370000000000101043b0000ffff0010008c00000dd50000213d000000000001004b000002760000613d0000000e0100035f0000012401100370000000000101043b000d00000001001d000006f80010009c00000dd50000213d000102710000003d000019e20000013d0000000201100039000000000301041a0000070103300197000000000223019f000000000021041b0000000e0100035f000002a401100370000000000101043b000000ff0010008c00000dd50000213d000000000001004b0000028a0000613d0000000e0100035f0000014401100370000000000101043b000d00000001001d000006f90010009c00000dd50000213d000102850000003d000018d20000013d0000000301100039000000000201041a00000702022001970000000d022001af000000000021041b0000000e0100035f000002c401100370000000000101043b000000ff0010008c00000dd50000213d000000000001004b0000029e0000613d0000000e0100035f000000e401100370000000000101043b000d00000001001d000006cd0010009c00000dd50000213d000102990000003d000018d20000013d0000000201100039000000000201041a000006de022001970000000d022001af000000000021041b0000000e0100035f000002e401100370000000000101043b000000ff0010008c00000dd50000213d000000000001004b000002b80000613d0000000e0100035f000001a401100370000000000201043b000000000002004b0000000001000039000000010100c039000d00000002001d000000000012004b00000dd50000c13d000102b00000003d000018d20000013d0000000d0000006b000006e90200004100000000020060190000000301100039000000000301041a000006fb03300197000000000223019f000000000021041b0000000e0100035f0000030401100370000000000101043b000000ff0010008c00000dd50000213d000000000001004b000002d20000613d000102c10000003d0000196b0000013d000006a90010009c000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c70000800d0200003900000004030000390000072004000041000102cf0000003d00001a5e0000013d00000dd50000613d000000400100043d000f00000001001d0000000f01000029000006a90010009c000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c70000800d020000390000000203000039000007220400004100000012050000290000095f0000013d000000240040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000101043b001200000001001d000006cd0010009c00000dd50000213d000102ec0000003d0000194d0000013d00000712020000411a9f18a50000040f001106cd0010019b0000000001000410000000110010006c0000000001000039000000010100c0391a9f131c0000040f0000071501000041000000000101041a000006cd01100197000000110010006c000000000100003900000001010060391a9f132b0000040f1a9f12ee0000040f000000400100043d001100000001001d000007210010009c000012360000213d00000011010000290000002002100039000000400020043f00000000000104350000071901000041000000000101041a000000ff0010019000000a650000c13d000f00000002001d000000400500043d0000071a01000041000000000015043500000000010004140000001202000029000000040020008c00000ac20000613d000000040400003900000020060000390000000003050019001000000005001d00000010050000291a9f12600000040f0000001005000029000000000001004b00000ac20000c13d000000400200043d001200000002001d000006dd01000041000000000012043500000004012000391a9f13490000040f000000120210006a00000012010000291a9f187f0000040f000001e40040008c00000dd50000413d00000000010c043b000006ce0010009c00000dd50000213d0000002302100039000000000042004b00000dd50000813d000000040210003900000000022f034f000000000302043b000006ce0030009c00000dd50000213d00000024021000390000000001230019000000000041004b00000dd50000213d000000000109043b001200000001001d000006cd0010009c00000dd50000213d000001c401f00370000000000401043b000000000004004b0000000001000039000000010100c039001100000004001d000000000014004b00000dd50000c13d0000000001000415001000000001001d00000044010000390000000201100367000000000101043b000006cd0010009c00000dd50000213d0000000004000411000000000041004b00000c2b0000613d000000120010006b00000c2b0000613d000007110100004100000d980000013d0000000001000416000000000001004b00000dd50000c13d00000000010400191a9f12de0000040f001200000002001d000000000010043f0000009f01000039000103570000003d000018da0000013d00000012020000291a9f12eb0000040f000000000101041a000006ce02100197000006bc0000013d000000240040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000101043b000000000010043f000000a801000039000103660000003d000019090000013d000000010210018f000000800020043f0000008001100270000000a00010043f0000008001000039000000400200003900000a150000013d000000240040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000101043b000000000010043f0000009e01000039000103770000003d000019090000013d000000ff0210018f000000800020043f0000000802100270000000ff0220018f000000a00020043f0000001001100270000000ff0110018f000000c00010043f0000008001000039000000600200003900000a150000013d000001040040008c000000000900041600000dd50000413d000000000009004b00000dd50000c13d0000014009000039000000400090043f000000000101043b000006cd0010009c00000dd50000213d000000800010043f000000000105043b000006d40010009c00000dd50000213d000000a00010043f000000000102043b000006cd0010009c00000dd50000213d000000c00010043f000000000103043b000103980000003d00001a1e0000013d00000dd50000c13d000000e00010043f000000000106043b0001039d0000003d00001a1e0000013d00000dd50000c13d000001000010043f000000000108043b000103a20000003d00001a1e0000013d00000dd50000c13d000001200010043f000000000207043b000006d40020009c00000dd50000213d000000e401f00370000000000101043b000006ce0010009c00000dd50000213d0000002303100039000000000043004b00000dd50000813d001100040010003d0000001103f00360000000000303043b001200000003001d000006ce0030009c00000dd50000213d00000012011000290000002401100039000000000041004b00000dd50000213d0000000001000415000f00000001001d000000800100043d0000006004100210000000400300043d0000002001300039000000e00500043d000000c00600043d000000a00700043d0000000000410435000000a00470021000000034073000390000000000470435000000600460021000000040063000390000000000460435000000000005004b000006e904000041000000000400601900000054053000390000000000450435000000a002200210000000550430003900000000002404350000000000d30435000006ea0030009c000012360000213d0000008002300039001000000002001d000000400020043f00000000020304331a9f18910000040f000e00000001001d000000800100043d000006cd021001970000000001000411000000000021004b00000d730000c13d000d00100000002d0000000e01000029000000000010043f000000a901000039000103e40000003d000019090000013d000006cd0010019800000e3b0000c13d000000800100043d001006cd0010019c000001c60000613d000000c00100043d000c06cd0010019c000001c60000613d000000e00100043d000b00000001001d000000000001004b0000000001000019000003f50000613d000001000100043d000000000001004b0000000001000039000000010100c0390000000100100190000001c60000c13d0000000e0000006b000001c60000613d000001200000043f0000000e01000029000000000010043f000000a901000039000103ff0000003d000018da0000013d000000a00200043d000000a00220021000000010022001af000000000021041b0000000b0000006b000006ee0200004100000000020060190000000101100039000000000301041a000006ef03300197000000000232019f000001000300043d000000000003004b000006f0030000410000000003006019000000000232019f0000000c022001af000000000021041b0017000c0000002d000104140000003d000019490000013d000000170440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b000000200200008a00000dd50000613d0000000d05000029000000240150003900000040030000390000000000310435000006f101000041000000000015043500000004015000390000000e03000029000000000031043500000044015000390000001204000029000000000041043500000000032401700000001f0440018f00000064015000390000000002310019000000110500002900000020055000390000000205500367000004340000613d000000000605034f0000000007010019000104330000003d0000193d0000013d000004310000c13d000000000004004b0000043a0000613d000000000335034f00000003044002100001043a0000003d000018df0000013d0000001201100029000000000001043500000000010004140000000c02000029000000040020008c0000113e0000c13d0000000102000031000011530000013d000001c40040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000201043b000006cd0020009c00000dd50000213d0000000001000411000000000012004b00000a680000c13d000000a401f00370000000000101043b000006f80010009c00000dd50000213d000000000001004b00000b020000c13d00110000000b001d00120000000f0353000000a302000039000000000102041a000000010110003a00000aad0000613d000000000012041b000000000010043f000000a7010000390001045e0000003d000018da0000013d000000120900035f0000000402900370000000000702043b000006cd0070009c000000110a00002900000dd50000213d000000000201041a000006de02200197000000000272019f000000000021041b0000002403900370000000000303043b000006f80030009c00000dd50000213d000006ff02200197000000a0033002100000070003300197000000000223019f000000000021041b0000004403900370000000000303043b000006f80030009c00000dd50000213d0000070102200197000000d003300210000000000223019f000000000021041b0000006402900370000000000202043b000006cd0020009c00000dd50000213d0000000103100039000000000403041a000006de04400197000000000424019f000000000043041b0000008404900370000000000404043b000006f80040009c00000dd50000213d000000a0044002100000070004400197000000000224019f000000000023041b000000c402900370000000000302043b000006cd0030009c00000dd50000213d0000000202100039000000000402041a000006de04400197000000000334019f000000000032041b000000e404900370000000000404043b000006f80040009c00000dd50000213d000006ff03300197000000a0044002100000070004400197000000000334019f000000000032041b0000010404900370000000000404043b000006f80040009c00000dd50000213d0000070103300197000000d004400210000000000334019f000000000032041b0000012402900370000000000302043b000006f90030009c00000dd50000213d0000000302100039000000000402041a0000070204400197000000000334019f000000000032041b0000014404900370000000000604043b000006f80060009c00000dd50000213d0000070303300197000000c0046002100000070404400197000000000434019f000000000042041b0000016403900370000000000303043b000000000003004b0000000005000039000000010500c039000000000053004b00000dd50000c13d0000070504400197000000000003004b00000706050000410000000005006019000000000445019f000000000042041b0000018405900370000000000505043b000000000005004b0000000008000039000000010800c039000000000085004b00000dd50000c13d0000070704400197000000000005004b000006e9050000410000000005006019000000000445019f000000000042041b0000000401100039000001a402900370000000000202043b000000000021041b000006a900a0009c000006a90a0080410000004001a00210000000a302000039000000000502041a000000000003004b000011810000c13d0000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c70000800d020000390000000303000039000007090400004100000000060700190000095f0000013d000000640040008c000000000300041600000dd50000413d000000000003004b00000dd50000c13d000000000101043b001200000001001d000000000305043b000000000003004b0000000001000039000000010100c039001100000003001d000000000013004b00000dd50000c13d000000000102043b001000000001001d0000071f0010009c00000dd50000213d0000001201000029000000000010043f0000002000e0043f000000400200003900000000010000191a9f18910000040f000000000201041a000006eb01000041000000800010043f0000000001000414000006cd02200197000000040020008c000005080000613d000105070000003d000019d80000013d00000a730000613d00000000040200190001050b0000003d000019560000013d000006ea0020009c000012360000213d0000008002200039000f00000002001d000000400020043f000006d00010009c000000000200041100000dd50000213d000000200010008c00000dd50000413d000000800100043d000006cd0010009c00000dd50000213d000000000021004b0000051c0000613d000000000042004b00000d970000c13d0001051e0000003d0000196b0000013d000006a90010009c000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c70000800d020000390000000403000039000007200400004100000012050000290000095f0000013d000000240040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000101043b001200000001001d000006cd0010009c00000dd50000213d1a9f12ee0000040f0000001201000029000000000001004b00000a820000c13d000006f70100004100000d980000013d000000640040008c000000000300041600000dd50000413d000000000003004b00000dd50000c13d000000000101043b001200000001001d000006cd0010009c00000dd50000213d000000000105043b001100000001001d000006cd0010009c00000dd50000213d000000000102043b001000000001001d000006cd0010009c00000dd50000213d1a9f12ee0000040f0000001204000029000000000004004b00000d970000613d0000009c01000039000000000201041a000006cd03200197000000000043004b000005580000613d000006de02200197000000000242019f000000000021041b000000aa03000039000000000103041a000006cd021001970000001104000029000000000042004b000000ab02000039000005620000613d000006de01100197000000000141019f000000000013041b000000000102041a000006cd02100197000000100020006c00000b100000613d000006de0110019700000010011001af000000ab02000039000000000012041b00000b100000013d0000000001000416000000000001004b00000dd50000c13d00000000010400191a9f12d30000040f1a9f14410000040f000006b90000013d000000a40040008c000000000400041600000dd50000413d000000000004004b00000dd50000c13d000000000101043b001200000001001d000006cd0010009c00000dd50000213d000000000105043b001100000001001d000006cd0010009c00000dd50000213d000000000102043b001000000001001d000006cd0010009c00000dd50000213d000000000103043b000f00000001001d000006cd0010009c00000dd50000213d000000000106043b000e00000001001d0000000001000415000d00000001001d000000000300041a0000ffff003001900000059e0000613d0000000001000410001600000001001d0000800201000039000c00000003001d00000024030000390000000004000415000000160440008a0000000504400210000006d1020000411a9f18a50000040f0000000c03000029000000ff0230018f000000010020008c00000b910000c13d000000000001004b00000b910000c13d0000ff0000300190000001000100008a0000000004030019000000000113016f00000001021001bf000000000020041b0000009c01000039000000000301041a000006de0330019700000012033001af000000400500043d00000b2a0000c13d0000ffff0400008a000000000242016f00000100022001bf000000000020041b000000000031041b000006df0050009c000012360000213d00000000040500190000004001400039000000400010043f0000000b010000390000000001140436000006e0020000410000000000210435000000400200043d000006df0020009c000012360000213d0000004003200039000000400030043f0000002005200039000c00000005001d000006e10300004100000000003504350000000503000039000000000032043500000000020404331a9f18910000040f001200000001001d0000000c010000290000000502000039000105ca0000003d0000199f0000013d000006e202000041000105cd0000003d0000191b0000013d000006e3030000410000000000310435000006e40020009c000012360000213d000000c003200039000000400030043f00000000020204331a9f18910000040f0000000104000039000000000014041b0000000501000039000006e302000041000000000021041b0000006a01000039000000000201041a000006de0220019700000010022001af000000000021041b00000000010400191a9f13df0000040f0000000101000039000105e40000003d000019b10000013d0000ff010100008a000000000200041a000000000112016f000000000010041b000000400100043d00000001030000390000000000310435000006a90010009c000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d9011001c70000800d02000039000006e5040000411a9f18c30000040f000000010020019000000b720000c13d00000dd50000013d000000840040008c00000dd50000413d000105fe0000003d00001a800000013d000006cd0010009c00000dd50000213d000000000102043b001000000001001d000006a90010009c00000dd50000213d000000000103043b000006ce0010009c00000dd50000213d0000002302100039000000000042004b00000dd50000813d0001060c0000003d000019c70000013d000f00000001001d0000000001000415000e00000001001d000106110000003d000019930000013d00000b000000c13d00000080021000390000000002020433000000000002004b000001c60000c13d000c00000001001d0000004001100039000b00000001001d0000000001010433000d06cd0010019b000000ab01000039000000000101041a000006cd011001970000000d0010006b00000b9b0000c13d00000000010004111a9f14a80000040f000000000001004b00000c860000c13d000007280100004100000d980000013d000001c40040008c000000000100041600000dd50000413d000000000001004b00000dd50000c13d00000000010c043b000006ce0010009c00000dd50000213d0000002302100039000000000042004b00000dd50000813d000000040210003900000000022f034f000000000302043b000006ce0030009c00000dd50000213d00000024021000390000000001230019000000000041004b00000dd50000213d000000000109043b000006cd0010009c00000dd50000213d00000004010000391a9f156b0000040f000006cd01100197000106420000003d000018ee0000013d00000000010000190000066a0000613d000000020100036700120000000103530000016401100370000000000101043b001100000001001d0001064b0000003d00001a420000013d0000014402200370000000000202043b0001064f0000003d000019620000013d00000000010000190000066a0000c13d000000120100035f0000012401100370000000000101043b001000000001001d000106570000003d00001a010000013d000006e6020000411a9f18a50000040f000000100010006c00000000010000190000066a0000213d000000120200035f000000c401200370000000000101043b000f00000001001d000000000001004b001000a40020037400000cb80000c13d000000120100035f000000e401100370000000000101043b000f00000001001d000000000001004b00000d2a0000c13d0000000101000039000000010210018f000006bc0000013d0000000001000416000000000001004b00000dd50000c13d00000000010400191a9f12d30000040f0000006a02000039000000000202041a000000000112013f000006cd0010019800000000020000390000000102006039000006bc0000013d000000240040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000101043b001200000001001d000006cd0010009c00000dd50000213d1a9f12ee0000040f0000001201000029000000000001004b00000a8c0000c13d000000400100043d0000006402100039000006e70300004100000000003204350000004402100039000006e8030000410000000000320435000000240210003900000026030000390000000000320435000006dd02000041000000000021043500000004021000390000002003000039000000000032043500000a220000013d0000000001000416000000000001004b00000dd50000c13d00000000010400191a9f12de0000040f001200000002001d1a9f12980000040f000000010110003900000012020000291a9f12eb0000040f000000000201041a000006bc0000013d0000000001000416000000000001004b00000dd50000c13d000106a60000003d0000194d0000013d00000712020000411a9f18a50000040f000006cd011001970000000002000410000000000012004b00000a170000c13d000007150100004100000a120000013d000000440040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000205043b001200000002001d000000000101043b1a9f12950000040f00000012020000291a9f143a0000040f000000000001004b0000000002000039000000010200c039000000400100043d000000000021043500000a140000013d000000240040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000101043b000000000010043f000000a201000039000000200010043f00000a0e0000013d000000240040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000101043b0000024002000039000000400020043f000000800000043f000000a00000043f000000c00000043f000000e00000043f000001000000043f000001200000043f000001400000043f000001600000043f000001800000043f000001a00000043f000001c00000043f000001e00000043f000002000000043f000002200000043f000000000010043f0000002000e0043f000106e30000003d00001a9b0000013d000000000401041a000006cd02400197000002400020043f000000a003400270000006f803300197000002600030043f000000d004400270000002800040043f0000000105100039000000000705041a0000000208100039000000030b1000390000000401100039000006cd05700197000002a00050043f000000d006700270000000a007700270000006f807700197000002c00070043f000002e00060043f000000000a08041a000006cd08a00197000003000080043f000000a009a00270000006f809900197000003200090043f000000d00aa002700000034000a0043f000000000e0b041a000006f90be001970000036000b0043f000000c00ce00270000006f80cc001970000038000c0043f000006fa00e00198000000000d000039000000010d00c039000003a000d0043f000006fb00e0009c000000000e000039000000010e002039000003c000e0043f000000000f01041a000003e000f0043f000005c001000039000000400010043f000004000020043f000004200030043f000004400040043f000004600050043f000004800070043f000004a00060043f000004c00080043f000004e00090043f0000050000a0043f0000052000b0043f0000054000c0043f0000056000d0043f0000058000e0043f000005a000f0043f000005c00020043f000005e00030043f000006000040043f000006200050043f000006400070043f000006600060043f000006800080043f000006a00090043f000006c000a0043f000006e000b0043f0000070000c0043f0000072000d0043f0000074000e0043f0000076000f0043f000001c00200003900000a150000013d0000000001000416000000000001004b00000dd50000c13d0000003801000039000000000101041a000006cd0110019700000a120000013d000000e40040008c00000dd50000413d000000000101043b001200000001001d000006cd0010009c00000dd50000213d000000000505043b000000000005004b0000000001000039000000010100c039001100000005001d000000000015004b00000dd50000c13d000000000103043b001000000001001d000000000102043b000f00000001001d000000000106043b000006ce0010009c00000dd50000213d0000002302100039000000000042004b00000dd50000813d000d00040010003d0000000d02f00360000000000202043b000e00000002001d000006ce0020009c00000dd50000213d00000024011000390000000e020000290000000502200210000b00000001001d000c00000002001d0000000001120019000000000041004b00000dd50000213d000000000208043b000000000002004b0000000001000039000000010100c039000a00000002001d000000000012004b00000dd50000c13d000000000107043b000800000001001d000006cd0010009c00000dd50000213d0000000001000415000500000001001d000006eb01000041000000400200043d000900000002001d00000000001204350000000e0000006b00000010020000290000000e0200c029001000000002001d00000000010004140000001202000029000000040020008c0000077b0000613d00000004040000390000002006000039000000120200002900000009030000290001077a0000003d00001a700000013d00000a730000613d0000000101000031000700000001001d0001077f0000003d00001a5a0000013d0000000902100029000400000001001d000000000012004b00000000010000390000000101004039000600000002001d000006ce0020009c000012360000213d0000000100100190000012360000c13d0000000601000029000000400010043f0000000701000029000006d00010009c000000000200041100000dd50000213d0000000701000029000000200010008c00000dd50000413d00000009010000290000000001010433000006cd0010009c00000dd50000213d000000000021004b0000079a0000613d000000120020006c00000d970000c13d000000110000006b0000000601000029000300240010003d000900040010003d0000000c010000290002001f0010019300000e1c0000c13d0000001001000029000000010010008c00000ea60000c13d0000000a0000006b00000f070000c13d000006d801000041000107a90000003d00001a2c0000013d00000000010004140000001202000029000000040020008c000010dd0000613d0000002404000039000107b00000003d000019830000013d000010db0000c13d000107b30000003d00001a930000013d000107b50000003d000018e90000013d00000eea0000613d000000000603034f0000000007010019000107ba0000003d0000193d0000013d000007b80000c13d00000eea0000013d000000240040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000301043b0000009c01000039000000000101041a000006cd011001970000000004000411000000000014004b00000d970000c13d0000000001000414000000040040008c00000a8e0000c13d000000010100003900000abc0000013d000001c40040008c00000dd50000413d0000016401f00370000000000101043b000006ce0010009c00000dd50000213d0000002302100039000000000042004b00000dd50000813d000000040210003900000000022f034f000000000202043b001200000002001d000006ce0020009c00000dd50000213d0000002402100039001100000002001d0000001201200029000000000041004b00000dd50000213d00000000010c043b001000000001001d000006cd0010009c00000dd50000213d000000000109043b000006ce0010009c00000dd50000213d0000002302100039000000000042004b00000dd50000813d000e00040010003d0000000e02f00360000000000202043b000f00000002001d000006ce0020009c00000dd50000213d0000000f02000029000d0005002002180000000d011000290000002401100039000000000041004b00000dd50000213d0000000001000415000c00000001001d00000044010000390000000201100367000000000101043b000006cd0010009c00000dd50000213d0000000002000411000000000021004b000008030000613d000000100010006b0000034b0000c13d0000000001000415000b00000001001d00000002040003670000000401400370000000000101043b000006cd0010009c00000dd50000213d0000002402400370000000000202043b000006cd0020009c00000dd50000213d0000004403400370000000000303043b000006cd0030009c00000dd50000213d0000006405400370000000000505043b000006cd0050009c00000dd50000213d000000a406400370000000000606043b000006ce0060009c00000dd50000213d000000c407400370000000000707043b000006ce0070009c00000dd50000213d000000e408400370000000000808043b000006ce0080009c00000dd50000213d0000010409400370000000000909043b000006ce0090009c00000dd50000213d000000840a400370000000000a0a043b000001240b400370000000000b0b043b0000014404400370000000000c04043b000000400400043d000001800d4000390000000000cd0435000001600c4000390000000000bc0435000001400b40003900000000009b04350000012009400039000000000089043500000100084000390000000000780435000000e0074000390000000000670435000000c0064000390000000000a60435000000a006400039000000000056043500000080054000390000000000350435000000600340003900000000002304350000004002400039000000000012043500000020014000390000070b020000410000000000210435000001800200003900000000002404350000070c0040009c000012360000213d000001a002400039000000400020043f00000000020404331a9f18910000040f1a9f18380000040f000a00000001001d0000000003000031000000110100002900000012020000291a9f129b0000040f00000000020100190000000a010000291a9f16000000040f000000020200036700120000000203530000014402200370000000000202043b000900000002001d000000000020043f000000a102000039000000200020043f000a00000001001d000108620000003d00001a9b0000013d000000010200008a0000000f0320014f000000000201041a000800000002001d001100000003001d000000000032004b00000aad0000213d000000120200035f0000004402200370000000000202043b000006cd0020009c00000dd50000213d000000000020043f0000000101100039000108720000003d000019090000013d000700000001001d000000110010006c00000aad0000213d0000000a01000029000006cd01100197000108790000003d000018ee0000013d00000c800000613d000000120100035f000000a401100370000000000101043b000006ce0010009c00000dd50000213d00000000020004150000001c0220008a00110005002002180000000f0010006c000008890000813d00000000020004150000001b0220008a0011000500200218000000000001004b00000c800000c13d00000009010000290001088c0000003d00001a420000013d0000012402200370000000000202043b000a00000002001d000108910000003d000019620000013d00000011010000290000000501100270000000000100003f000000010100c03f00000c800000c13d000000120100035f0000010401100370000000000101043b001100000001001d000006ce0010009c00000dd50000213d0001089e0000003d00001a010000013d000006e6020000411a9f18a50000040f000000110010006c00000c800000213d000000120100035f000000c401100370000000000101043b000006ce0010009c00000dd50000213d00000008030000290011000f0030002d000000110010006b000008ad0000a13d000000000001004b00000c800000c13d000000120100035f000000e401100370000000000101043b000006ce0010009c00000dd50000213d00000007030000290012000f0030002d000000120010006b000008b80000a13d000000000001004b00000c800000c13d0000000901000029000000000010043f000000a001000039000108bd0000003d000018da0000013d0000000a020000291a9f140d0000040f0000000901000029000108c20000003d0000195b0000013d0000001102000029000000000021041b0000000901000029000108c70000003d0000195b0000013d00000044020000390000000202200367000000000202043b000006cd0020009c00000dd50000213d000108ce0000003d00001a4a0000013d0000001202000029000000000021041b00000000010004150000000b01100069000000000100000200000002010003670000014402100370000000000202043b001200000002001d0000000402100370000000000402043b000006cd0040009c00000dd50000213d0000006402100370000000000602043b000006cd0060009c00000dd50000213d0000002402100370000000000702043b000006cd0070009c00000dd50000213d0000008401100370000000000501043b00000012010000290000000f020000291a9f165a0000040f000000200300003900000002040003670000002401400370000000000601043b000006cd0060009c00000dd50000213d000000400100043d00000020021000390000000f05000029000000000052043500000000003104350000000d050000290011001f005001930000000e02000029000e00200020003d00000040031000390000000002530019000000000005004b000009000000613d0000000e04400360000000004504043c0000000003530436000000000023004b000008fc0000c13d000000110000006b00000000000204350000000002120049000006a90020009c000006a9020080410000006002200210000006a90010009c000006a9010080410000004001100210000000000112019f0000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c70000800d0200003900000004030000390000070d04000041000000120500002900000000070000191a9f18c30000040f000000010020019000000dd50000613d0000000201000367000b0000000103530000002401100370000000000101043b001200000001001d0000000f01000029000000010010008c000011f90000c13d0000001201000029000006cd0010009c00000dd50000213d0000000b0200035f0000000e01200360000000000101043b001100000001001d001900120000002d0001092a0000003d000019490000013d000000190440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b000011ad0000613d000000400200043d0000002401200039000000110300002900000000003104350000070f010000410000000000120435001100000002001d00000004012000390000001002000029000000000021043500000000010004140000001202000029000000040020008c000009440000613d000000440400003900000012020000290000001103000029000109430000003d0000197e0000013d00000a730000613d000109460000003d000019790000013d00000011020000290000122b0000013d0000000001000416000000000001004b00000dd50000c13d1a9f12ee0000040f0000003801000039000000000201041a000006de03200197000000000031041b000000400100043d000006a90010009c000006a90100804100000040011002100000000003000414000006a90030009c000006a903008041000000c003300210000000000113019f000006cd05200197000006d3011001c70000800d0200003900000003030000390000070a0400004100000000060000191a9f18c30000040f000000010020019000000b100000c13d00000dd50000013d000000240040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000101043b000000000010043f0000009d010000390001096d0000003d000018da0000013d0000000802100039000000000202041a0000000703100039000000000303041a0000000604100039000000000404041a0000000505100039000000000505041a0000000406100039000000000606041a0000000307100039000000000707041a0000000208100039000000000808041a0000000109100039000000000909041a000000000101041a000006cd01100197000000800010043f000006cd01900197000000a00010043f000006cd01800197000000c00010043f000000e00070043f000001000060043f000001200050043f000006ce01400197000001400010043f0000004001400270000006ce01100197000001600010043f0000008001400270000006ce01100197000001800010043f000000c001400270000001a00010043f000001c00030043f000000ff0120018f000001e00010043f0000008001000039000001800200003900000a150000013d000000840040008c00000dd50000413d0001099b0000003d00001a800000013d000006cd0010009c00000dd50000213d000000000102043b000006ce0010009c00000dd50000213d0000002302100039000000000042004b00000dd50000813d000000040210003900000000022f034f000000000202043b001000000002001d000006ce0020009c00000dd50000213d000000240110003900000010020000290000000502200210000f00000001001d000e00000002001d0000000001120019000000000041004b00000dd50000213d000000000103043b000006ce0010009c00000dd50000213d0000002302100039000000000042004b00000dd50000813d000109b90000003d000019c70000013d000d00000001001d0000000001000415000c00000001001d000109be0000003d000019930000013d00000b000000c13d000b00000001001d00000080011000390000000001010433000000000001004b000001c60000613d0000001001000029000906a90010019b0000000b010000290000004001100039000800000001001d0000000001010433000a06cd0010019b000000ab01000039000000000101041a000006cd011001970000000a0010006b00000cca0000c13d00000000010004111a9f14a80000040f000000000001004b000006240000613d000109d60000003d00001a070000013d000800000005001d000109d90000003d000019ce0000013d0000000d010000291a9f13cb0000040f0000000803000029000109de0000003d000019bc0000013d000d00000002001d000006ce0020009c000012360000213d0000000100100190000012360000c13d0000000d01000029000000400010043f0020000a0000002d000109e80000003d000019490000013d000000200440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b000000000600041100000dd50000613d00000726010000410000000d02000029000109f30000003d00001a520000013d00000008080000291a9f14c00000040f000000000201001900000000010004140000000a03000029000000040030008c00000a000000613d0000000d0300002900000000043200490000000a02000029000109ff0000003d0000197e0000013d00000a730000613d0000000101000031000a00000001001d00010a040000003d00001a5a0000013d0000000d0200002900000f7c0000013d000000240040008c000000000200041600000dd50000413d000000000002004b00000dd50000c13d000000000101043b000000000010043f000000200090043f000000400200003900000000010000191a9f18910000040f000000000101041a000000800010043f0000008001000039000000200200003900000000030000191a9f18870000040f000006dd01000041000000800010043f0000002001000039000000840010043f0000003801000039000000a40010043f0000071301000041000000c40010043f0000071401000041000000e40010043f000000800100003900000084020000391a9f187f0000040f000006eb01000041000000800010043f0000000001000414000000040020008c00000a330000613d000000040400003900000080030000390000002006000039001000000002001d000000100200002900000000050300191a9f12600000040f0000001002000029000000000001004b00000a730000613d000000000402001900010a360000003d000019560000013d000006ea0020009c000012360000213d0000008002200039001000000002001d000000400020043f000006d00010009c000000000200041100000dd50000213d000000200010008c00000dd50000413d000000800100043d000006cd0010009c00000dd50000213d000000000021004b00000a470000613d000000000042004b00000d970000c13d0000001101000029000000000010043f000000a901000039000000200010043f00010a4d0000003d00001a9b0000013d0000000101100039000000000201041a00000716022001970000001206000029000000000006004b00000717030000410000000003006019000000000232019f000000000021041b0000001001000029000006a90010009c000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c70000800d020000390000000303000039000007180400004100000011050000290000095f0000013d00000012010000291a9f13560000040f00000b100000013d000006eb01000041000000800010043f0000000001000414000000040020008c00000a970000613d00000004040000390000008003000039000000200600003900010a720000003d00001a700000013d00000a970000c13d0000000304000367000000010200003100010a770000003d0000192d0000013d00000a7d0000613d000000000704034f000000000801001900010a7c0000003d00001a360000013d00000a7a0000c13d000000000006004b00000a810000613d00010a810000003d0000190f0000013d1a9f187f0000040f000000000010043f000000a50100003900010a860000003d000018da0000013d000000000301041a000000000003004b00000aa90000c13d00000012010000291a9f13ee0000040f00000b100000013d1a9f13020000040f00000b100000013d000000000003004b00000ab10000c13d000000800300003900000000020400190000000004000019000000000500001900000000060000191a9f123c0000040f00000abc0000013d00010a990000003d000019560000013d000006ea0020009c000012360000213d000000800b2000390000004000b0043f000006d00010009c000000000200041100000dd50000213d000000200010008c00000dd50000413d000000800100043d000006cd0010009c00000dd50000213d000000000021004b00000d970000c13d000000020f0003670000044d0000013d000000a404000039000000000204041a000000000002004b00000b040000c13d000006f501000041000000000010043f0000001101000039000012390000013d000006a90010009c000006a901008041000000c001100210000006fc011001c7000080090200003900000000050000191a9f18c30000040f0000006003100270000106a90030019d0003000000010355000000010120018f001200000001001d1a9f13720000040f000000120000006b00000b100000c13d000006fd0100004100000d980000013d00000001010000310000001f02100039000000200300008a000000000332016f000000000253001900010ac90000003d000019ec0000013d000006ce0020009c000012360000213d0000000100300190000012360000c13d000000400020043f000006d00010009c00000dd50000213d000000200010008c00000dd50000413d0000000001050433000007150010009c00010ad60000003d00001a620000013d000006a90010009c001000000001001d000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c70000800d0200003900000002030000390000071b0400004100010ae50000003d00001a5e0000013d00000dd50000613d00000011010000290000000001010433000000000001004b00000b100000613d00000010010000290000071c0010009c000012360000213d00000010030000290000006001300039000000400010043f00000040013000390000071d02000041000000000021043500000020013000390000071e020000410000000000210435000000270100003900000000001304350000001101000029000000000401043300000000010004140000001202000029000000040020008c00000d420000c13d000000010100003900000d450000013d000007250100004100000d980000013d000006fe0100004100000d980000013d000000010130008a000000000032004b00000b130000c13d000006f40230009a000000000002041b000000000014041b0000001201000029000000000010043f000000a50100003900010b0f0000003d000018da0000013d000000000001041b000000400100043d000000000200001900000a150000013d000000000012004b00000f090000a13d000006f40120009a000000000101041a000006f40230009a000000000012041b000000000010043f000000a501000039000000200010043f00000040020000390000000001000019001100000003001d1a9f18910000040f0000001102000029000000000021041b000000a401000039000000000101041a000000000001004b00000c820000c13d000006f501000041000000000010043f0000003101000039000012390000013d000000000031041b001200000005001d000006df0050009c000012360000213d00000012020000290000004001200039000000400010043f0000000b010000390000000002120436000006e001000041000c00000002001d0000000000120435000000400200043d000006df0020009c000012360000213d00000000010200190000000003020019000a00000001001d0000004001100039000000400010043f0000002002200039000b00000002001d000006e1010000410000000000120435000000050100003900000000001304350000000801400270000000ff0110018f1a9f13df0000040f000000120100002900000000020104330000000c010000291a9f18910000040f0000000a020000290000000002020433001200000001001d0000000b0100002900010b510000003d0000199f0000013d000006e20200004100010b540000003d0000191b0000013d000006e3030000410000000000310435000006e40020009c000012360000213d000000c003200039000000400030043f00000000020204331a9f18910000040f0000000102000039000000000012041b0000000501000039000006e302000041000000000021041b000000000100041a0000000801100270000000ff0110018f1a9f13df0000040f0000006a01000039000000000201041a000006de0220019700000010022001af000000000021041b000000000100041a0000000801100270000000ff0110018f001200000001001d1a9f13df0000040f000000120100002900010b720000003d000019b10000013d00000000010004150000000d0200002900000c280000013d00000012010000290000000f020000290000000c040000291a9f14ea0000040f000000400200043d0000002401200039001200000002001d00000004032000390000000b020000290000000002020433000006f8042001970000000f020000290000000002020433000006cd022001970000001105000029000000010050008c00000c050000c13d000006d605000041000000120600002900000000005604350000000000430435000000100300002900000000003104350000000001000414000000040020008c00000c180000613d000000440400003900000c120000013d000000400100043d0000006402100039000006db0300004100000000003204350000004402100039000006dc03000041000000000032043500000024021000390000002e030000390000068e0000013d000000aa01000039000000000201041a0000000c0100002900000000010104330000000003000411000006cd03300197000000400500043d0000006404500039000000000034043500000044035000390000000d040000290000000000430435000000240350003900000010040000290000000000430435000006cd0110019700000084035000390000000000130435000006cf010000410000000000150435000d00000005001d0000000401500039000000120300002900000000003104350000000001000414000006cd02200197000000040020008c00000bbd0000613d000000a40400003900000020060000390000000d0300002900010bbc0000003d00001a700000013d00000a730000613d00010bbf0000003d000019560000013d0000000d040000290000000d03200029000000000023004b00000000020000390000000102004039000a00000003001d000006ce0030009c000012360000213d0000000100200190000012360000c13d0000000a02000029000000400020043f000006d00010009c000000000200041600000dd50000213d000000200010008c00000dd50000413d0000000001040433000d00000001001d000900000012005300000d4d0000813d000007270100004100000d980000013d001d00120000002d00010bd90000003d000019490000013d0000001d0440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b00000dd50000613d000000400300043d000000240130003900000011020000290000000000210435000006d7010000410000000000130435001100000003001d00000004013000390000001002000029000000000021043500000000010004140000001202000029000000040020008c00000bf30000613d00000044040000390000001202000029000000110300002900010bf20000003d0000197e0000013d00000a730000613d00000001010000310000001f02100039000000200300008a000000000332016f000000110230002900010bfa0000003d000019ec0000013d000006ce0020009c000012360000213d0000000100300190000012360000c13d000000400020043f000006d00010009c00000dd50000213d00000000010004150000000d01100069000000000100000200000c260000013d000006d505000041000000120600002900000000005604350000000000430435000000100300002900000000003104350000004401600039000000110300002900000000003104350000000001000414000000040020008c00000c180000613d00000064040000390000002006000039000000120300002900000000050300191a9f123c0000040f000000000001004b00000a730000613d00010c1a0000003d000019790000013d000000120230002900010c1d0000003d000019ec0000013d000006ce0020009c000012360000213d0000000100300190000012360000c13d000000400020043f000006d00010009c00000dd50000213d000000200010008c00000dd50000413d00000000010004150000000e020000290000000001120049000000000100000200000b100000013d00000004010000391a9f156b0000040f0000000202000367000f0000000203530000016402200370000000000202043b000b00000002001d000000000020043f000000a102000039000000200020043f000c00000001001d000000400200003900000000010000191a9f18910000040f000000000201041a000d00000002001d0000000f0200035f000000a402200370000000000202043b000e00000002001d000006ce0020009c00000dd50000213d000000010200008a0000000e0320014f000a00000003001d0000000d0030006b00000aad0000213d0000000f0200035f0000004402200370000000000202043b000006cd0020009c00000dd50000213d000000000020043f000000010110003900010c4f0000003d000019090000013d000900000001001d0000000a0010006c00000aad0000213d0000000c01000029000006cd0110019700010c560000003d000018ee0000013d00000c800000613d0000000b01000029000000000010043f000000a00100003900010c5c0000003d000018da0000013d0000000f0200035f0000014402200370000000000202043b000c00000002001d00010c620000003d000019620000013d00000c800000c13d0000000f0100035f0000012401100370000000000101043b000a00000001001d00010c690000003d00001a010000013d000006e6020000411a9f18a50000040f0000000a0010006c00000c800000213d0000000d02000029000d000e0020002d0000000f0100035f000000c401100370000000000101043b0000000d0010006b00000c760000a13d000000000001004b00000c800000c13d00000009020000290000000e022000290000000f0100035f000000e401100370000000000101043b000f00000002001d000000000012004b000010600000a13d000000000001004b000010600000613d000007100100004100000d980000013d0000000003010019000000010110008a000000a40400003900000b070000013d00010c880000003d00001a070000013d000b00000005001d00010c8b0000003d000019ce0000013d0000000f010000291a9f13cb0000040f0000000b0300002900010c900000003d000019bc0000013d000f00000002001d000006ce0020009c000012360000213d0000000100100190000012360000c13d0000000f01000029000000400010043f0014000d0000002d00010c9a0000003d000019490000013d000000140440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b000000000500041100000dd50000613d000006d2010000410000000f0200002900010ca50000003d00001a8c0000013d0000000b070000291a9f14900000040f000000000201001900000000010004140000000d03000029000000040030008c00000cb20000613d0000000f0300002900000000043200490000000d0200002900010cb10000003d0000197e0000013d00000a730000613d0000000101000031000d00000001001d00010cb60000003d00001a5a0000013d0000000f0200002900000dc70000013d000000100100035f000000000101043b000e00000001001d000006ce0010009c00000dd50000213d000000110100002900010cc00000003d000019f50000013d000000000101041a000000010200008a000000000221013f0000000e0020006b00000aad0000213d0000000e011000290000000f0010006c0000000001000019000006630000a13d0000066a0000013d000000aa01000039000000000201041a0000000b0100002900000000010104330000000003000411000006cd03300197000000400500043d0000006404500039000000000034043500000044035000390000000a040000290000000000430435000000240350003900000009040000290000000000430435000006cd0110019700000084035000390000000000130435000006cf010000410000000000150435000a00000005001d0000000401500039000000120300002900000000003104350000000001000414000006cd02200197000000040020008c00000cec0000613d000000a40400003900000020060000390000000a0300002900010ceb0000003d00001a700000013d00000a730000613d00010cee0000003d000019560000013d0000000a03200029000000000023004b00000000020000390000000102004039000700000003001d000006ce0030009c000012360000213d0000000100200190000012360000c13d0000000702000029000000400020043f000006d00010009c000000000200041600000dd50000213d000000200010008c00000dd50000413d0000000a010000290000000001010433000a00000001001d000600000012005300000bd40000413d00000008010000290000000001010433000800000001001d002106cd0010019b00010d090000003d000019490000013d000000210440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b000000000600041100000dd50000613d0000000801000029000806cd0010019b0000072601000041000000070200002900010d160000003d00001a520000013d0000000d080000291a9f14c00000040f000000000201001900000000010004140000000803000029000000040030008c00000ef20000c13d000a00010000003500000f780000013d0000001002000029000000200320003900000012020000291a9f12840000040f001000000001001d1a9f13720000040f000000000301001900000012010000290000001002000029000000110400002900000d4b0000013d000000100100035f000000000101043b001000000001001d000006ce0010009c00000dd50000213d000000110100002900010d320000003d000019f50000013d000000120200035f0000004402200370000000000202043b000006cd0020009c00000dd50000213d00010d390000003d000019410000013d000000010200008a000000000221013f000000100020006b00000aad0000213d00000010011000290000000f0010006c0000000001000039000000010100a0390000066a0000013d00000012020000290000000f030000291a9f12840000040f001100000001001d1a9f13720000040f00000000030100190000001201000029000000110200002900000010040000291a9f13a00000040f00000b100000013d0000000b010000290000000001010433000b00000001001d001506cd0010019b00010d530000003d000019490000013d000000150440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b000000000500041100000dd50000613d0000000b01000029000b06cd0010019b000006d2010000410000000a0200002900010d600000003d00001a8c0000013d0000000f070000291a9f14900000040f000000000201001900000000010004140000000b03000029000000040030008c00000d690000c13d000d00010000003500000dc30000013d00000000050300190000000a0420006a00000000020004160000000d0020006c00000d9b0000c13d00000000020500190000000a0300002900010d720000003d00001a740000013d00000dae0000013d000006eb01000041000000100300002900000000001304350000000001000414000000040020008c00000d7f0000613d00000004040000390000002006000039000000100300002900010d7e0000003d00001a700000013d00000a730000613d00010d810000003d000019560000013d0000001003200029000000000023004b00000000020000390000000102004039000d00000003001d000006ce0030009c000012360000213d0000000100200190000012360000c13d0000000d02000029000000400020043f000006d00010009c000000000200041100000dd50000213d000000200010008c00000dd50000413d00000010010000290000000001010433000006cd0010009c00000dd50000213d000000000021004b000003df0000613d0000072a01000041000000000010043f000006ed0100004100001aa1000104300000000a02000029000006a90020009c000006a9020080410000004002200210000006a90040009c000006a9040080410000006003400210000000000223019f000006a90010009c000006a901008041000000c001100210000000000112019f000006d3011001c70000800902000039000000090300002900010dac0000003d00001a3a0000013d000106a90020019d000006a902200197000d00000002001d000000000001004b00000dc30000c13d00010db30000003d00001a970000013d00010db50000003d000018e90000013d00000dbb0000613d000000000603034f000000000701001900010dba0000003d0000193d0000013d00000db80000c13d000000000005004b00000dc10000613d000000000343034f000000030450021000010dc10000003d000018df0000013d0000000d020000291a9f187f0000040f0000000d0100002900010dc60000003d00001a5a0000013d0000000a020000290000000002210019000000000012004b00000000010000390000000101004039000f00000002001d000006ce0020009c000012360000213d0000000100100190000012360000c13d0000000f01000029000000400010043f0000000d01000029000006d00010009c00000dd60000a13d00001a1c0000013d0000000c020000290000000001020433000b06cd0010019b00000060012000390000000001010433000000000001004b00000df90000c13d0000001001000029000000010010008c00000e3d0000c13d000006d8010000410000000f02000029000000000012043500000004012000390000001102000029000000000021043500000000010004140000000b02000029000000040020008c00000e830000613d000000240400003900010ded0000003d0000198b0000013d00000e830000c13d00010df00000003d00001a970000013d00010df20000003d000018e90000013d00000dbb0000613d000000000603034f000000000701001900010df70000003d0000193d0000013d00000df50000c13d00000dbb0000013d0000000f02000029000000240120003900000004022000390000000c0300002900000020033000390000000003030433000006d4033001970000001004000029000000010040008c00000e670000c13d000006d6040000410000000f05000029000000000045043500000000003204350000001102000029000000000021043500000000010004140000000b02000029000000040020008c00000e830000613d000000440400003900010e100000003d0000198b0000013d00000e830000c13d00010e130000003d00001a970000013d00010e150000003d000018e90000013d00000dbb0000613d000000000603034f000000000701001900010e1a0000003d0000193d0000013d00000e180000c13d00000dbb0000013d0000001001000029000000010010008c00000ecc0000c13d000006d601000041000000060200002900000000001204350000000f010000290000000902000029000000000012043500000008010000290000000302000029000000000012043500000000010004140000001202000029000000040020008c00000f3e0000613d000000440400003900010e2f0000003d000019830000013d00000f3c0000c13d00010e320000003d00001a930000013d00010e340000003d000018e90000013d00000eea0000613d000000000603034f000000000701001900010e390000003d0000193d0000013d00000e370000c13d00000eea0000013d000006ec0100004100000d980000013d0013000b0000002d00010e400000003d000019490000013d000000130440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b00000dd50000613d0000000f03000029000000240130003900000010020000290000000000210435000006d701000041000000000013043500000004013000390000001102000029000000000021043500000000010004140000000b02000029000000040020008c00000efc0000613d00000044040000390000000b020000290000000f03000029000000000503001900000000060000191a9f123c0000040f000d000100000035000000000001004b00000efc0000c13d00010e5e0000003d00001a970000013d00010e600000003d000018e90000013d00000dbb0000613d000000000603034f000000000701001900010e650000003d0000193d0000013d00000e630000c13d00000dbb0000013d000006d5040000410000000f05000029000000000045043500000000003204350000001102000029000000000021043500000044015000390000001002000029000000000021043500000000010004140000000b02000029000000040020008c00000e830000613d000000640400003900010e770000003d0000198b0000013d00000e830000c13d00010e7a0000003d00001a970000013d00010e7c0000003d000018e90000013d00000dbb0000613d000000000603034f000000000701001900010e810000003d0000193d0000013d00000e7f0000c13d00000dbb0000013d00010e850000003d00001a230000013d000006ce0010009c000012360000213d0000000100200190000012360000c13d000000400010043f0000000d02000029000006d00020009c00000dd50000213d0000000d02000029000000200020008c00000dd50000413d0000000c02000029000000000202043300000010030000290000000000310435000006a90010009c000006a90100804100000040011002100000000003000414000006a90030009c000006a903008041000000c003300210000000000113019f000006d9011001c7000006cd062001970000800d0200003900000004030000390000000107000039000006da0400004100010ea40000003d00001a5e0000013d00000c260000c13d00000dd50000013d002300120000002d00010ea90000003d000019490000013d000000230440008a0000000504400210000006d1020000411a9f18a50000040f0000000a0000006b00000f0d0000c13d000000000001004b00000dd50000613d000000100100002900000003020000290000000000120435000006d70100004100010eb70000003d00001a2c0000013d00000000010004140000001202000029000000040020008c0000111d0000613d00000044040000390000001202000029000000060300002900010ec00000003d00001a100000013d0000111b0000c13d00010ec30000003d00001a930000013d00010ec50000003d000018e90000013d00000eea0000613d000000000603034f000000000701001900010eca0000003d0000193d0000013d00000ec80000c13d00000eea0000013d000006d501000041000000060200002900000000001204350000000f010000290000000903000029000000000013043500000008010000290000000303000029000000000013043500000044012000390000001002000029000000000021043500000000010004140000001202000029000000040020008c00000f3e0000613d000000640400003900010edf0000003d000019830000013d00000f3c0000c13d00010ee20000003d00001a930000013d00010ee40000003d000018e90000013d00000eea0000613d000000000603034f000000000701001900010ee90000003d0000193d0000013d00000ee70000c13d000000000005004b00000ef00000613d000000000343034f000000030450021000010ef00000003d000018df0000013d00000007020000291a9f187f0000040f0000000005030019000000070420006a00000000020004160000000a0020006c00000f4f0000c13d0000000002050019000000070300002900010efb0000003d00001a740000013d00000f620000013d00010efe0000003d00001a230000013d000006ce0010009c000012360000213d0000000100200190000012360000c13d000000400010043f0000000d02000029000006d00020009c00000e900000a13d00000dd50000013d0000000e0000006b000010370000c13d000006f501000041000000000010043f0000003201000039000012390000013d000000000001004b00000dd50000613d000000060300002900000044013000390000000e0200002900000000002104350000004001000039000000030200002900000000001204350000070e01000041000000000013043500000008010000290000000902000029000000000012043500000064013000390000000c021000290000000c0000006b00000f250000613d0000000b030000290000000203300367000000003403043c0000000001410436000000000021004b00000f210000c13d000000020000006b000000000002043500000000010004140000001203000029000000040030008c000010ed0000613d00000006030000290000000004320049000000120200002900010f300000003d00001a100000013d000010eb0000c13d00010f330000003d00001a930000013d00010f350000003d000018e90000013d00000eea0000613d000000000603034f000000000701001900010f3a0000003d0000193d0000013d00000f380000c13d00000eea0000013d00010f3e0000003d000019fc0000013d00010f400000003d000019ab0000013d000006ce0010009c000012360000213d0000000100200190000012360000c13d000000400010043f0000000702000029000006d00020009c000000200300003900000dd50000213d0000000702000029000000200020008c00000dd50000413d0000000a0000006b000010f80000c13d000011270000013d0000000702000029000006a90020009c000006a9020080410000004002200210000006a90040009c000006a9040080410000006003400210000000000223019f000006a90010009c000006a901008041000000c001100210000000000112019f000006d3011001c70000800902000039000000060300002900010f600000003d00001a3a0000013d000106a90020019d000006a902200197000a00000002001d000000000001004b00000f780000c13d0000000303000367000000200100008a0000000a0200002900010f6a0000003d000018e90000013d00000f700000613d000000000603034f000000000701001900010f6f0000003d0000193d0000013d00000f6d0000c13d000000000005004b00000f760000613d000000000343034f000000030450021000010f760000003d000018df0000013d0000000a020000291a9f187f0000040f0000000a0100002900010f7b0000003d00001a5a0000013d00000007020000290000000002210019000000000012004b00000000010000390000000101004039000d00000002001d000006ce0020009c000012360000213d0000000100100190000012360000c13d0000000d01000029000000400010043f0000000a01000029000006d00010009c00000dd50000213d0000000b010000290000000001010433000806cd0010019b0000000901000029000000010010008c0000000e010000290009001f0010019300000fc10000c13d0000000f010000290000000201100367000000000101043b000700000001001d001e00080000002d00010f990000003d000019490000013d0000001e0440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b00000dd50000613d0000000d020000290000002401200039000000070300002900000000003104350000070f01000041000000000012043500000004012000390000001102000029000000000021043500000000010004140000000802000029000000040020008c00000ffb0000613d000000440400003900000008020000290000000d03000029000000000503001900000000060000191a9f123c0000040f000a000100000035000000000001004b00000ffb0000c13d0000000303000367000000200100008a0000000a0200002900010fba0000003d000018e90000013d00000f700000613d000000000603034f000000000701001900010fbf0000003d0000193d0000013d00000fbd0000c13d00000f700000013d001f00080000002d00010fc40000003d000019490000013d0000001f0440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b00000dd50000613d0000000d030000290000004401300039000000100200002900000000002104350000002401300039000000400200003900000000002104350000070e01000041000000000013043500000004013000390000001102000029000000000021043500000064013000390000000e021000290000000e0000006b00000fe00000613d0000000f030000290000000203300367000000003403043c0000000001410436000000000021004b00000fdc0000c13d000000090000006b000000000002043500000000010004140000000803000029000000040030008c00000ffb0000613d0000000d0300002900000000043200490000000802000029000000000503001900000000060000191a9f123c0000040f000a000100000035000000000001004b00000ffb0000c13d0000000303000367000000200100008a0000000a0200002900010ff40000003d000018e90000013d00000f700000613d000000000603034f000000000701001900010ff90000003d0000193d0000013d00000ff70000c13d00000f700000013d0000000a010000290000001f01100039000000200200008a000000000221016f0000000d01200029000000000021004b00000000020000390000000102004039000006ce0010009c000012360000213d0000000100200190000012360000c13d000000400010043f0000000a02000029000006d00020009c000000200400003900000dd50000213d0000000b020000290000000003020433000000200210003900000010050000290000000000520435000000000041043500000040041000390000000e024000290000000e0000006b0000101c0000613d0000000f050000290000000205500367000000005605043c0000000004640436000000000024004b000010180000c13d000006cd06300197000000090000006b00000000000204350000000002120049000006a90020009c000006a9020080410000006002200210000006a90010009c000006a9010080410000004001100210000000000112019f0000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c70000800d02000039000000040300003900000001070000390000070d04000041000110330000003d00001a5e0000013d00000dd50000613d00000000010004150000000c0200002900000c280000013d0000000d0100002900000020011000390000000201100367000000000101043b001100000001001d002200120000002d0001103f0000003d000019490000013d000000220440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b00000dd50000613d0000000301000029000000110200002900000000002104350000070f010000410001104b0000003d00001a2c0000013d00000000010004140000001202000029000000040020008c000010ed0000613d000000440400003900000012020000290000000603000029000110540000003d00001a100000013d000010eb0000c13d000110570000003d00001a930000013d000110590000003d000018e90000013d00000eea0000613d000000000603034f00000000070100190001105e0000003d0000193d0000013d0000105c0000c13d00000eea0000013d0000000b01000029000000000010043f000000a001000039000000200010043f000110660000003d00001a9b0000013d0000000c020000291a9f140d0000040f0000000b010000290001106b0000003d0000195b0000013d0000000d02000029000000000021041b0000000b01000029000110700000003d0000195b0000013d0000000202000367000e0000000203530000004402200370000000000202043b000006cd0020009c00000dd50000213d000110780000003d00001a4a0000013d0000000f02000029000000000021041b0000000e0200035f0000016401200370000000000101043b000f00000001001d000000a401200370000000000201043b000006ce0020009c00000dd50000213d0000000e0100035f0000000401100370000000000401043b000006cd0040009c00000dd50000213d0000000e0100035f0000006401100370000000000601043b000006cd0060009c00000dd50000213d0000000e0100035f0000002401100370000000000701043b000006cd0070009c00000dd50000213d0000000e0100035f0000008401100370000000000501043b0000000f010000291a9f165a0000040f00000002010003670000002402100370000000000602043b000006cd0060009c00000dd50000213d000000a401100370000000000101043b000006ce0010009c00000dd50000213d000000400200043d0000000000120435000006a90020009c000006a90200804100000040012002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d9011001c70000800d020000390000000403000039000006da040000410000000f0500002900000000070000191a9f18c30000040f000000010020019000000dd50000613d0000000201000367000000a402100370000000000202043b000f00000002001d000000110000006b0000118b0000c13d0000000f02000029000006ce0020009c00000dd50000213d0000002401100370000000000101043b001100000001001d0000000f01000029000000010010008c000011a10000c13d0000001101000029000006cd0010009c00000dd50000213d000000400200043d000006d8010000410000000000120435000f00000002001d00000004012000390000001202000029000000000021043500000000010004140000001102000029000000040020008c000010d70000613d0000002404000039000000200600003900000011020000290000000f0300002900000000050300191a9f123c0000040f000000000001004b00000a730000613d000110d90000003d000019790000013d0000000f02000029000011c90000013d000110dd0000003d000019fc0000013d000110df0000003d000019ab0000013d000006ce0010009c000012360000213d0000000100200190000012360000c13d000000400010043f0000000702000029000006d00020009c00000dd50000213d0000000702000029000000200020008c000011270000813d00000dd50000013d000110ed0000003d000019fc0000013d000110ef0000003d000019ab0000013d000006ce0010009c000012360000213d0000000100200190000012360000c13d000000400010043f0000000702000029000006d00020009c000000200300003900000dd50000213d00000020021000390000000e040000290000000000420435000000000031043500000040031000390000000c023000290000000c0000006b000011060000613d0000000b040000290000000204400367000000004504043c0000000003530436000000000023004b000011020000c13d000000020000006b00000000000204350000000002120049000006a90020009c000006a9020080410000006002200210000006a90010009c000006a9010080410000004001100210000000000112019f0000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c70000800d0200003900000002030000390000072b040000410000001205000029000011380000013d0001111d0000003d000019fc0000013d0001111f0000003d000019ab0000013d000006ce0010009c000012360000213d0000000100200190000012360000c13d000000400010043f0000000702000029000006d00020009c00000dd50000213d00000010020000290000000000210435000006a90010009c000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d9011001c70000800d0200003900000004030000390000072c04000041000000120500002900000011060000290000000f070000291a9f18c30000040f000000010020019000000dd50000613d0000000001000415000000050200002900000c280000013d00000012020000290000001f02200039000000200300008a000000000232016f00000064042000390000000c020000290000000d03000029000111470000003d00001a740000013d000000000001004b000011530000c13d00000003040003670001114c0000003d0000192d0000013d00000a7d0000613d000000000704034f0000000008010019000111510000003d00001a360000013d0000114f0000c13d00000a7d0000013d0000001f01200039000000200300008a000000000331016f0000000d01300029000000000031004b00000000030000390000000103004039000006ce0010009c000012360000213d0000000100300190000012360000c13d000000400010043f000006d00020009c00000dd50000213d000000e00200043d000000000002004b0000000002000039000000010200c0390000002003100039000000800400043d000000c00500043d000000a00600043d0000000000230435000006d4026001970000000000210435000006a90010009c000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006f2011001c7000006cd06500197000006cd074001970000800d020000390000000403000039000006f3040000410000000e050000291a9f18c30000040f000000010020019000000dd50000613d00000000010004150000000f0200002900000c280000013d0000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c70000800d02000039000000040300003900000708040000410000095f0000013d0000000f02000029000006ce0020009c00000dd50000213d0000002402100370000000000202043b0000000f03000029000000010030008c000011b00000c13d000006cd0020009c00000dd50000213d000000400500043d000006d60300004100000000003504350000010401100370000000000101043b0001119c0000003d00001a790000013d0000000001000414000000040020008c000011c60000613d0000004404000039000011c00000013d0000001101000029000006cd0010009c00000dd50000213d001800110000002d000111a70000003d000019490000013d000000180440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b000011d80000c13d000000000100001900000000020000191a9f187f0000040f000006cd0020009c00000dd50000213d000000400500043d000006d50300004100000000003504350000010401100370000000000101043b00000044035000390000000f040000290000000000430435000111bc0000003d00001a790000013d0000000001000414000000040020008c000011c60000613d00000064040000390000002006000039000000120300002900000000050300191a9f123c0000040f000000000001004b00000a730000613d000111c80000003d000019790000013d00000012020000290000000002230019000111cc0000003d000019ec0000013d000006ce0020009c000012360000213d0000000100300190000012360000c13d000000400020043f000006d00010009c00000dd50000213d000000200010008c00000dd50000413d0000000001000415000000100200002900000c280000013d000000400300043d00000024013000390000000f020000290000000000210435000006d7010000410000000000130435000f00000003001d00000004013000390000001202000029000000000021043500000000010004140000001102000029000000040020008c000011ec0000613d000000440400003900000011020000290000000f03000029000111eb0000003d0000197e0000013d00000a730000613d000111ee0000003d000019790000013d0000000f02300029000111f10000003d000019ec0000013d000006ce0020009c000012360000213d0000000100300190000012360000c13d000000400020043f000006d00010009c000011d50000a13d00000dd50000013d0000001201000029000006cd0010009c00000dd50000213d001a00120000002d000111ff0000003d000019490000013d0000001a0440008a0000000504400210000006d1020000411a9f18a50000040f000000000001004b000011ad0000613d000000400300043d00000044013000390000000f0200002900000000002104350000002401300039000000400200003900000000002104350000070e010000410000000000130435000000040130003900000010020000290000000000210435001000000003001d00000064013000390000000d021000290000000d0000006b0000121c0000613d0000000b0400035f0000000e03400360000000003403043c0000000001410436000000000021004b000012180000c13d000000110000006b000000000002043500000000010004140000001203000029000000040030008c000012280000613d000000100300002900000000043200490000001202000029000112270000003d0000197e0000013d00000a730000613d0001122a0000003d000019790000013d000000100200002900000000022300190001122e0000003d000019ec0000013d000006ce0020009c000012360000213d0000000100300190000012360000c13d000000400020043f000006d00010009c00000dd50000213d000010340000013d000006f501000041000000000010043f0000004101000039000000040010043f000006f60100004100001aa1000104300003000000000002000300000006001d000200000005001d000006a90030009c000006a9030080410000004003300210000006a90040009c000006a9040080410000006004400210000000000334019f000006a90010009c000006a901008041000000c001100210000000000113019f1a9f18c30000040f00000002090000290000006003100270000006a903300197000000030030006c000000030400002900000000040340190000001f0540018f000007300640019800000000046900190000125a0000613d000000000701034f000000007807043c0000000009890436000000000049004b000012560000c13d000000010220018f000000000005004b0000125f0000613d0001125f0000003d000018f70000013d00001a320000013d0003000000000002000300000006001d000200000005001d000006a90030009c000006a9030080410000004003300210000006a90040009c000006a9040080410000006004400210000000000334019f000006a90010009c000006a901008041000000c001100210000000000113019f1a9f18c80000040f00000002090000290000006003100270000006a903300197000000030030006c000000030400002900000000040340190000001f0540018f000007300640019800000000046900190000127e0000613d000000000701034f000000007807043c0000000009890436000000000049004b0000127a0000c13d000000010220018f000000000005004b000012830000613d000112830000003d000018f70000013d00001a320000013d000006a90030009c000006a9030080410000004003300210000006a90040009c000006a9040080410000006004400210000000000334019f000006a90010009c000006a901008041000000c001100210000000000113019f1a9f18cd0000040f0000006003100270000106a90030019d0003000000010355000000010120018f000000000001042d000000000010043f000000a001000039000019f00000013d000000000010043f000000a101000039000019f00000013d000007310020009c000012cc0000813d00000000040100190000001f01200039000000200600008a000000000161016f0000003f01100039000000000561016f000000400100043d0000000005510019000000000015004b00000000070000390000000107004039000006ce0050009c000012cc0000213d0000000100700190000012cc0000c13d000000400050043f00000000052104360000000007420019000000000037004b000012d20000213d00000000066201700000001f0720018f00000002044003670000000003650019000012bc0000613d000000000804034f0000000009050019000000008a08043c0000000009a90436000000000039004b000012b80000c13d000000000007004b000012c90000613d000000000464034f0000000306700210000000000703043300000000076701cf000000000767022f000000000404043b0000010006600089000000000464022f00000000046401cf000000000474019f000000000043043500000000022500190000000000020435000000000001042d000006f501000041000000000010043f0000004101000039000000040010043f000006f60100004100001aa10001043000001a1c0000013d000006d00010009c000012dd0000213d000000230010008c000012dd0000a13d00000004010000390000000201100367000000000101043b000006cd0010009c000012dd0000213d000000000001042d00001a1c0000013d000006d00010009c000012ea0000213d000000430010008c000012ea0000a13d00000002010003670000002402100370000000000202043b000006cd0020009c000012ea0000213d0000000401100370000000000101043b000000000001042d00001a1c0000013d000006cd02200197000000000020043f000019f00000013d0000003801000039000000000101041a000006cd011001970000000002000411000000000021004b000012f50000c13d000000000001042d000000400100043d000000440210003900000732030000410000000000320435000006dd0200004100000000002104350000002402100039000000200300003900000000003204350000000402100039000000000032043500000064020000391a9f187f0000040f0000000006010019000006cd011001970000003802000039000000000302041a000006de04300197000000000114019f000000000012041b000000400100043d000006a90010009c000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006cd05300197000006d3011001c70000800d0200003900000003030000390000070a040000411a9f18c30000040f00000001002001900000131b0000613d000000000001042d00001a1c0000013d000000000001004b0000131f0000613d000000000001042d000000400100043d00000064021000390000073303000041000000000032043500000044021000390000073403000041000000000032043500000024021000390000002c030000390000000000320435000006dd02000041000019030000013d000000000001004b0000132e0000613d000000000001042d000000400100043d00000064021000390000073503000041000000000032043500000044021000390000073403000041000000000032043500000024021000390000002c030000390000000000320435000006dd02000041000019030000013d000000000001004b0000133d0000613d000000000001042d000000400100043d000000640210003900000736030000410000000000320435000000440210003900000737030000410000000000320435000000240210003900000029030000390000000000320435000006dd02000041000019030000013d00000060021000390000073803000041000000000032043500000040021000390000073903000041000000000032043500000020021000390000002e030000390000000000320435000000200200003900000000002104350000008001100039000000000001042d0003000000000002000200000001001d0001135a0000003d00001a690000013d000006d1020000411a9f18a50000040f000000000001004b000013660000613d0000000201000029000006cd011001970000071502000041000000000302041a000006de03300197000000000113019f000000000012041b000000000001042d000000400100043d00000064021000390000073a03000041000000000032043500000044021000390000073b03000041000000000032043500000024021000390000002d030000390000000000320435000006dd02000041000019030000013d00010000000000020000000102000032000013980000613d000007310020009c0000139a0000813d0000001f01200039000000200300008a000000000131016f0000003f01100039000000000431016f000000400100043d0000000004410019000000000014004b00000000050000390000000105004039000006ce0040009c0000139a0000213d00000001005001900000139a0000c13d000000400040043f000000000621043600000000033201700000001f0420018f00000000023600190000000305000367000013910000613d000000000705034f000000007807043c0000000006860436000000000026004b0000138d0000c13d000000000004004b000013990000613d000000000335034f0000000304400210000113970000003d000018df0000013d000000000001042d0000006001000039000000000001042d000006f501000041000000000010043f0000004101000039000000040010043f000006f60100004100001aa1000104300003000000000002000000000603001900000000050200190000000032030434000000000005004b000013b20000613d000000000002004b000013b00000c13d000113aa0000003d00001a690000013d000006d102000041000200000006001d1a9f18a50000040f0000000206000029000000000001004b000013c20000613d0000000001060019000000000001042d000000000002004b000013c00000c13d000000400300043d000200000003001d000006dd010000410000000000130435000000040130003900000020020000390000000000210435000000240230003900000000010400191a9f13cb0000040f0000000203000029000000000231004900000000010300191a9f187f0000040f000000400100043d00000044021000390000073c03000041000000000032043500000024021000390000001d030000390000000000320435000006dd0200004100001a160000013d0000002004100039000000000301043300000000013204360000000002000019000000000032004b000013d70000813d00000000051200190000000006240019000000000606043300000000006504350000002002200039000013cf0000013d000013da0000a13d000000000213001900000000000204350000001f02300039000000200300008a000000000232016f0000000001210019000000000001042d000000000001004b000013e20000613d000000000001042d000000400100043d00000064021000390000073d03000041000000000032043500000044021000390000073e03000041000000000032043500000024021000390000002b030000390000000000320435000006dd02000041000019030000013d0003000000000002000300000001001d000113f20000003d000018ee0000013d000013f40000613d000000000001042d000000a5050000390000000304000029000000a401000039000000000201041a000006ce0020009c000014070000213d0000000103200039000000000031041b0000073f0220009a000000000042041b000000000101041a000200000001001d000000000040043f000000200050043f000114040000003d00001a9b0000013d0000000202000029000000000021041b000000000001042d000006f501000041000000000010043f0000004101000039000000040010043f000006f60100004100001aa1000104300005000000000002000400000002001d000000000020043f000500000001001d0000000101100039000300000001001d000000200010043f000000400200003900000000010000191a9f18910000040f000000000101041a000000000001004b0000141b0000613d000000000001042d0000000501000029000000000101041a000006ce0010009c000014340000213d000200000001001d00000001011000390000000502000029000000000012041b000000000020043f000000200200003900000000010000191a9f18910000040f00000002011000290000000402000029000000000021041b0000000501000029000000000101041a000500000001001d000000000020043f0000000301000029000114310000003d000018da0000013d0000000502000029000000000021041b000000000001042d000006f501000041000000000010043f0000004101000039000000040010043f000006f60100004100001aa10001043000010000000000020001143d0000003d000019410000013d000000000001004b0000000001000039000000010100c039000000000001042d0001000000000002000006cd01100197000114450000003d000018ee0000013d0000000001000039000000010100c039000000000001042d0000000002010019000000400100043d000007400010009c000014690000813d000000c003100039000000400030043f0000002003100039000000000402041a000000a0054002700000000000530435000006cd0340019700000000003104350000000102200039000000000202041a0000004003100039000006cd0420019700000000004304350000072f002001980000000003000039000000010300c039000000a00410003900000000003404350000072e002001980000000003000039000000010300c039000000800410003900000000003404350000072d002001980000000002000039000000010200c03900000060031000390000000000230435000000000001042d000006f501000041000000000010043f0000004101000039000000040010043f000006f60100004100001aa1000104300000000043010434000006cd0330019700000000033204360000000004040433000006d404400197000000000043043500000040031000390000000003030433000006cd033001970000004004200039000000000034043500000060031000390000000003030433000000000003004b0000000003000039000000010300c0390000006004200039000000000034043500000080031000390000000003030433000000000003004b0000000003000039000000010300c03900000080042000390000000000340435000000a002200039000000a0011000390000000001010433000000000001004b0000000001000039000000010100c0390000000000120435000000000001042d0002000000000002000200000007001d000100000001001d000006cd0750019700000060051000390000000000750435000006a90540019700000040041000390000000000540435000006cd04300197000000200310003900000000004304350000000000210435000000800210003900000000010600191a9f146f0000040f0000000103000029000001400130003900000160020000390000000000210435000001600230003900000002010000291a9f13cb0000040f000000000001042d0002000000000002000100000001001d0000800b0100003900000004030000390000000004000415000000020440008a0000000504400210000006e2020000411a9f18a50000040f000001180010008c00000000020000390000000102006039000001440010008c0000000001000039000000010100603900000000002101a00000074201000041000007410100c0410000000102000029000006cd02200197000000000012004b00000000010000390000000101006039000000000001042d0003000000000002000000000a010019000000400110003900000160090000390000000000910435000006cd013001970000002003a00039000000000013043500000000002a04350000016001a000390000000000510435000007430050009c000014e90000813d0000018001a0003900000005025002120000000005210019000014d60000613d0000000202400367000000002302043c0000000001310436000000000051004b000014d20000c13d000300000008001d000000010000008b0000000000050435000006cd016001970000006002a0003900000000001204350000008002a00039000000000107001900020000000a001d000100000005001d1a9f146f0000040f0000000102000029000000020300002900000000013200490000014003300039000000000013043500000003010000291a9f13cb0000040f000000000001042d00001a1c0000013d000a000000000002000400000006001d00000000070200190000000006010019000000010100003900000080022000390000000002020433000006f802200197000006f804400197000000000042004b000700000006001d000600000007001d000014f90000813d000000000002004b0000152a0000c13d0000000008000415000000090880008a000000050880021000000100027000390000000002020433000006f802200197000006f804500197000000000042004b000015070000813d0000000008000415000000080880008a0000000508800210000000000002004b0000152a0000c13d000300000008001d000500000003001d00000020017000390000000001010433000200000001001d0000800b01000039000000040300003900000000040004150000000a0440008a0000000504400210000006e6020000411a9f18a50000040f0000000202000029000006f802200197000000000012004b0000151a0000a13d00000001010000390000000607000029000015250000013d000000060700002900000040027000390000000002020433000006f802200197000000000021004b00000000010000390000000101002039000000000002004b0000000002000039000000010200c039000000000121016f00000003020000290000000502200270000000000201001f00000007060000290000000503000029000000000001004b000015640000c13d000006f802300198000015640000613d000000e0017000390000000001010433000006f801100197000000000012004b000015350000a13d000000000001004b000015640000c13d000500000002001d000000000060043f000000a8010000390001153a0000003d000019090000013d0000000100100190000015660000c13d00000006040000290000006001400039000000000101043300000120024000390000000002020433000000c00340003900000000030304330000000004040433000006cd07400197000006cd04300197000006f905200197000006cd061001970000000701000029000000050200002900000004030000291a9f165a0000040f00000006010000290000000002010433000000400100043d00000005030000290000000000310435000006a90010009c000006a90100804100000040011002100000000003000414000006a90030009c000006a903008041000000c003300210000000000113019f000006d9011001c7000006cd062001970000800d0200003900000004030000390000000107000039000006da0400004100000007050000291a9f18c30000040f00000001002001900000156a0000613d000000000001042d0000074401000041000015670000013d0000074501000041000000000010043f000006ed0100004100001aa10001043000001a1c0000013d0003000000000002000300000003001d000200000002001d0000000202000367000000000312034f000000000303043b000006ee0030009c000015f90000813d0000002004100039000000000142034f000000000101043b000006cd0010009c000015f90000213d0000002005400039000000000452034f000000000404043b000006cd0040009c000015f90000213d0000002005500039000000000652034f000000000606043b000006cd0060009c000015f90000213d0000004005500039000000000752034f000000000807043b000006ce0080009c000015f90000213d000000a007500039000000000972034f0000008007500039000000000a72034f0000006007500039000000000b72034f0000004007500039000000000c72034f0000002007500039000000000d72034f000000200750008a000000000572034f000000000e05043b000000000d0d043b000000000c0c043b000000000b0b043b000000000a0a043b000000000909043b000000400500043d000001800f50003900000000009f043500000160095000390000000000a9043500000140095000390000000000b9043500000120095000390000000000c9043500000100095000390000000000d90435000000e0095000390000000000890435000000c0085000390000000000e80435000000a008500039000000000068043500000080065000390000000000460435000000600450003900000000001404350000004001500039000000000031043500000020065000390000074601000041000000000016043500000180010000390000000000150435000007470050009c000015fa0000813d000000e001700039000000000112034f000001a007500039000000400070043f000000000101043b00000020020000390000000000270435000001c0035000390000000000130435000007480050009c000015fa0000213d0000020001500039000001e002500039000000400020043f00000000040504330000000005000019000000000045004b000015cf0000813d00000000081500190000000009650019000000000909043300000000009804350000002005500039000015c70000013d0000000005140019000015d20000a13d000000000005043500000000060704330000000007000019000000000067004b000015dc0000813d00000000085700190000000009370019000000000909043300000000009804350000002007700039000015d40000013d000015df0000a13d00000000035600190000000000030435000000000346001900000000003204350000003f03300039000000200400008a000000000443016f0000000003240019000000000043004b00000000040000390000000104004039000006ce0030009c000015fa0000213d0000000100400190000015fa0000c13d000000400030043f00000000020204331a9f18910000040f1a9f18380000040f000100000001001d0000000003000031000000020100002900000003020000291a9f129b0000040f000000000201001900000001010000291a9f16000000040f000000000001042d00001a1c0000013d000006f501000041000000000010043f0000004101000039000000040010043f000006f60100004100001aa1000104300001000000000002000000400300043d0000000045020434000000410050008c000016210000c13d000000400520003900000000050504330000074a0050009c0000162e0000213d0000006002200039000000000202043300000000040404330000006006300039000000000056043500000040053000390000000000450435000000f802200270000000200430003900000000002404350000000000130435000000000000043f000000000100041400000001020000390000008004000039000000200600003900000000050000191a9f12600000040f000000000001004b0000163f0000613d000000000100043d000006cd00100198000016510000613d000000000001042d00000044013000390000074902000041000000000021043500000024013000390000001f020000390000000000210435000006dd01000041000000000013043500000004013000390000002002000039000000000021043500000064020000390000163d0000013d00000064013000390000074c02000041000000000021043500000044013000390000074d020000410000000000210435000000240130003900000022020000390000000000210435000006dd010000410000000000130435000000040130003900000020020000390000000000210435000000840200003900000000010300191a9f187f0000040f0000000304000367000000200100008a000000010200003100000000051201700000001f0620018f000000400100043d00000000035100190000164c0000613d000000000704034f00000000080100190001164b0000003d00001a360000013d000016490000c13d000000000006004b000016500000613d000116500000003d0000190f0000013d1a9f187f0000040f000000400100043d00000044021000390000074b030000410000000000320435000000240210003900000018030000390000000000320435000006dd0200004100001a160000013d000d000000000002000a00000006001d0000000008020019000000aa02000039000000000202041a000006cd06700197000000400b00043d0000008407b0003900000000006704350000002406b0003900000000008604350000074e06000041000000000c6b04360000000406b00039000d00000001001d0000000000160435000900000004001d000006cd094001970000006401b000390000000000910435000006cd033001970000004401b00039000700000003001d00000000003104350000000001000414000006cd02200197000000040020008c000c00000005001d000b00000009001d000016870000613d000000a404000039000000400600003900000000030b001900000000050b0019000800000008001d00060000000b001d00050000000c001d1a9f12600000040f000000050c000029000000060b00002900000008080000290000000b090000290000000c05000029000000000001004b000018050000613d00000001020000310000001f01200039000000200300008a000000000731016f000000000ab7001900000000007a004b00000000010000390000000101004039000006ce00a0009c000017fb0000213d0000000100100190000017fb0000c13d0000004000a0043f000006d00020009c000017fa0000213d0000003f0020008c000017fa0000a13d00000000040c0433000000000004004b0000000001000039000000010100c039000600000004001d000000000014004b000017fa0000c13d000000000c0b0433000000000009004b000000000100001900000000010c6019000500000001001d000000000008004b000000010100008a000016aa0000613d00000000048100d9000000000054004b000017ff0000413d00000000038500a9000000000009004b0000000008000411000027100b000039000017020000613d000000000003004b000017430000613d0000004401a0003900000000003104350000074f0100004100000000001a0435000006cd018001970000000404a0003900000000001404350000000a01000029000006cd061001970000002401a0003900000000006104350000000001000414000000040090008c00080000000c001d000016d40000613d000200000006001d000400000003001d00000064040000390000002006000039000000000209001900000000030a001900030000000a001d00000000050a00191a9f123c0000040f0000000102000031000000000001004b0000181c0000613d0000001f01200039000000200300008a000000000731016f00000000080004110000000403000029000000030a000029000027100b00003900000002060000290000000001a70019000000000071004b00000000040000390000000104004039000006ce0010009c000017fb0000213d0000000100400190000017fb0000c13d000000400010043f000006d00020009c000017fa0000213d000000200020008c000017fa0000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b000017fa0000c13d00000040021000390000000000b20435000000200210003900000000003204350000000000810435000006a90010009c000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f00000750011001c70000800d020000390000000403000039000007510400004100000009050000290000000d070000291a9f18c30000040f0000000008000411000000080c0000290000000b090000290000000c050000290000000100200190000017430000c13d000017fa0000013d000000000113013f00000000001c004b000017ff0000213d00000000013c00190000000002000416000000000021004b000018100000c13d000000000003004b000017430000613d00080000000c001d00000000010004140000000a02000029000006cd04200197000000040040008c000400000003001d000300000004001d000017150000c13d1a9f13720000040f000017280000013d000006a900a0009c000006a90a0080410000004002a00210000006a90010009c000006a901008041000000c001100210000000000121019f000006d3011001c7000080090200003900000000050000191a9f18c30000040f000200000002001d0000006002100270000106a90020019d00030000000103551a9f13720000040f00000002010000290000000100100190000018340000613d000000400100043d00000020021000390000271003000039000000000032043500000004020000290000000000210435000006a90010009c000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006f2011001c70000800d020000390000000303000039000007530400004100000003050000290000000d060000291a9f18c30000040f00000001002001900000000c050000290000000b09000029000000080c0000290000000008000411000017fa0000613d00000000000c004b000017f90000613d000000400700043d000000aa01000039000000000201041a000000000009004b000017590000613d00000044017000390000000000c10435000006cd01200197000000240270003900000000001204350000074f010000410000000000170435000006cd01800197000000040270003900000000001204350000000001000414000000040090008c0000175b0000c13d00000001020000310000176a0000013d000000000a070019000017800000013d00080000000c001d0000006404000039000000200600003900000000020900190000000003070019000400000007001d00000000050700191a9f123c0000040f0000000102000031000000000001004b000018260000613d0000000c050000290000000b09000029000000080c00002900000004070000290000001f01200039000000200300008a000000000131016f000000000a71001900000000001a004b00000000010000390000000101004039000006ce00a0009c000017fb0000213d0000000100100190000017fb0000c13d0000004000a0043f000006d00020009c000017fa0000213d000000200020008c000017fa0000413d00000000010704330001177d0000003d00001a1e0000013d000017fa0000c13d000000aa01000039000000000201041a0000000a01000029000006cd07100197000000c401a0003900000006030000290000000000310435000000a401a00039000000070300002900000000003104350000008401a000390000000000c104350000006401a0003900000000009104350000004401a000390000000000710435000000000005004b000000000100003900000001010060390000002403a000390000000000130435000007540100004100000000001a04350000000401a000390000000d0300002900000000003104350000000001000414000006cd04200197000000040040008c0000179e0000c13d0000000102000031000017d40000013d000b00000007001d0000000503000029000000000003004b000c0000000a001d000017c80000613d000006a900a0009c000006a90200004100000000020a40190000004002200210000006a90010009c000006a901008041000000c001100210000000000121019f00000755011001c7000080090200003900000000050000191a9f18c30000040f0000000c0a00002900000000030200190000006002100270000006a902200197000000200020008c000000200400003900000000040240190000001f0540018f000000200640019000000000046a0019000017c00000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000048004b000017bc0000c13d000000000005004b000017c40000613d000117c40000003d000018f70000013d000000010330018f000100000002001f0003000000010355000017d10000013d0000002006000039000000000204001900000000030a0019000000e40400003900000000050a00191a9f123c0000040f0000000c0a00002900000001020000310000000003010019000000000003004b000018120000613d0000000b070000290000001f01200039000000200300008a000000000331016f0000000001a30019000000000031004b00000000030000390000000103004039000006ce0010009c000017fb0000213d0000000100300190000017fb0000c13d000000400010043f000006d00020009c000017fa0000213d000000200020008c000017fa0000413d00000000020a0433000000000002004b000017f90000613d0000000000210435000006a90010009c000006a90100804100000040011002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d9011001c70000800d02000039000000040300003900000756040000410000000d0500002900000009060000291a9f18c30000040f0000000100200190000017fa0000613d000000000001042d00001a1c0000013d000006f501000041000000000010043f0000004101000039000018020000013d000006f501000041000000000010043f0000001101000039000000040010043f000006f60100004100001aa10001043000000003040003670000000102000031000118090000003d0000192d0000013d0000182f0000613d000000000704034f00000000080100190001180e0000003d00001a360000013d0000180c0000c13d0000182f0000013d0000075201000041000018350000013d0000000304000367000118150000003d0000192d0000013d0000182f0000613d000000000704034f00000000080100190001181a0000003d00001a360000013d000018180000c13d0000182f0000013d00000003040003670001181f0000003d0000192d0000013d0000182f0000613d000000000704034f0000000008010019000118240000003d00001a360000013d000018220000c13d0000182f0000013d0000000304000367000118290000003d0000192d0000013d0000182f0000613d000000000704034f00000000080100190001182e0000003d00001a360000013d0000182c0000c13d000000000006004b000018330000613d000118330000003d0000190f0000013d1a9f187f0000040f000006fd01000041000000000010043f000006ed0100004100001aa1000104300003000000000002000100000001001d0000000201000039000000000101041a000200000001001d0000800b0100003900000004030000390000000004000415000000030440008a0000000504400210000006e2020000411a9f18a50000040f000000400200043d000000020010006c0000184b0000c13d0000000101000039000000000101041a0000000004020019000018660000013d0000000503000039000000000303041a0000000304000039000000000404041a0000000405000039000000000505041a000000a0062000390000000007000410000000000076043500000080062000390000000000160435000000600120003900000000005104350000004001200039000000000041043500000020012000390000000000310435000000a0030000390000000000320435000007400020009c000018780000813d000000c003200039000200000003001d000000400030043f00000000020204331a9f18910000040f00000002040000290000004202400039000000010300002900000000003204350000002003400039000007570200004100000000002304350000002202400039000000000012043500000042010000390000000000140435000006ea0040009c000018780000213d0000008001400039000000400010043f000000000204043300000000010300191a9f18910000040f000000000001042d000006f501000041000000000010043f0000004101000039000000040010043f000006f60100004100001aa100010430000000000001042f000006a90010009c000006a9010080410000004001100210000006a90020009c000006a9020080410000006002200210000000000112019f00001aa100010430000006a90010009c000006a9010080410000004001100210000006a90020009c000006a9020080410000006002200210000000000112019f000000e002300210000000000121019f00001aa00001042e000006a90010009c000006a9010080410000004001100210000006a90020009c000006a9020080410000006002200210000000000112019f0000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f000006d3011001c700008010020000391a9f18c80000040f0000000100200190000018a40000613d000000000101043b000000000001042d00001a1c0000013d00000000050100190000000000200443000000050030008c000018b30000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b000018ab0000413d000006a90030009c000006a90300804100000060013002100000000002000414000006a90020009c000006a902008041000000c002200210000000000112019f00000758011001c700000000020500191a9f18c80000040f0000000100200190000018c20000613d000000000101043b000000000001042d000000000001042f000018c6002104210000000102000039000000000001042d0000000002000019000000000001042d000018cb002104230000000102000039000000000001042d0000000002000019000000000001042d000018d0002104250000000102000039000000000001042d0000000002000019000000000001042d0000001201000029000000000010043f000000a701000039000000200010043f000000400200003900000000010000191a9f18910000040f000000010000013b000000200010043f000000400200003900000000010000191a9f18910000040f000000010000013b000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000010000013b00000000041201700000001f0520018f000000400100043d0000000002410019000000010000013b000000000010043f000000a501000039000000200010043f000000400200003900000000010000191a9f18910000040f000000000101041a000000000001004b000000010000013b000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000000010000013b000000000021043500000004021000390000002003000039000000000032043500000084020000391a9f187f0000040f000000200010043f000000400200003900000000010000191a9f18910000040f000000000101041a000000010000013b000000000454034f0000000305600210000000000603043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000430435000000010000013b1a9f18a50000040f0000000202000039000000000012041b0000000003000410000000400200043d000000a00420003900000000003404350000008003200039000000000013043500000060012000390000000c030000290000000000310435000000400120003900000012030000290000000000310435000000a0010000390000000001120436000000010000013b000000200100008a00000000051201700000001f0620018f000000400100043d0000000003510019000000010000013b0000001201000029000000000010043f000000a701000039000000200010043f000000400200003900000000010000191a9f18910000040f0000000d02000029000000a002200210000000010000013b000000006806043c0000000007870436000000000027004b000000010000013b000000000020043f0000000101100039000000200010043f000000400200003900000000010000191a9f18910000040f000000000101041a000000010000013b000080020100003900000024030000390000000004000415000000010000013b0000000001000412002500000001001d002400000000003d000080050100003900000044030000390000000004000415000000250440008a0000000504400210000000010000013b00000001010000310000001f02100039000000200300008a000000000232016f000000010000013b000000000010043f000000a101000039000000200010043f000000000100001900000040020000391a9f18910000040f000000010000013b000000000020043f0000000101100039000000200010043f000000000100001900000040020000391a9f18910000040f000000000101041a000000000001004b000000010000013b0000001201000029000000000010043f000000a801000039000000200010043f000000400200003900000000010000191a9f18910000040f000000100700002900000080027002100000001106000029000000000262019f000000000021041b0000000f01000029000000010000013b00000001010000310000001f02100039000000200300008a000000000332016f000000010000013b000000000503001900000000060000191a9f123c0000040f000000000001004b000000010000013b00000020060000390000001202000029000000060300002900000000050300191a9f123c0000040f0007000100000035000000000001004b000000010000013b00000020060000390000000b020000290000000f0300002900000000050300191a9f123c0000040f000d000100000035000000000001004b000000010000013b0000001201000029000000000010043f000000a901000039000000200010043f000000400200003900000000010000191a9f18910000040f1a9f14480000040f000000a0021000390000000002020433000000000002004b000000010000013b1a9f18910000040f00000003020000390000001203000029000000000032041b000c00000001001d0000000403000039000000000013041b0000800b010000390000000004000415000000250440008a0000000504400210000000010000013b00000004020000290000000601200029000000000021004b00000000020000390000000102004039000000010000013b1a9f13df0000040f00000000010004111a9f13020000040f00000011010000291a9f13020000040f0000000f010000291a9f13ee0000040f000000a6010000390000000e02000029000000000021041b000000010000013b0000000001310049000000200210008a00000000002304350000001f01100039000000200200008a000000000121016f0000000002310019000000000012004b00000000010000390000000101004039000000010000013b000000040210003900000000022f034f000000000202043b000000240110003900000000030400191a9f129b0000040f000000010000013b000000600350003900000060040000390000000000430435000000200350003900000000002304350000006001100270000000400250003900000000001204350000008002500039000000010000013b000000040400003900000080030000390000002006000039000f00000002001d0000000f0200002900000000050300191a9f12600000040f0000000f02000029000000000001004b000000010000013b0000001201000029000000000010043f000000a701000039000000200010043f000000400200003900000000010000191a9f18910000040f0000000d02000029000000d002200210000000010000013b000000000032004b00000000030000390000000103004039000000010000013b000000200010043f000000400200003900000000010000191a9f18910000040f000000000001042d000000000010043f000000a101000039000000200010043f000000400200003900000000010000191a9f18910000040f000000010000013b00000007010000290000001f01100039000000200200008a0004000000210173000000010000013b0000800b0100003900000004030000390000000004000415000000250440008a0000000504400210000000010000013b0000000001000031000000200210008a0000000202200367000000480110008a0000000201100367000000000101043b000000000202043b000000400500043d000000010000013b000000000503001900000000060000191a9f123c0000040f0007000100000035000000000001004b000000010000013b000000000021043500000004021000390000002003000039000000000032043500000064020000391a9f187f0000040f000000000100001900001aa100010430000000000001004b0000000002000039000000010200c039000000000021004b000000010000013b0000000d010000290000001f01100039000000200200008a000000000221016f0000000f01200029000000000021004b00000000020000390000000102004039000000010000013b00000006020000290000000000120435000000080100002900000009020000290000000000120435000000010000013b000100000003001f00030000000103550000000001020019000000000001042d000000007907043c0000000008980436000000000038004b000000010000013b000000000405001900000000050000191a9f18c30000040f000000000301034f000000010120018f00030000000303550000006002300270000000010000013b000000000010043f000000a001000039000000200010043f000000400200003900000000010000191a9f18910000040f000000120200035f000000010000013b000000000020043f0000000101100039000000200010043f000000400200003900000000010000191a9f18910000040f0000000003000411000000010000013b00000000001204350000000401200039000000120200002900000011030000290000000f0400002900000010050000290000000b07000029000000010000013b0000001f01100039000000200200008a000000000121016f000000010000013b00000012050000291a9f18c30000040f0000000100200190000000010000013b000000000100003900000001010060391a9f133a0000040f00000012010000291a9f13560000040f000000400100043d000000010000013b000300000001001d000080020100003900000024030000390000000004000415000000030440008a0000000504400210000000010000013b00000000050300191a9f12600000040f000000000001004b000000010000013b000000000503001900000000060000191a9f123c0000040f0000000102000031000000010000013b000000240350003900000012040000290000000000430435001200000005001d00000004035000390000000000130435000000010000013b000000000101043b001200000001001d000000000105043b001100000001001d000000010000013b0000001002000029000000000020043f000000200010043f000000000100001900000040020000391a9f18910000040f000000010000013b000000000012043500000004012000390000001202000029000000110300002900000010040000290000000c06000029000000010000013b0000000303000367000000200100008a0000000702000029000000010000013b0000000303000367000000200100008a0000000d02000029000000010000013b000000400200003900000000010000191a9f18910000040f000000010000013b00001a9f0000043200001aa00001042e00001aa1000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff000000020000000000000000000000000000008000000100000000000000000000000000000000000000000000000000000000000000000000000000fc2c99710000000000000000000000000000000000000000000000000000000006056f83000000000000000000000000000000000000000000000000000000000dbb18a1000000000000000000000000000000000000000000000000000000001d9165aa0000000000000000000000000000000000000000000000000000000023bc2078000000000000000000000000000000000000000000000000000000002cf9adc8000000000000000000000000000000000000000000000000000000003659cfe6000000000000000000000000000000000000000000000000000000003716e28400000000000000000000000000000000000000000000000000000000391a6d28000000000000000000000000000000000000000000000000000000004f1ef2860000000000000000000000000000000000000000000000000000000052169be80000000000000000000000000000000000000000000000000000000052d1902d00000000000000000000000000000000000000000000000000000000532742460000000000000000000000000000000000000000000000000000000056292ab500000000000000000000000000000000000000000000000000000000572b6c0500000000000000000000000000000000000000000000000000000000619b8589000000000000000000000000000000000000000000000000000000006c1b7abd00000000000000000000000000000000000000000000000000000000715018a60000000000000000000000000000000000000000000000000000000077a856ea000000000000000000000000000000000000000000000000000000007ced595c000000000000000000000000000000000000000000000000000000007e5811fc000000000000000000000000000000000000000000000000000000008a320d64000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000009e2dc50000000000000000000000000000000000000000000000000000000000a0f7652300000000000000000000000000000000000000000000000000000000b052d17c00000000000000000000000000000000000000000000000000000000b414ae2f00000000000000000000000000000000000000000000000000000000c462507e00000000000000000000000000000000000000000000000000000000e28be14400000000000000000000000000000000000000000000000000000000e2f66b1e00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000f4a4034500000000000000000000000000000000000000000000000000000000f7013ef60000000000000000000000000000000000000000000000000000000004105018000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff9690ca56000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b839cc163e50000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff1b30808d00000000000000000000000000000000000000000000000000000000b859c935000000000000000000000000000000000000000000000000000000005be9544800000000000000000000000000000000000000000000000000000000184a94d5000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000020000000000000000000000000981414aed4973b05aa301314dc13a5a4077f24490497b98bc270852581c1c578647920696e697469616c697a6564000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320616c72656108c379a000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf4d696e744d616e61676572000000000000000000000000000000000000000000312e302e300000000000000000000000000000000000000000000000000000009a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f000000000000000000000000000000000000000000000000ffffffffffffff3f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d9553913264647265737300000000000000000000000000000000000000000000000000004f776e61626c653a206e6577206f776e657220697320746865207a65726f20610100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f8da5cb5b000000000000000000000000000000000000000000000000000000009419d6f40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000010000000000000000000000000000000000000000ffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000001a8d37920000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000400000000000000000000000006ec667d7188a57a345b217226db199b2b1e98d2ccdb2eaa555af7ad1932430371bcb23ca25f7b3072817e7997715d2534ac248ffc2bd850c540cae4262f5b1744e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000040f3a16b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff00ff00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0200000000000000000000000000000000000000000000800000000000000000f9ad387200000000000000000000000000000000000000000000000000000000875fc25f00000000000000000000000000000000000000000000000000000000ffffffffffff000000000000ffffffffffffffffffffffffffffffffffffffff000000000000ffffffffffff0000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffff000000000000ffffffffffffffffffffffffffffffffffffffffffffffff0000ffffffffffff000000000000000000000000000000000000000000000000ff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00010000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa712e8b25b3d4d043988e80f0a4087773b1c7e29e4115a4256e86aebe91c9be97258df9bfe0a9fb9cf1285396575e6472f56ca38b4851afcb725c82726fd67ff8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0af2a8dc7de0e027b17ddbe873c600be814993ef395f58475bc9ef0408f7ccf16000000000000000000000000000000000000000000000000fffffffffffffe5fe0bf8a4af82e2af496af5f4957e2767f8b52e51a77caedd2f30a1843872d1b7c6371fbe7000000000000000000000000000000000000000000000000000000000d640e8100000000000000000000000000000000000000000000000000000000ed3c247c0000000000000000000000000000000000000000000000000000000043d0477700000000000000000000000000000000000000000000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e555550535570677261646561626c653a206d757374206e6f742062652063616c6c6564207468726f7567682064656c656761746563616c6c0000000000000000360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff0000000000000000000100000000000000000000000000000000000000000000a5a0d9b368dd777972caaaa919c8ca3243792928d90f1b032a1bab6b243a73ab4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd914352d1902d00000000000000000000000000000000000000000000000000000000bc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b000000000000000000000000000000000000000000000000ffffffffffffff9f206661696c656400000000000000000000000000000000000000000000000000416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c00000000000000000000000000000000ffffffffffffffffffffffffffffffffaaca5cb46300e4b20595b143bc883119e775ef88ff77f45fa989ca323576f06b000000000000000000000000000000000000000000000000ffffffffffffffdfe772ce44f6b7edf20d62f174efc62c5a18484d62a710bd48d57af1afd140811c000000000000000000000000000000000000000000000000fffffffffffffe3fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000dfa4c86400000000000000000000000000000000000000000000000000000000c4804ce200000000000000000000000000000000000000000000000000000000207226af00000000000000000000000000000000000000000000000000000000ac3274ef00000000000000000000000000000000000000000000000000000000efb5e1bc0000000000000000000000000000000000000000000000000000000082b42900000000000000000000000000000000000000000000000000000000004e84cd8521d66b0c0a2d95e21910942e1616948e140df953825b0cb02c32a5e94c0491da007181c9465d71c51f64ba4f8eb23133900a4bb2dae027b0c2252c3f0000000000000000000000ff000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffe000000000000000000000000000000000000000000000000100000000000000004f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657264656c656761746563616c6c000000000000000000000000000000000000000046756e6374696f6e206d7573742062652063616c6c6564207468726f756768206163746976652070726f787900000000000000000000000000000000000000006961626c6555554944000000000000000000000000000000000000000000000045524331393637557067726164653a20756e737570706f727465642070726f786f6e206973206e6f74205555505300000000000000000000000000000000000045524331393637557067726164653a206e657720696d706c656d656e746174696f74206120636f6e747261637400000000000000000000000000000000000000455243313936373a206e657720696d706c656d656e746174696f6e206973206e416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006e697469616c697a696e67000000000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e7472616374206973206e6f7420691bcb23ca25f7b3072817e7997715d2534ac248ffc2bd850c540cae4262f5b173000000000000000000000000000000000000000000000000ffffffffffffff40000000000000000000000000b16a1dbe755f992636705fdbb3a8678a657eb3ea000000000000000000000000abcc9b596420a9e9172fd5938620e265a0f9df9208000000000000000000000000000000000000000000000000000000000000001cae1b7c00000000000000000000000000000000000000000000000000000000d7d248ba0000000000000000000000000000000000000000000000000000000075d70c323d802883252e6285d4bb7cc6fcb7faca7fe3ab1d9e9f260aaa4c3424000000000000000000000000000000000000000000000000fffffffffffffe60000000000000000000000000000000000000000000000000fffffffffffffe1f45434453413a20696e76616c6964207369676e6174757265206c656e677468007fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a045434453413a20696e76616c6964207369676e61747572650000000000000000756500000000000000000000000000000000000000000000000000000000000045434453413a20696e76616c6964207369676e6174757265202773272076616c76c198930000000000000000000000000000000000000000000000000000000023b872dd000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000060000000000000000000000000c899cbcc4511003ff90131e8b89605738e9a7f4925273377ae479a673cf5038cfc512fde000000000000000000000000000000000000000000000000000000009363885e28e7ba67b096932f9f00dff44742731d6cb4fa26ccd4424e78e41e136f18e93f0000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000e400000000000000000000000027dcd1d67ca97c55aa198d8494458949bbbddae9336ef0969fc655edb5d2180a190100000000000000000000000000000000000000000000000000000000000002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1cdfc074d29b02d11406b3f3088ca4843bf2b0c0b7767b8edd6b7821829c62e
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.