Overview
APE Balance
APE Value
$0.00More Info
Private Name Tags
ContractCreator
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:
DiscreteDutchAuctionMechanic
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
Yes with 1 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "./MechanicMintManagerClientUpgradeable.sol"; import "../../erc721/interfaces/IEditionCollection.sol"; import "../../erc721/interfaces/IERC721GeneralSupplyMetadata.sol"; import "./PackedPrices.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; /** * @notice Highlight's bespoke Dutch Auction mint mechanic (rebates, discrete prices, not continuous) * @dev Processes ether based auctions only * DPP = Dynamic Price Period * FPP = Fixed Price Period * @author highlight.xyz */ contract DiscreteDutchAuctionMechanic is MechanicMintManagerClientUpgradeable, UUPSUpgradeable { using EnumerableSet for EnumerableSet.Bytes32Set; /** * @notice Throw when an action is unauthorized */ error Unauthorized(); /** * @notice Throw when a vector is attempted to be created or updated with an invalid configuration */ error InvalidVectorConfig(); /** * @notice Throw when a vector is attempted to be updated or deleted at an invalid time */ error InvalidUpdate(); /** * @notice Throw when a vector is already created with a mechanic vector ID */ error VectorAlreadyCreated(); /** * @notice Throw when it is invalid to mint on a vector */ error InvalidMint(); /** * @notice Throw when it is invalid to withdraw funds from a DPP */ error InvalidDPPFundsWithdrawl(); /** * @notice Throw when it is invalid to collect a rebate */ error InvalidRebate(); /** * @notice Throw when a collector isn't owed any rebates */ error CollectorNotOwedRebate(); /** * @notice Throw when the contract fails to send ether to a payment recipient */ error EtherSendFailed(); /** * @notice Throw when the transaction sender has sent an invalid payment amount during a mint */ error InvalidPaymentAmount(); /** * @notice Vector data * @dev Guiding uint typing: * log(periodDuration) <= log(timestamps) * log(numTokensBought) <= log(maxUser) * log(numToMint) <= log(numTokensBought) * log(maxUser) <= log(maxTotal) * log(lowestPriceSoldAtIndex) < log(numPrices) * log(prices[i]) <= log(totalSales) * log(totalPosted) <= log(totalSales) * log(prices[i]) <= log(totalPosted) * log(numTokensbought) + log(totalPosted) <= 256 */ struct DutchAuctionVector { // slot 0 uint48 startTimestamp; uint48 endTimestamp; uint32 periodDuration; uint32 maxUserClaimableViaVector; uint48 maxTotalClaimableViaVector; uint48 currentSupply; // slot 1 uint32 lowestPriceSoldAtIndex; uint32 tokenLimitPerTx; uint32 numPrices; address payable paymentRecipient; // slot 2 uint240 totalSales; uint8 bytesPerPrice; bool auctionExhausted; bool payeeRevenueHasBeenWithdrawn; } /** * @notice Config used to control updating of fields in DutchAuctionVector */ struct DutchAuctionVectorUpdateConfig { bool updateStartTimestamp; bool updateEndTimestamp; bool updatePeriodDuration; bool updateMaxUserClaimableViaVector; bool updateMaxTotalClaimableViaVector; bool updateTokenLimitPerTx; bool updatePaymentRecipient; bool updatePrices; } /** * @notice User purchase info per dutch auction per user * @param numTokensBought Number of tokens bought in the dutch auction * @param numRebates Number of times the user has requested a rebate * @param totalPosted Total amount paid by buyer minus rebates sent */ struct UserPurchaseInfo { uint32 numTokensBought; uint24 numRebates; uint200 totalPosted; } /** * @notice Stores dutch auctions, indexed by global mechanic vector id */ mapping(bytes32 => DutchAuctionVector) private vector; /** * @notice Stores dutch auction prices (packed), indexed by global mechanic vector id */ mapping(bytes32 => bytes) private vectorPackedPrices; /** * @notice Stores user purchase info, per user per auction */ mapping(bytes32 => mapping(address => UserPurchaseInfo)) public userPurchaseInfo; /** * @notice Emitted when a dutch auction is created */ event DiscreteDutchAuctionCreated(bytes32 indexed mechanicVectorId); /** * @notice Emitted when a dutch auction is updated */ event DiscreteDutchAuctionUpdated(bytes32 indexed mechanicVectorId); /** * @notice Emitted when a number of tokens are minted via a dutch auction */ event DiscreteDutchAuctionMint( bytes32 indexed mechanicVectorId, address indexed recipient, uint200 pricePerToken, uint48 numMinted ); /** * @notice Emitted when a collector receives a rebate * @param mechanicVectorId Mechanic vector ID * @param collector Collector receiving rebate * @param rebate The amount of ETH returned to the collector * @param currentPricePerNft The current price per NFT at the time of rebate */ event DiscreteDutchAuctionCollectorRebate( bytes32 indexed mechanicVectorId, address indexed collector, uint200 rebate, uint200 currentPricePerNft ); /** * @notice Emitted when the DPP revenue is withdrawn to the payment recipient once the auction hits the FPP. * @dev NOTE - amount of funds withdrawn may include sales from the FPP. After funds are withdrawn, payment goes * straight to the payment recipient on mint * @param mechanicVectorId Mechanic vector ID * @param paymentRecipient Payment recipient at time of withdrawal * @param clearingPrice The final clearing price per NFT * @param currentSupply The number of minted tokens to withdraw sales for */ event DiscreteDutchAuctionDPPFundsWithdrawn( bytes32 indexed mechanicVectorId, address indexed paymentRecipient, uint200 clearingPrice, uint48 currentSupply ); /** * @notice Initialize mechanic contract * @param _mintManager Mint manager address * @param platform Platform owning the contract */ function initialize(address _mintManager, address platform) external initializer { __MechanicMintManagerClientUpgradeable_initialize(_mintManager, platform); } /** * @notice Create a dutch auction vector * @param mechanicVectorId Global mechanic vector ID * @param vectorData Vector data, to be deserialized into dutch auction vector data */ function createVector(bytes32 mechanicVectorId, bytes memory vectorData) external onlyMintManager { // precaution, although MintManager tightly controls creation and prevents double creation if (vector[mechanicVectorId].periodDuration != 0) { _revert(VectorAlreadyCreated.selector); } ( uint48 startTimestamp, uint48 endTimestamp, uint32 periodDuration, uint32 maxUserClaimableViaVector, uint48 maxTotalClaimableViaVector, uint32 tokenLimitPerTx, uint32 numPrices, uint8 bytesPerPrice, address paymentRecipient, bytes memory packedPrices ) = abi.decode(vectorData, (uint48, uint48, uint32, uint32, uint48, uint32, uint32, uint8, address, bytes)); DutchAuctionVector memory _vector = DutchAuctionVector( startTimestamp == 0 ? uint48(block.timestamp) : startTimestamp, endTimestamp, periodDuration, maxUserClaimableViaVector, maxTotalClaimableViaVector, 0, 0, tokenLimitPerTx, numPrices, payable(paymentRecipient), 0, bytesPerPrice, false, false ); _validateVectorConfig(_vector, packedPrices, true); vector[mechanicVectorId] = _vector; vectorPackedPrices[mechanicVectorId] = packedPrices; emit DiscreteDutchAuctionCreated(mechanicVectorId); } /* solhint-disable code-complexity */ /** * @notice Update a dutch auction vector * @param mechanicVectorId Global mechanic vector ID * @param newVector New vector fields * @param updateConfig Config denoting what fields on vector to update */ function updateVector( bytes32 mechanicVectorId, DutchAuctionVector calldata newVector, bytes calldata newPackedPrices, DutchAuctionVectorUpdateConfig calldata updateConfig ) external { MechanicVectorMetadata memory metadata = _getMechanicVectorMetadata(mechanicVectorId); if ( metadata.contractAddress != msg.sender && OwnableUpgradeable(metadata.contractAddress).owner() != msg.sender ) { _revert(Unauthorized.selector); } DutchAuctionVector memory currentVector = vector[mechanicVectorId]; // after first token has been minted, cannot update: prices, period, start time, max total claimable via vector if ( currentVector.currentSupply > 0 && (updateConfig.updatePrices || updateConfig.updatePeriodDuration || updateConfig.updateStartTimestamp || updateConfig.updateMaxTotalClaimableViaVector) ) { _revert(InvalidUpdate.selector); } // construct end state of vector with updates applied, then validate if (updateConfig.updateStartTimestamp) { currentVector.startTimestamp = newVector.startTimestamp == 0 ? uint48(block.timestamp) : newVector.startTimestamp; } if (updateConfig.updateEndTimestamp) { currentVector.endTimestamp = newVector.endTimestamp; } if (updateConfig.updatePeriodDuration) { currentVector.periodDuration = newVector.periodDuration; } if (updateConfig.updateMaxUserClaimableViaVector) { currentVector.maxUserClaimableViaVector = newVector.maxUserClaimableViaVector; } if (updateConfig.updateMaxTotalClaimableViaVector) { currentVector.maxTotalClaimableViaVector = newVector.maxTotalClaimableViaVector; } if (updateConfig.updateTokenLimitPerTx) { currentVector.tokenLimitPerTx = newVector.tokenLimitPerTx; } if (updateConfig.updatePaymentRecipient) { currentVector.paymentRecipient = newVector.paymentRecipient; } if (updateConfig.updatePrices) { currentVector.bytesPerPrice = newVector.bytesPerPrice; currentVector.numPrices = newVector.numPrices; } _validateVectorConfig(currentVector, newPackedPrices, updateConfig.updatePrices); // rather than updating entire vector, update per-field if (updateConfig.updateStartTimestamp) { vector[mechanicVectorId].startTimestamp = currentVector.startTimestamp; } if (updateConfig.updateEndTimestamp) { vector[mechanicVectorId].endTimestamp = currentVector.endTimestamp; } if (updateConfig.updatePeriodDuration) { vector[mechanicVectorId].periodDuration = currentVector.periodDuration; } if (updateConfig.updateMaxUserClaimableViaVector) { vector[mechanicVectorId].maxUserClaimableViaVector = currentVector.maxUserClaimableViaVector; } if (updateConfig.updateMaxTotalClaimableViaVector) { vector[mechanicVectorId].maxTotalClaimableViaVector = currentVector.maxTotalClaimableViaVector; } if (updateConfig.updateTokenLimitPerTx) { vector[mechanicVectorId].tokenLimitPerTx = currentVector.tokenLimitPerTx; } if (updateConfig.updatePaymentRecipient) { vector[mechanicVectorId].paymentRecipient = currentVector.paymentRecipient; } if (updateConfig.updatePrices) { vectorPackedPrices[mechanicVectorId] = newPackedPrices; vector[mechanicVectorId].bytesPerPrice = currentVector.bytesPerPrice; vector[mechanicVectorId].numPrices = currentVector.numPrices; } emit DiscreteDutchAuctionUpdated(mechanicVectorId); } /* solhint-enable code-complexity */ /** * @notice See {IMechanic-processNumMint} */ function processNumMint( bytes32 mechanicVectorId, address recipient, uint32 numToMint, address minter, MechanicVectorMetadata calldata mechanicVectorMetadata, bytes calldata data ) external payable onlyMintManager { _processMint(mechanicVectorId, recipient, numToMint); } /** * @notice See {IMechanic-processChooseMint} */ function processChooseMint( bytes32 mechanicVectorId, address recipient, uint256[] calldata tokenIds, address minter, MechanicVectorMetadata calldata mechanicVectorMetadata, bytes calldata data ) external payable onlyMintManager { _processMint(mechanicVectorId, recipient, uint32(tokenIds.length)); } /** * @notice Rebate a collector any rebates they're eligible for * @param mechanicVectorId Mechanic vector ID * @param collector Collector to send rebates to */ function rebateCollector(bytes32 mechanicVectorId, address payable collector) external { DutchAuctionVector memory _vector = vector[mechanicVectorId]; UserPurchaseInfo memory _userPurchaseInfo = userPurchaseInfo[mechanicVectorId][collector]; if (_vector.currentSupply == 0) { _revert(InvalidRebate.selector); } bool _auctionExhausted = _vector.auctionExhausted; if (!_auctionExhausted) { _auctionExhausted = _isAuctionExhausted( mechanicVectorId, _vector.currentSupply, _vector.maxTotalClaimableViaVector ); if (_auctionExhausted) { vector[mechanicVectorId].auctionExhausted = true; } } // rebate collector at the price: // - lowest price sold at if auction is exhausted (vector sold out or collection sold out) // - current price otherwise uint200 currentPrice = PackedPrices.priceAt( vectorPackedPrices[mechanicVectorId], _vector.bytesPerPrice, _auctionExhausted ? _vector.lowestPriceSoldAtIndex : _calculatePriceIndex(_vector.startTimestamp, _vector.periodDuration, _vector.numPrices) ); uint200 currentPriceObligation = _userPurchaseInfo.numTokensBought * currentPrice; uint200 amountOwed = _userPurchaseInfo.totalPosted - currentPriceObligation; if (amountOwed == 0) { _revert(CollectorNotOwedRebate.selector); } userPurchaseInfo[mechanicVectorId][collector].totalPosted = currentPriceObligation; userPurchaseInfo[mechanicVectorId][collector].numRebates = _userPurchaseInfo.numRebates + 1; (bool sentToCollector, bytes memory data) = collector.call{ value: amountOwed }(""); if (!sentToCollector) { _revert(EtherSendFailed.selector); } emit DiscreteDutchAuctionCollectorRebate(mechanicVectorId, collector, amountOwed, currentPrice); } /** * @notice Withdraw funds collected through the dynamic period of a dutch auction * @param mechanicVectorId Mechanic vector ID */ function withdrawDPPFunds(bytes32 mechanicVectorId) external { // all slots are used, so load entire object from storage DutchAuctionVector memory _vector = vector[mechanicVectorId]; if (_vector.payeeRevenueHasBeenWithdrawn || _vector.currentSupply == 0) { _revert(InvalidDPPFundsWithdrawl.selector); } bool _auctionExhausted = _vector.auctionExhausted; if (!_auctionExhausted) { _auctionExhausted = _isAuctionExhausted( mechanicVectorId, _vector.currentSupply, _vector.maxTotalClaimableViaVector ); if (_auctionExhausted) { vector[mechanicVectorId].auctionExhausted = true; } } uint32 priceIndex = _auctionExhausted ? _vector.lowestPriceSoldAtIndex : _calculatePriceIndex(_vector.startTimestamp, _vector.periodDuration, _vector.numPrices); // if any of the following 3 are met, DPP funds can be withdrawn: // - auction is in FPP // - maxTotalClaimableViaVector is reached // - all tokens have been minted on collection (outside of vector knowledge) if (!_auctionExhausted && !_auctionIsInFPP(_vector.currentSupply, priceIndex, _vector.numPrices)) { _revert(InvalidDPPFundsWithdrawl.selector); } vector[mechanicVectorId].payeeRevenueHasBeenWithdrawn = true; uint200 clearingPrice = PackedPrices.priceAt( vectorPackedPrices[mechanicVectorId], _vector.bytesPerPrice, priceIndex ); uint200 totalRefund = _vector.currentSupply * clearingPrice; // precaution: protect against pulling out more than total sales -> // guards against bad actor pulling out more via // funds collection + rebate price ascending setup (theoretically not possible) if (totalRefund > _vector.totalSales) { _revert(InvalidDPPFundsWithdrawl.selector); } uint200 platformFee = (totalRefund * 500) / 10000; (bool sentToPaymentRecipient, ) = _vector.paymentRecipient.call{ value: totalRefund - platformFee }(""); if (!sentToPaymentRecipient) { _revert(EtherSendFailed.selector); } (bool sentToPlatform, ) = (payable(owner())).call{ value: platformFee }(""); if (!sentToPlatform) { _revert(EtherSendFailed.selector); } emit DiscreteDutchAuctionDPPFundsWithdrawn( mechanicVectorId, _vector.paymentRecipient, clearingPrice, _vector.currentSupply ); } /** * @notice Get how much of a rebate a user is owed * @param mechanicVectorId Mechanic vector ID * @param user User to get rebate information for */ function getUserInfo( bytes32 mechanicVectorId, address user ) external view returns (uint256 rebate, UserPurchaseInfo memory) { DutchAuctionVector memory _vector = vector[mechanicVectorId]; UserPurchaseInfo memory _userPurchaseInfo = userPurchaseInfo[mechanicVectorId][user]; if (_vector.currentSupply == 0) { return (0, _userPurchaseInfo); } // rebate collector at the price: // - lowest price sold at if vector is sold out or collection is sold out // - current price otherwise uint200 currentPrice = PackedPrices.priceAt( vectorPackedPrices[mechanicVectorId], _vector.bytesPerPrice, _isAuctionExhausted(mechanicVectorId, _vector.currentSupply, _vector.maxTotalClaimableViaVector) ? _vector.lowestPriceSoldAtIndex : _calculatePriceIndex(_vector.startTimestamp, _vector.periodDuration, _vector.numPrices) ); uint200 currentPriceObligation = _userPurchaseInfo.numTokensBought * currentPrice; uint256 amountOwed = uint256(_userPurchaseInfo.totalPosted - currentPriceObligation); return (amountOwed, _userPurchaseInfo); } /** * @notice Get how much is owed to the payment recipient (currently) * @param mechanicVectorId Mechanic vector ID * @param escrowFunds Amount owed to the creator currently * @param amountFinalized Whether this is the actual amount that will be owed (will decrease until the auction ends) */ function getPayeePotentialEscrowedFunds( bytes32 mechanicVectorId ) external view returns (uint256 escrowFunds, bool amountFinalized) { return _getPayeePotentialEscrowedFunds(mechanicVectorId); } /** * @notice Get raw vector data * @param mechanicVectorId Mechanic vector ID */ function getRawVector( bytes32 mechanicVectorId ) external view returns (DutchAuctionVector memory _vector, bytes memory packedPrices) { _vector = vector[mechanicVectorId]; packedPrices = vectorPackedPrices[mechanicVectorId]; } /** * @notice Get a vector's full state, including the refund currently owed to the creator and human-readable prices * @param mechanicVectorId Mechanic vector ID */ function getVectorState( bytes32 mechanicVectorId ) external view returns ( DutchAuctionVector memory _vector, uint200[] memory prices, uint200 currentPrice, uint256 payeePotentialEscrowedFunds, uint256 collectionSupply, uint256 collectionSize, bool escrowedFundsAmountFinalized, bool auctionExhausted, bool auctionInFPP ) { _vector = vector[mechanicVectorId]; (payeePotentialEscrowedFunds, escrowedFundsAmountFinalized) = _getPayeePotentialEscrowedFunds(mechanicVectorId); (collectionSupply, collectionSize) = _collectionSupplyAndSize(mechanicVectorId); auctionExhausted = _vector.auctionExhausted || _isAuctionExhausted(mechanicVectorId, _vector.currentSupply, _vector.maxTotalClaimableViaVector); uint32 priceIndex = auctionExhausted ? _vector.lowestPriceSoldAtIndex : _calculatePriceIndex(_vector.startTimestamp, _vector.periodDuration, _vector.numPrices); currentPrice = PackedPrices.priceAt(vectorPackedPrices[mechanicVectorId], _vector.bytesPerPrice, priceIndex); auctionInFPP = _auctionIsInFPP(_vector.currentSupply, priceIndex, _vector.numPrices); prices = PackedPrices.unpack(vectorPackedPrices[mechanicVectorId], _vector.bytesPerPrice, _vector.numPrices); } /* solhint-disable no-empty-blocks */ /** * @notice Limit upgrades of contract to DiscreteDutchAuctionMechanic owner * @param // New implementation address */ function _authorizeUpgrade(address) internal override onlyOwner {} /** * @notice Process mint logic common through sequential and collector's choice based mints * @param mechanicVectorId Mechanic vector ID * @param recipient Mint recipient * @param numToMint Number of tokens to mint */ function _processMint(bytes32 mechanicVectorId, address recipient, uint32 numToMint) private { DutchAuctionVector memory _vector = vector[mechanicVectorId]; UserPurchaseInfo memory _userPurchaseInfo = userPurchaseInfo[mechanicVectorId][recipient]; uint48 newSupply = _vector.currentSupply + numToMint; if ( block.timestamp < _vector.startTimestamp || (block.timestamp > _vector.endTimestamp && _vector.endTimestamp != 0) || (_vector.maxTotalClaimableViaVector != 0 && newSupply > _vector.maxTotalClaimableViaVector) || (_vector.maxUserClaimableViaVector != 0 && _userPurchaseInfo.numTokensBought + numToMint > _vector.maxUserClaimableViaVector) || (_vector.tokenLimitPerTx != 0 && numToMint > _vector.tokenLimitPerTx) || _vector.auctionExhausted ) { _revert(InvalidMint.selector); } // can safely cast down here since the value is dependent on array length uint32 priceIndex = _calculatePriceIndex(_vector.startTimestamp, _vector.periodDuration, _vector.numPrices); uint200 price = PackedPrices.priceAt(vectorPackedPrices[mechanicVectorId], _vector.bytesPerPrice, priceIndex); uint200 totalPrice = price * numToMint; if (totalPrice > msg.value) { _revert(InvalidPaymentAmount.selector); } // update lowestPriceSoldAtindex, currentSupply, totalSales and user purchase info if (_vector.lowestPriceSoldAtIndex != priceIndex) { vector[mechanicVectorId].lowestPriceSoldAtIndex = priceIndex; } vector[mechanicVectorId].currentSupply = newSupply; vector[mechanicVectorId].totalSales = _vector.totalSales + totalPrice; _userPurchaseInfo.numTokensBought += numToMint; _userPurchaseInfo.totalPosted += uint200(msg.value); // if collector sent more, let them collect the difference userPurchaseInfo[mechanicVectorId][recipient] = _userPurchaseInfo; if (_vector.payeeRevenueHasBeenWithdrawn) { // send ether value to payment recipient uint200 platformFee = (totalPrice * 500) / 10000; (bool sentToPaymentRecipient, ) = _vector.paymentRecipient.call{ value: totalPrice - platformFee }(""); if (!sentToPaymentRecipient) { _revert(EtherSendFailed.selector); } (bool sentToPlatform, ) = (payable(owner())).call{ value: platformFee }(""); if (!sentToPlatform) { _revert(EtherSendFailed.selector); } } emit DiscreteDutchAuctionMint(mechanicVectorId, recipient, price, numToMint); } /** * @notice Validate a dutch auction vector * @param _vector Dutch auction vector being validated */ function _validateVectorConfig( DutchAuctionVector memory _vector, bytes memory packedPrices, bool validateIndividualPrices ) private { if ( _vector.periodDuration == 0 || _vector.paymentRecipient == address(0) || _vector.numPrices < 2 || _vector.bytesPerPrice > 32 ) { _revert(InvalidVectorConfig.selector); } if (_vector.endTimestamp != 0) { // allow the last period to be truncated if (_vector.startTimestamp + ((_vector.numPrices - 1) * _vector.periodDuration) >= _vector.endTimestamp) { _revert(InvalidVectorConfig.selector); } } if (validateIndividualPrices) { if (_vector.bytesPerPrice * _vector.numPrices != packedPrices.length) { _revert(InvalidVectorConfig.selector); } uint200[] memory prices = PackedPrices.unpack(packedPrices, _vector.bytesPerPrice, _vector.numPrices); uint200 lastPrice = prices[0]; uint256 numPrices = uint256(_vector.numPrices); // cast up into uint256 for gas savings on array check for (uint256 i = 1; i < _vector.numPrices; i++) { if (prices[i] >= lastPrice) { _revert(InvalidVectorConfig.selector); } lastPrice = prices[i]; } } } /** * @notice Get how much is owed to the payment recipient currently * @param mechanicVectorId Mechanic vector ID * @return escrowFunds + isFinalAmount */ function _getPayeePotentialEscrowedFunds(bytes32 mechanicVectorId) private view returns (uint256, bool) { DutchAuctionVector memory _vector = vector[mechanicVectorId]; if (_vector.payeeRevenueHasBeenWithdrawn) { // escrowed funds have already been withdrawn / finalized return (0, true); } if (_vector.currentSupply == 0) { return (0, false); } bool auctionExhausted = _vector.auctionExhausted || _isAuctionExhausted(mechanicVectorId, _vector.currentSupply, _vector.maxTotalClaimableViaVector); uint32 priceIndex = auctionExhausted ? _vector.lowestPriceSoldAtIndex : _calculatePriceIndex(_vector.startTimestamp, _vector.periodDuration, _vector.numPrices); uint200 potentialClearingPrice = PackedPrices.priceAt( vectorPackedPrices[mechanicVectorId], _vector.bytesPerPrice, priceIndex ); // escrowFunds is only final if auction is exhausted or in FPP return ( (uint256(_vector.currentSupply * potentialClearingPrice) * 9500) / 10000, // 95% (auctionExhausted || _auctionIsInFPP(_vector.currentSupply, priceIndex, _vector.numPrices)) ); } /** * @notice Return true if an auction has reached its max supply or if the underlying collection has * @param mechanicVectorId Mechanic vector ID * @param currentSupply Current supply minted through the vector * @param maxTotalClaimableViaVector Max claimable via the vector */ function _isAuctionExhausted( bytes32 mechanicVectorId, uint48 currentSupply, uint48 maxTotalClaimableViaVector ) private view returns (bool) { if (maxTotalClaimableViaVector != 0 && currentSupply >= maxTotalClaimableViaVector) return true; (uint256 supply, uint256 size) = _collectionSupplyAndSize(mechanicVectorId); return size != 0 && supply >= size; } /** * @notice Returns a collection's current supply * @param mechanicVectorId Mechanic vector ID */ function _collectionSupplyAndSize(bytes32 mechanicVectorId) private view returns (uint256 supply, uint256 size) { MechanicVectorMetadata memory metadata = _getMechanicVectorMetadata(mechanicVectorId); if (metadata.contractAddress == address(0)) { revert("Vector doesn't exist"); } if (metadata.isEditionBased) { IEditionCollection.EditionDetails memory edition = IEditionCollection(metadata.contractAddress) .getEditionDetails(metadata.editionId); supply = edition.supply; size = edition.size; } else { // supply holds a tighter constraint (no burns), some old contracts don't have it try IERC721GeneralSupplyMetadata(metadata.contractAddress).supply() returns (uint256 _supply) { supply = _supply; } catch { supply = IERC721GeneralSupplyMetadata(metadata.contractAddress).totalSupply(); } size = IERC721GeneralSupplyMetadata(metadata.contractAddress).limitSupply(); } } /** * @notice Calculate what price the dutch auction is at * @param startTimestamp Auction start time * @param periodDuration Time per period * @param numPrices Number of prices */ function _calculatePriceIndex( uint48 startTimestamp, uint32 periodDuration, uint32 numPrices ) private view returns (uint32) { if (block.timestamp <= startTimestamp) { return 0; } uint256 hypotheticalIndex = uint256((block.timestamp - startTimestamp) / periodDuration); if (hypotheticalIndex >= numPrices) { return numPrices - 1; } else { return uint32(hypotheticalIndex); } } /** * @notice Return if the auction is in the fixed price period * @param currentSupply Current supply of tokens minted via mechanic vector * @param priceIndex Index of price prices * @param numPrices Number of prices */ function _auctionIsInFPP(uint48 currentSupply, uint256 priceIndex, uint32 numPrices) private pure returns (bool) { return currentSupply > 0 && priceIndex == numPrices - 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822.sol"; import "../ERC1967/ERC1967Upgrade.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeTo(address newImplementation) public virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Interfaces with the details of editions on collections * @author highlight.xyz */ interface IEditionCollection { /** * @notice Edition details * @param name Edition name * @param size Edition size * @param supply Total number of tokens minted on edition * @param initialTokenId Token id of first token minted in edition */ struct EditionDetails { string name; uint256 size; uint256 supply; uint256 initialTokenId; } /** * @notice Get the edition a token belongs to * @param tokenId The token id of the token */ function getEditionId(uint256 tokenId) external view returns (uint256); /** * @notice Get an edition's details * @param editionId Edition id */ function getEditionDetails(uint256 editionId) external view returns (EditionDetails memory); /** * @notice Get the details and uris of a number of editions * @param editionIds List of editions to get info for */ function getEditionsDetailsAndUri( uint256[] calldata editionIds ) external view returns (EditionDetails[] memory, string[] memory uris); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Get a Series based collection's supply metadata * @author highlight.xyz */ interface IERC721GeneralSupplyMetadata { /** * @notice Get a series based collection's supply, burned tokens notwithstanding */ function supply() external view returns (uint256); /** * @notice Get a series based collection's total supply */ function totalSupply() external view returns (uint256); /** * @notice Get a series based collection's supply cap */ function limitSupply() external view returns (uint256); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "./IMechanicData.sol"; /** * @notice Interface that mint mechanics are forced to adhere to, * provided they support both collector's choice and sequential minting */ interface IMechanic is IMechanicData { /** * @notice Create a mechanic vector on the mechanic * @param mechanicVectorId Global mechanic vector ID * @param vectorData Mechanic vector data */ function createVector(bytes32 mechanicVectorId, bytes calldata vectorData) external; /** * @notice Process a sequential mint * @param mechanicVectorId Global ID identifying mint vector, using this mechanic * @param recipient Mint recipient * @param numToMint Number of tokens to mint * @param minter Account that called mint on the MintManager * @param mechanicVectorMetadata Mechanic vector metadata * @param data Custom data that can be deserialized and processed according to implementation */ function processNumMint( bytes32 mechanicVectorId, address recipient, uint32 numToMint, address minter, MechanicVectorMetadata calldata mechanicVectorMetadata, bytes calldata data ) external payable; /** * @notice Process a collector's choice mint * @param mechanicVectorId Global ID identifying mint vector, using this mechanic * @param recipient Mint recipient * @param tokenIds IDs of tokens to mint * @param minter Account that called mint on the MintManager * @param mechanicVectorMetadata Mechanic vector metadata * @param data Custom data that can be deserialized and processed according to implementation */ function processChooseMint( bytes32 mechanicVectorId, address recipient, uint256[] calldata tokenIds, address minter, MechanicVectorMetadata calldata mechanicVectorMetadata, bytes calldata data ) external payable; }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Defines a mechanic's metadata on the MintManager */ interface IMechanicData { /** * @notice A mechanic's metadata * @param contractAddress Collection contract address * @param editionId Edition ID if the collection is edition based * @param mechanic Address of mint mechanic contract * @param isEditionBased True if collection is edition based * @param isChoose True if collection uses a collector's choice mint paradigm * @param paused True if mechanic vector is paused */ struct MechanicVectorMetadata { address contractAddress; uint96 editionId; address mechanic; bool isEditionBased; bool isChoose; bool paused; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import "./IMechanicData.sol"; interface IMechanicMintManagerView is IMechanicData { /** * @notice Get a mechanic vector's metadata * @param mechanicVectorId Global mechanic vector ID */ function mechanicVectorMetadata(bytes32 mechanicVectorId) external view returns (MechanicVectorMetadata memory); /** * @notice Returns whether an address is a valid platform executor * @param _executor Address to be checked */ function isPlatformExecutor(address _executor) external view returns (bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./interfaces/IMechanic.sol"; import "./interfaces/IMechanicMintManagerView.sol"; /** * @notice MintManager client, to be used by mechanic contracts * @author highlight.xyz */ abstract contract MechanicMintManagerClientUpgradeable is OwnableUpgradeable, IMechanic { /** * @notice Throw when caller is not MintManager */ error NotMintManager(); /** * @notice Throw when input mint manager is invalid */ error InvalidMintManager(); /** * @notice Mint manager */ address public mintManager; /** * @notice Enforce caller to be mint manager */ modifier onlyMintManager() { if (msg.sender != mintManager) { _revert(NotMintManager.selector); } _; } /** * @notice Update the mint manager * @param _mintManager New mint manager */ function updateMintManager(address _mintManager) external onlyOwner { if (_mintManager == address(0)) { _revert(InvalidMintManager.selector); } mintManager = _mintManager; } /** * @notice Initialize mechanic mint manager client * @param _mintManager Mint manager address * @param platform Platform owning the contract */ function __MechanicMintManagerClientUpgradeable_initialize( address _mintManager, address platform ) internal onlyInitializing { __Ownable_init(); mintManager = _mintManager; _transferOwnership(platform); } /** * @notice Get a mechanic mint vector's metadata * @param mechanicVectorId Mechanic vector ID */ function _getMechanicVectorMetadata( bytes32 mechanicVectorId ) internal view returns (MechanicVectorMetadata memory) { return IMechanicMintManagerView(mintManager).mechanicVectorMetadata(mechanicVectorId); } function _isPlatformExecutor(address _executor) internal view returns (bool) { return IMechanicMintManagerView(mintManager).isPlatformExecutor(_executor); } /** * @dev For more efficient reverts. */ function _revert(bytes4 errorSelector) internal pure { assembly { mstore(0x00, errorSelector) revert(0x00, 0x04) } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.10; /** * @notice Util library to pack, unpack, and access packed prices data * @author highlight.xyz */ library PackedPrices { /** * @notice Return unpacked prices * @dev Assume length validations are met */ function unpack( bytes memory packedPrices, uint8 bytesPerPrice, uint32 numPrices ) internal view returns (uint200[] memory prices) { prices = new uint200[](numPrices); for (uint32 i = 0; i < numPrices; i++) { prices[i] = priceAt(packedPrices, bytesPerPrice, i); } } /** * @notice Return price at an index * @dev Assume length validations are met */ function priceAt(bytes memory packedPrices, uint8 bytesPerPrice, uint32 index) internal view returns (uint200) { uint256 readIndex = index * bytesPerPrice; uint256 price; assembly { // Load 32 bytes starting from the correct position in packedPrices price := mload(add(packedPrices, add(32, readIndex))) } return uint200(price >> (256 - (bytesPerPrice * 8))); } }
{ "metadata": { "bytecodeHash": "none" }, "optimizer": { "enabled": true, "runs": 1 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"CollectorNotOwedRebate","type":"error"},{"inputs":[],"name":"EtherSendFailed","type":"error"},{"inputs":[],"name":"InvalidDPPFundsWithdrawl","type":"error"},{"inputs":[],"name":"InvalidMint","type":"error"},{"inputs":[],"name":"InvalidMintManager","type":"error"},{"inputs":[],"name":"InvalidPaymentAmount","type":"error"},{"inputs":[],"name":"InvalidRebate","type":"error"},{"inputs":[],"name":"InvalidUpdate","type":"error"},{"inputs":[],"name":"InvalidVectorConfig","type":"error"},{"inputs":[],"name":"NotMintManager","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"VectorAlreadyCreated","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":"mechanicVectorId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"collector","type":"address"},{"indexed":false,"internalType":"uint200","name":"rebate","type":"uint200"},{"indexed":false,"internalType":"uint200","name":"currentPricePerNft","type":"uint200"}],"name":"DiscreteDutchAuctionCollectorRebate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"}],"name":"DiscreteDutchAuctionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"paymentRecipient","type":"address"},{"indexed":false,"internalType":"uint200","name":"clearingPrice","type":"uint200"},{"indexed":false,"internalType":"uint48","name":"currentSupply","type":"uint48"}],"name":"DiscreteDutchAuctionDPPFundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint200","name":"pricePerToken","type":"uint200"},{"indexed":false,"internalType":"uint48","name":"numMinted","type":"uint48"}],"name":"DiscreteDutchAuctionMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"}],"name":"DiscreteDutchAuctionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"bytes","name":"vectorData","type":"bytes"}],"name":"createVector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"}],"name":"getPayeePotentialEscrowedFunds","outputs":[{"internalType":"uint256","name":"escrowFunds","type":"uint256"},{"internalType":"bool","name":"amountFinalized","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"}],"name":"getRawVector","outputs":[{"components":[{"internalType":"uint48","name":"startTimestamp","type":"uint48"},{"internalType":"uint48","name":"endTimestamp","type":"uint48"},{"internalType":"uint32","name":"periodDuration","type":"uint32"},{"internalType":"uint32","name":"maxUserClaimableViaVector","type":"uint32"},{"internalType":"uint48","name":"maxTotalClaimableViaVector","type":"uint48"},{"internalType":"uint48","name":"currentSupply","type":"uint48"},{"internalType":"uint32","name":"lowestPriceSoldAtIndex","type":"uint32"},{"internalType":"uint32","name":"tokenLimitPerTx","type":"uint32"},{"internalType":"uint32","name":"numPrices","type":"uint32"},{"internalType":"address payable","name":"paymentRecipient","type":"address"},{"internalType":"uint240","name":"totalSales","type":"uint240"},{"internalType":"uint8","name":"bytesPerPrice","type":"uint8"},{"internalType":"bool","name":"auctionExhausted","type":"bool"},{"internalType":"bool","name":"payeeRevenueHasBeenWithdrawn","type":"bool"}],"internalType":"struct DiscreteDutchAuctionMechanic.DutchAuctionVector","name":"_vector","type":"tuple"},{"internalType":"bytes","name":"packedPrices","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"address","name":"user","type":"address"}],"name":"getUserInfo","outputs":[{"internalType":"uint256","name":"rebate","type":"uint256"},{"components":[{"internalType":"uint32","name":"numTokensBought","type":"uint32"},{"internalType":"uint24","name":"numRebates","type":"uint24"},{"internalType":"uint200","name":"totalPosted","type":"uint200"}],"internalType":"struct DiscreteDutchAuctionMechanic.UserPurchaseInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"}],"name":"getVectorState","outputs":[{"components":[{"internalType":"uint48","name":"startTimestamp","type":"uint48"},{"internalType":"uint48","name":"endTimestamp","type":"uint48"},{"internalType":"uint32","name":"periodDuration","type":"uint32"},{"internalType":"uint32","name":"maxUserClaimableViaVector","type":"uint32"},{"internalType":"uint48","name":"maxTotalClaimableViaVector","type":"uint48"},{"internalType":"uint48","name":"currentSupply","type":"uint48"},{"internalType":"uint32","name":"lowestPriceSoldAtIndex","type":"uint32"},{"internalType":"uint32","name":"tokenLimitPerTx","type":"uint32"},{"internalType":"uint32","name":"numPrices","type":"uint32"},{"internalType":"address payable","name":"paymentRecipient","type":"address"},{"internalType":"uint240","name":"totalSales","type":"uint240"},{"internalType":"uint8","name":"bytesPerPrice","type":"uint8"},{"internalType":"bool","name":"auctionExhausted","type":"bool"},{"internalType":"bool","name":"payeeRevenueHasBeenWithdrawn","type":"bool"}],"internalType":"struct DiscreteDutchAuctionMechanic.DutchAuctionVector","name":"_vector","type":"tuple"},{"internalType":"uint200[]","name":"prices","type":"uint200[]"},{"internalType":"uint200","name":"currentPrice","type":"uint200"},{"internalType":"uint256","name":"payeePotentialEscrowedFunds","type":"uint256"},{"internalType":"uint256","name":"collectionSupply","type":"uint256"},{"internalType":"uint256","name":"collectionSize","type":"uint256"},{"internalType":"bool","name":"escrowedFundsAmountFinalized","type":"bool"},{"internalType":"bool","name":"auctionExhausted","type":"bool"},{"internalType":"bool","name":"auctionInFPP","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_mintManager","type":"address"},{"internalType":"address","name":"platform","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"address","name":"minter","type":"address"},{"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":"bytes","name":"data","type":"bytes"}],"name":"processChooseMint","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":"address","name":"minter","type":"address"},{"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":"bytes","name":"data","type":"bytes"}],"name":"processNumMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"internalType":"address payable","name":"collector","type":"address"}],"name":"rebateCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mintManager","type":"address"}],"name":"updateMintManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"},{"components":[{"internalType":"uint48","name":"startTimestamp","type":"uint48"},{"internalType":"uint48","name":"endTimestamp","type":"uint48"},{"internalType":"uint32","name":"periodDuration","type":"uint32"},{"internalType":"uint32","name":"maxUserClaimableViaVector","type":"uint32"},{"internalType":"uint48","name":"maxTotalClaimableViaVector","type":"uint48"},{"internalType":"uint48","name":"currentSupply","type":"uint48"},{"internalType":"uint32","name":"lowestPriceSoldAtIndex","type":"uint32"},{"internalType":"uint32","name":"tokenLimitPerTx","type":"uint32"},{"internalType":"uint32","name":"numPrices","type":"uint32"},{"internalType":"address payable","name":"paymentRecipient","type":"address"},{"internalType":"uint240","name":"totalSales","type":"uint240"},{"internalType":"uint8","name":"bytesPerPrice","type":"uint8"},{"internalType":"bool","name":"auctionExhausted","type":"bool"},{"internalType":"bool","name":"payeeRevenueHasBeenWithdrawn","type":"bool"}],"internalType":"struct DiscreteDutchAuctionMechanic.DutchAuctionVector","name":"newVector","type":"tuple"},{"internalType":"bytes","name":"newPackedPrices","type":"bytes"},{"components":[{"internalType":"bool","name":"updateStartTimestamp","type":"bool"},{"internalType":"bool","name":"updateEndTimestamp","type":"bool"},{"internalType":"bool","name":"updatePeriodDuration","type":"bool"},{"internalType":"bool","name":"updateMaxUserClaimableViaVector","type":"bool"},{"internalType":"bool","name":"updateMaxTotalClaimableViaVector","type":"bool"},{"internalType":"bool","name":"updateTokenLimitPerTx","type":"bool"},{"internalType":"bool","name":"updatePaymentRecipient","type":"bool"},{"internalType":"bool","name":"updatePrices","type":"bool"}],"internalType":"struct DiscreteDutchAuctionMechanic.DutchAuctionVectorUpdateConfig","name":"updateConfig","type":"tuple"}],"name":"updateVector","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":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"userPurchaseInfo","outputs":[{"internalType":"uint32","name":"numTokensBought","type":"uint32"},{"internalType":"uint24","name":"numRebates","type":"uint24"},{"internalType":"uint200","name":"totalPosted","type":"uint200"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mechanicVectorId","type":"bytes32"}],"name":"withdrawDPPFunds","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523060805234801561001457600080fd5b5060805161474c61004c60003960008181610eba01528181610f03015281816115260152818161156601526115e2015261474c6000f3fe6080604052600436106100ef5760003560e01c80630ae94103146100f457806313b5d9e61461012b5780631a8d379214610160578063312e109c146101825780633659cfe6146101de57806339986206146101fe578063485cc9551461021e5780634f1ef2861461023e57806352d1902d1461025157806361c4006814610274578063715018a6146102a95780637e4edf70146102be5780638da5cb5b146102f65780639cc163e51461030b578063c4804ce21461031e578063ceab8e1914610331578063da5988c814610351578063f12f63da146103dd578063f2fde38b146103fd578063fe7f6c331461041d575b600080fd5b34801561010057600080fd5b5061011461010f3660046138d4565b61043d565b604051610122929190613a66565b60405180910390f35b34801561013757600080fd5b5061014b6101463660046138d4565b6105e1565b60405161012299989796959493929190613a91565b34801561016c57600080fd5b5061018061017b366004613c29565b6108e2565b005b34801561018e57600080fd5b506101a261019d366004613c94565b610c14565b60408051928352815163ffffffff1660208085019190915282015162ffffff168382015201516001600160c81b03166060820152608001610122565b3480156101ea57600080fd5b506101806101f9366004613cc4565b610eaf565b34801561020a57600080fd5b506101806102193660046138d4565b610f81565b34801561022a57600080fd5b50610180610239366004613ce1565b6113ff565b61018061024c366004613d0f565b61151b565b34801561025d57600080fd5b506102666115d5565b604051908152602001610122565b34801561028057600080fd5b5061029461028f3660046138d4565b611683565b60408051928352901515602083015201610122565b3480156102b557600080fd5b50610180611698565b3480156102ca57600080fd5b506065546102de906001600160a01b031681565b6040516001600160a01b039091168152602001610122565b34801561030257600080fd5b506102de6116ac565b610180610319366004613db3565b6116bb565b61018061032c366004613e4b565b6116f1565b34801561033d57600080fd5b5061018061034c366004613cc4565b611728565b34801561035d57600080fd5b506103ae61036c366004613c94565b606860209081526000928352604080842090915290825290205463ffffffff811690600160201b810462ffffff1690600160381b90046001600160c81b031683565b6040805163ffffffff909416845262ffffff90921660208401526001600160c81b031690820152606001610122565b3480156103e957600080fd5b506101806103f8366004613f29565b611770565b34801561040957600080fd5b50610180610418366004613cc4565b611e8d565b34801561042957600080fd5b50610180610438366004613c94565b611f03565b610445613753565b50600081815260666020908152604080832081516101c081018352815465ffffffffffff8082168352600160301b820481168387015263ffffffff600160601b808404821685880152600160801b84048216606086810191909152600160a01b850484166080870152600160d01b90940490921660a0850152600185015480821660c0860152600160201b8104821660e0860152600160401b81049091166101008501526001600160a01b039190041661012083015260028301546001600160f01b03811661014084015260ff600160f01b82048116610160850152600160f81b9091048116151561018084015260039093015490921615156101a082015285855260679093529220805491929161055c90613fb2565b80601f016020809104026020016040519081016040528092919081815260200182805461058890613fb2565b80156105d55780601f106105aa576101008083540402835291602001916105d5565b820191906000526020600020905b8154815290600101906020018083116105b857829003601f168201915b50505050509050915091565b6105e9613753565b50600081815260666020908152604080832081516101c081018352815465ffffffffffff8082168352600160301b8204811695830195909552600160601b80820463ffffffff90811695840195909552600160801b82048516606080850191909152600160a01b830487166080850152600160d01b90920490951660a0830152600183015480851660c0840152600160201b8104851660e0840152600160401b8104909416610100830152939092046001600160a01b031661012083015260028101546001600160f01b038116610140840152600160f01b810460ff908116610160850152600160f81b909104811615156101808401526003909101541615156101a0820152918080808080806106ff8a612321565b909650925061070d8a612530565b6101808b015191965094508061073157506107318a8a60a001518b6080015161276f565b9150600082610757576107528a600001518b604001518c61010001516127d2565b61075d565b8960c001515b60008c815260676020526040902080549192506108079161077d90613fb2565b80601f01602080910402602001604051908101604052809291908181526020018280546107a990613fb2565b80156107f65780601f106107cb576101008083540402835291602001916107f6565b820191906000526020600020905b8154815290600101906020018083116107d957829003601f168201915b50505050508b610160015183612841565b97506108238a60a001518263ffffffff168c6101000151612889565b60008c815260676020526040902080549193506108d29161084390613fb2565b80601f016020809104026020016040519081016040528092919081815260200182805461086f90613fb2565b80156108bc5780601f10610891576101008083540402835291602001916108bc565b820191906000526020600020905b81548152906001019060200180831161089f57829003601f168201915b50505050508b61016001518c61010001516128b9565b9850509193959799909294969850565b6065546001600160a01b0316331461090457610904639a04794d60e01b612969565b600082815260666020526040902054600160601b900463ffffffff1615610935576109356366fa676560e11b612969565b6000806000806000806000806000808a806020019051810190610958919061407b565b99509950995099509950995099509950995099506000604051806101c001604052808c65ffffffffffff16600014610990578c610992565b425b65ffffffffffff90811682528c8116602083015263ffffffff808d1660408401528b81166060840152908a166080830152600060a0830181905260c0830181905289821660e08401529088166101008301526001600160a01b038616610120830152610140820181905260ff871661016083015261018082018190526101a0909101529050610a2381836001612973565b60008d8152606660209081526040808320845181548487015184880151606089015160808a015160a08b015165ffffffffffff908116600160d01b026001600160d01b03928216600160a01b02929092166001600160a01b0363ffffffff948516600160801b0263ffffffff60801b19968616600160601b90810297909716600160601b600160a01b0319988516600160301b026001600160601b0319909a1694909a16939093179790971795909516969096179590951784169290921793909317845560c088015160018501805460e08b01516101008c01516101208d01519096169096026001600160601b03958516600160401b02959095166001600160401b03968516600160201b026001600160401b031990921693909416929092179190911793909316171790556101408501516002820180546101608801516101808901511515600160f81b026001600160f81b0360ff909216600160f01b026001600160f81b03199093166001600160f01b039095169490941791909117169190911790556101a08501516003909101805491151560ff19909216919091179055606782529091208351610bd9928501906137c7565b506040518d907fae1d04d24b8c04c53f07b4b6c8509fb74edd038b61159d9cc6090d31bb9cb71e90600090a250505050505050505050505050565b6040805160608082018352600080835260208084018290528385018290528682526066815284822085516101c081018752815465ffffffffffff8082168352600160301b8204811683860152600160601b80830463ffffffff908116858c0152600160801b84048116858a0152600160a01b840483166080860152600160d01b909304821660a08501908152600186015480851660c0870152600160201b808204861660e0880152600160401b820486166101008801529290046001600160a01b0390811661012087015260028701546001600160f01b038116610140880152600160f01b810460ff908116610160890152600160f81b9091048116151561018088015260039097015490961615156101a08601528c8852606887528a8820958c1688529486528987208a519889018b52549283168852820462ffffff1694870194909452600160381b90046001600160c81b031696850196909652519194929116610d8757600093509150610ea89050565b60008681526067602052604081208054610e679190610da590613fb2565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd190613fb2565b8015610e1e5780601f10610df357610100808354040283529160200191610e1e565b820191906000526020600020905b815481529060010190602001808311610e0157829003601f168201915b5050505050846101600151610e3c8a8760a00151886080015161276f565b610e5d57610e58866000015187604001518861010001516127d2565b612841565b8560c00151612841565b9050600081836000015163ffffffff16610e819190614174565b90506000818460400151610e9591906141a3565b6001600160c81b03169650929450505050505b9250929050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161415610f015760405162461bcd60e51b8152600401610ef8906141cb565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610f33612b4e565b6001600160a01b031614610f595760405162461bcd60e51b8152600401610ef890614205565b610f6281612b6a565b60408051600080825260208201909252610f7e91839190612b72565b50565b60008181526066602090815260409182902082516101c081018452815465ffffffffffff8082168352600160301b8204811694830194909452600160601b80820463ffffffff90811696840196909652600160801b820486166060840152600160a01b820485166080840152600160d01b90910490931660a0820152600182015480851660c0830152600160201b8104851660e0830152600160401b8104909416610100820152919092046001600160a01b031661012082015260028201546001600160f01b038116610140830152600160f01b810460ff908116610160840152600160f81b9091048116151561018083015260039092015490911615156101a082018190528061109c575060a081015165ffffffffffff16155b156110b1576110b1631c7c1d0760e01b612969565b610180810151806110fc576110cf838360a00151846080015161276f565b905080156110fc57600083815260666020526040902060020180546001600160f81b0316600160f81b1790555b6000816111205761111b836000015184604001518561010001516127d2565b611126565b8260c001515b90508115801561114d575061114b8360a001518263ffffffff16856101000151612889565b155b1561116257611162631c7c1d0760e01b612969565b6000848152606660209081526040808320600301805460ff19166001179055606790915281208054611222919061119890613fb2565b80601f01602080910402602001604051908101604052809291908181526020018280546111c490613fb2565b80156112115780601f106111e657610100808354040283529160200191611211565b820191906000526020600020905b8154815290600101906020018083116111f457829003601f168201915b505050505085610160015184612841565b90506000818560a0015165ffffffffffff1661123e9190614174565b90508461014001516001600160f01b0316816001600160c81b0316111561126f5761126f631c7c1d0760e01b612969565b6000612710611280836101f4614174565b61128a9190614255565b905060008661012001516001600160a01b031682846112a991906141a3565b6001600160c81b031660405160006040518083038185875af1925050503d80600081146112f2576040519150601f19603f3d011682016040523d82523d6000602084013e6112f7565b606091505b505090508061131057611310637cd69c3960e11b612969565b600061131a6116ac565b6001600160a01b0316836001600160c81b031660405160006040518083038185875af1925050503d806000811461136d576040519150601f19603f3d011682016040523d82523d6000602084013e611372565b606091505b505090508061138b5761138b637cd69c3960e11b612969565b8761012001516001600160a01b0316897ffccb3c89d1529bc3eb407d46314f16504f8eb486bf9aa10978b72b5132203657878b60a001516040516113ec9291906001600160c81b0392909216825265ffffffffffff16602082015260400190565b60405180910390a3505050505050505050565b600054610100900460ff161580801561141f5750600054600160ff909116105b80611440575061142e30612cdd565b158015611440575060005460ff166001145b6114a35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610ef8565b6000805460ff1916600117905580156114c6576000805461ff0019166101001790555b6114d08383612cec565b8015611516576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156115645760405162461bcd60e51b8152600401610ef8906141cb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611596612b4e565b6001600160a01b0316146115bc5760405162461bcd60e51b8152600401610ef890614205565b6115c582612b6a565b6115d182826001612b72565b5050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146116705760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610ef8565b506000805160206146f983398151915290565b60008061168f83612321565b91509150915091565b6116a0612d3f565b6116aa6000612d9e565b565b6033546001600160a01b031690565b6065546001600160a01b031633146116dd576116dd639a04794d60e01b612969565b6116e8878787612df0565b50505050505050565b6065546001600160a01b0316331461171357611713639a04794d60e01b612969565b61171e888887612df0565b5050505050505050565b611730612d3f565b6001600160a01b03811661174e5761174e63040b3bcf60e31b612969565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600061177b86613428565b80519091506001600160a01b0316331480159061180f5750336001600160a01b031681600001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061427b565b6001600160a01b031614155b15611823576118236282b42960e81b612969565b60008681526066602090815260409182902082516101c081018452815465ffffffffffff8082168352600160301b8204811694830194909452600160601b80820463ffffffff90811696840196909652600160801b820486166060840152600160a01b820485166080840152600160d01b90910490931660a08201819052600183015480861660c0840152600160201b8104861660e0840152600160401b8104909516610100830152929093046001600160a01b031661012084015260028101546001600160f01b038116610140850152600160f01b810460ff908116610160860152600160f81b909104811615156101808501526003909101541615156101a0830152158015906119805750611941610100840160e085016142a6565b80611957575061195760608401604085016142a6565b8061196a575061196a60208401846142a6565b80611980575061198060a08401608085016142a6565b1561199557611995637d5ba07f60e01b612969565b6119a260208401846142a6565b156119e0576119b460208701876142c3565b65ffffffffffff16156119d3576119ce60208701876142c3565b6119d5565b425b65ffffffffffff1681525b6119f060408401602085016142a6565b15611a1357611a0560408701602088016142c3565b65ffffffffffff1660208201525b611a2360608401604085016142a6565b15611a4457611a3860608701604088016142e0565b63ffffffff1660408201525b611a5460808401606085016142a6565b15611a7557611a6960808701606088016142e0565b63ffffffff1660608201525b611a8560a08401608085016142a6565b15611aa857611a9a60a08701608088016142c3565b65ffffffffffff1660808201525b611ab860c0840160a085016142a6565b15611ada57611ace610100870160e088016142e0565b63ffffffff1660e08201525b611aea60e0840160c085016142a6565b15611b1157611b0161014087016101208801613cc4565b6001600160a01b03166101208201525b611b22610100840160e085016142a6565b15611b6157611b39610180870161016088016142fd565b60ff16610160820152611b54610120870161010088016142e0565b63ffffffff166101008201525b611bb28186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bad92505050610100870160e088016142a6565b612973565b611bbf60208401846142a6565b15611bf05780516000888152606660205260409020805465ffffffffffff191665ffffffffffff9092169190911790555b611c0060408401602085016142a6565b15611c4157602080820151600089815260669092526040909120805465ffffffffffff909216600160301b0265ffffffffffff60301b199092169190911790555b611c5160608401604085016142a6565b15611c8d576040808201516000898152606660205291909120805463ffffffff909216600160601b0263ffffffff60601b199092169190911790555b611c9d60808401606085016142a6565b15611cd85760608101516000888152606660205260409020805463ffffffff909216600160801b0263ffffffff60801b199092169190911790555b611ce860a08401608085016142a6565b15611d275760808101516000888152606660205260409020805465ffffffffffff909216600160a01b0265ffffffffffff60a01b199092169190911790555b611d3760c0840160a085016142a6565b15611d755760e08101516000888152606660205260409020600101805463ffffffff909216600160201b0263ffffffff60201b199092169190911790555b611d8560e0840160c085016142a6565b15611dc657610120810151600088815260666020526040902060010180546001600160a01b03909216600160601b026001600160601b039092169190911790555b611dd7610100840160e085016142a6565b15611e59576000878152606760205260409020611df590868661384b565b50610160810151600088815260666020526040902060028101805460ff909316600160f01b0260ff60f01b19909316929092179091556101008201516001909101805463ffffffff909216600160401b0263ffffffff60401b199092169190911790555b60405187907f14c26fbe57d45444878cd034a1d26785710ec308068cb07e6d1d3ebde07ee5fe90600090a250505050505050565b611e95612d3f565b6001600160a01b038116611efa5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610ef8565b610f7e81612d9e565b600082815260666020908152604080832081516101c081018352815465ffffffffffff8082168352600160301b8204811683870152600160601b80830463ffffffff90811685880152600160801b84048116606080870191909152600160a01b850484166080870152600160d01b909404831660a08601908152600187015480831660c0880152600160201b808204841660e0890152600160401b820484166101008901529390046001600160a01b0390811661012088015260028801546001600160f01b038116610140890152600160f01b810460ff9081166101608a0152600160f81b9091048116151561018089015260039098015490971615156101a08701528b8a5260688952878a20968b168a529588529786902086519384018752549788168352870462ffffff1695820195909552600160381b9095046001600160c81b031692850192909252519092911661206857612068631e425da960e31b612969565b610180820151806120b357612086858460a00151856080015161276f565b905080156120b357600085815260666020526040902060020180546001600160f81b0316600160f81b1790555b6000858152606760205260408120805461217c91906120d190613fb2565b80601f01602080910402602001604051908101604052809291908181526020018280546120fd90613fb2565b801561214a5780601f1061211f5761010080835404028352916020019161214a565b820191906000526020600020905b81548152906001019060200180831161212d57829003601f168201915b50505050508561016001518461217257610e58876000015188604001518961010001516127d2565b8660c00151612841565b9050600081846000015163ffffffff166121969190614174565b905060008185604001516121aa91906141a3565b90506001600160c81b0381166121ca576121ca63196274cd60e31b612969565b60008881526068602090815260408083206001600160a01b038b1684528252909120805466ffffffffffffff16600160381b6001600160c81b0386160217905585015161221890600161431a565b60008981526068602090815260408083206001600160a01b038c168085529252808320805462ffffff95909516600160201b0262ffffff60201b19909516949094179093559151909182916001600160c81b038516908381818185875af1925050503d80600081146122a6576040519150601f19603f3d011682016040523d82523d6000602084013e6122ab565b606091505b5091509150816122c5576122c5637cd69c3960e11b612969565b604080516001600160c81b038086168252871660208201526001600160a01b038b16918c917f5e52ef8f94736e46374f2129ca32a992be1653b810bbb26e3b64b1a80e070aca910160405180910390a350505050505050505050565b600081815260666020908152604080832081516101c081018352815465ffffffffffff8082168352600160301b8204811695830195909552600160601b80820463ffffffff90811695840195909552600160801b820485166060840152600160a01b820486166080840152600160d01b90910490941660a0820152600182015480841660c0830152600160201b8104841660e0830152600160401b8104909316610100820152929091046001600160a01b031661012083015260028101546001600160f01b038116610140840152600160f01b810460ff908116610160850152600160f81b90910481161515610180840152600390910154161580156101a0830152829190612437575060009360019350915050565b60a081015165ffffffffffff166124545750600093849350915050565b6000816101800151806124755750612475858360a00151846080015161276f565b905060008161249b57612496836000015184604001518561010001516127d2565b6124a1565b8260c001515b905060006124c660676000898152602001908152602001600020805461119890613fb2565b9050612710818560a0015165ffffffffffff166124e39190614174565b6124f8906001600160c81b031661251c614341565b6125029190614360565b838061252357506125238560a001518463ffffffff16876101000151612889565b9550955050505050915091565b600080600061253e84613428565b80519091506001600160a01b031661258f5760405162461bcd60e51b8152602060048201526014602482015273159958dd1bdc88191bd95cdb89dd08195e1a5cdd60621b6044820152606401610ef8565b80606001511561262e578051602082015160405163ddf990f960e01b81526001600160601b0390911660048201526000916001600160a01b03169063ddf990f990602401600060405180830381865afa1580156125f0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526126189190810190614374565b9050806040015193508060200151925050612769565b80600001516001600160a01b031663047fc9aa6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561268c575060408051601f3d908101601f1916820190925261268991810190614416565b60015b6126fd5780600001516001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f69190614416565b9250612700565b92505b80600001516001600160a01b0316632ddcb21f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612742573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127669190614416565b91505b50915091565b600065ffffffffffff82161580159061279857508165ffffffffffff168365ffffffffffff1610155b156127a5575060016127cb565b6000806127b186612530565b91509150806000141580156127c65750808210155b925050505b9392505050565b60008365ffffffffffff1642116127eb575060006127cb565b600063ffffffff841661280665ffffffffffff87164261442f565b6128109190614360565b90508263ffffffff1681106128325761282a600184614446565b9150506127cb565b90506127cb565b509392505050565b60008061285160ff851684614463565b63ffffffff168581016020015190915061286c856008614486565b61287b9060ff166101006144af565b61ffff161c95945050505050565b6000808465ffffffffffff161180156128b157506128a8600183614446565b63ffffffff1683145b949350505050565b60608163ffffffff166001600160401b038111156128d9576128d9613b3e565b604051908082528060200260200182016040528015612902578160200160208202803683370190505b50905060005b8263ffffffff168163ffffffff16101561283957612927858583612841565b828263ffffffff168151811061293f5761293f6144ca565b6001600160c81b039092166020928302919091019091015280612961816144e0565b915050612908565b8060005260046000fd5b604083015163ffffffff16158061299657506101208301516001600160a01b0316155b806129ac5750600283610100015163ffffffff16105b806129bf5750602083610160015160ff16115b156129d4576129d4634b3c503560e11b612969565b602083015165ffffffffffff1615612a4357826020015165ffffffffffff1683604001516001856101000151612a0a9190614446565b612a149190614463565b8451612a269163ffffffff1690614504565b65ffffffffffff1610612a4357612a43634b3c503560e11b612969565b801561151657815183610100015184610160015160ff16612a649190614463565b63ffffffff1614612a7f57612a7f634b3c503560e11b612969565b6000612a96838561016001518661010001516128b9565b9050600081600081518110612aad57612aad6144ca565b602090810291909101015161010086015190915063ffffffff1660015b86610100015163ffffffff168110156116e857826001600160c81b0316848281518110612af957612af96144ca565b60200260200101516001600160c81b031610612b1f57612b1f634b3c503560e11b612969565b838181518110612b3157612b316144ca565b602002602001015192508080612b4690614525565b915050612aca565b6000805160206146f9833981519152546001600160a01b031690565b610f7e612d3f565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612ba557611516836134c8565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612bff575060408051601f3d908101601f19168201909252612bfc91810190614416565b60015b612c625760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610ef8565b6000805160206146f98339815191528114612cd15760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610ef8565b50611516838383613562565b6001600160a01b03163b151590565b600054610100900460ff16612d135760405162461bcd60e51b8152600401610ef890614540565b612d1b61358d565b606580546001600160a01b0319166001600160a01b0384161790556115d181612d9e565b33612d486116ac565b6001600160a01b0316146116aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ef8565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600083815260666020908152604080832081516101c081018352815465ffffffffffff8082168352600160301b8204811683870152600160601b80830463ffffffff90811685880152600160801b84048116606080870191909152600160a01b850484166080870152600160d01b90940490921660a08501908152600186015480841660c0870152600160201b808204851660e0880152600160401b820485166101008801529290046001600160a01b0390811661012087015260028701546001600160f01b038116610140880152600160f01b810460ff908116610160890152600160f81b9091048116151561018088015260039097015490961615156101a08601528b895260688852868920958b1689529487528588208651938401875254808316845290810462ffffff1696830196909652600160381b9095046001600160c81b031693810193909352905190939192612f509190861690614504565b835190915065ffffffffffff16421080612f8b5750826020015165ffffffffffff1642118015612f8b5750602083015165ffffffffffff1615155b80612fbf5750608083015165ffffffffffff1615801590612fbf5750826080015165ffffffffffff168165ffffffffffff16115b80612ffc5750606083015163ffffffff1615801590612ffc5750826060015163ffffffff16848360000151612ff4919061458b565b63ffffffff16115b8061302a575060e083015163ffffffff161580159061302a57508260e0015163ffffffff168463ffffffff16115b8061303757508261018001515b1561304c5761304c63201dc6f560e01b612969565b6000613066846000015185604001518661010001516127d2565b90506000613115606760008a8152602001908152602001600020805461308b90613fb2565b80601f01602080910402602001604051908101604052809291908181526020018280546130b790613fb2565b80156131045780601f106130d957610100808354040283529160200191613104565b820191906000526020600020905b8154815290600101906020018083116130e757829003601f168201915b505050505086610160015184612841565b9050600061312963ffffffff881683614174565b905034816001600160c81b0316111561314c5761314c637e2897ef60e11b612969565b8263ffffffff168660c0015163ffffffff1614613188576000898152606660205260409020600101805463ffffffff191663ffffffff85161790555b600089815260666020526040902080546001600160d01b0316600160d01b65ffffffffffff8716021790556101408601516131cd906001600160c81b038316906145aa565b60008a815260666020526040902060020180546001600160f01b0319166001600160f01b039290921691909117905584518790869061320d90839061458b565b63ffffffff1690525060408501805134919061322a9083906145cc565b6001600160c81b0390811690915260008b81526068602090815260408083206001600160a01b038e16845282529182902089518154928b0151938b0151909416600160381b0266ffffffffffffff62ffffff909416600160201b0266ffffffffffffff1990931663ffffffff909516949094179190911791909116919091179055506101a0860151156133d75760006127106132c8836101f4614174565b6132d29190614255565b905060008761012001516001600160a01b031682846132f191906141a3565b6001600160c81b031660405160006040518083038185875af1925050503d806000811461333a576040519150601f19603f3d011682016040523d82523d6000602084013e61333f565b606091505b505090508061335857613358637cd69c3960e11b612969565b60006133626116ac565b6001600160a01b0316836001600160c81b031660405160006040518083038185875af1925050503d80600081146133b5576040519150601f19603f3d011682016040523d82523d6000602084013e6133ba565b606091505b50509050806133d3576133d3637cd69c3960e11b612969565b5050505b604080516001600160c81b038416815263ffffffff891660208201526001600160a01b038a16918b917f71c0c8850819ac31eeb7ba034624f403ddf922c2fbfe1b6af1644a61a8e019ee91016113ec565b6040805160c081018252600080825260208201819052818301819052606082018190526080820181905260a0820152606554915162820a0360e31b81526004810184905290916001600160a01b03169063041050189060240160c060405180830381865afa15801561349e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c291906145f9565b92915050565b6134d181612cdd565b6135335760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610ef8565b6000805160206146f983398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61356b836135bc565b6000825111806135785750805b156115165761358783836135fc565b50505050565b600054610100900460ff166135b45760405162461bcd60e51b8152600401610ef890614540565b6116aa613621565b6135c5816134c8565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606127cb838360405180606001604052806027815260200161471960279139613651565b600054610100900460ff166136485760405162461bcd60e51b8152600401610ef890614540565b6116aa33612d9e565b6060600080856001600160a01b03168560405161366e91906146a9565b600060405180830381855af49150503d80600081146136a9576040519150601f19603f3d011682016040523d82523d6000602084013e6136ae565b606091505b50915091506127c6868383876060831561372457825161371d576136d185612cdd565b61371d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ef8565b50816128b1565b6128b183838151156137395781518083602001fd5b8060405162461bcd60e51b8152600401610ef891906146c5565b604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915290565b8280546137d390613fb2565b90600052602060002090601f0160209004810192826137f5576000855561383b565b82601f1061380e57805160ff191683800117855561383b565b8280016001018555821561383b579182015b8281111561383b578251825591602001919060010190613820565b506138479291506138bf565b5090565b82805461385790613fb2565b90600052602060002090601f016020900481019282613879576000855561383b565b82601f106138925782800160ff1982351617855561383b565b8280016001018555821561383b579182015b8281111561383b5782358255916020019190600101906138a4565b5b8082111561384757600081556001016138c0565b6000602082840312156138e657600080fd5b5035919050565b805165ffffffffffff1682526020810151613912602084018265ffffffffffff169052565b50604081015161392a604084018263ffffffff169052565b506060810151613942606084018263ffffffff169052565b50608081015161395c608084018265ffffffffffff169052565b5060a081015161397660a084018265ffffffffffff169052565b5060c081015161398e60c084018263ffffffff169052565b5060e08101516139a660e084018263ffffffff169052565b506101008181015163ffffffff1690830152610120808201516001600160a01b031690830152610140808201516001600160f01b0316908301526101608082015160ff1690830152610180808201511515908301526101a08082015180151582850152613587565b60005b83811015613a29578181015183820152602001613a11565b838111156135875750506000910152565b60008151808452613a52816020860160208601613a0e565b601f01601f19169290920160200192915050565b60006101e0613a7583866138ed565b806101c0840152613a8881840185613a3a565b95945050505050565b60006102c0808301613aa3848e6138ed565b6101c08401919091528a51908190526102e0830190602090818d0160005b82811015613ae65781516001600160c81b031685529383019390830190600101613ac1565b5050506001600160c81b038b166101e0850152509050876102008301528661022083015285610240830152613b2061026083018615159052565b9215156102808201529015156102a090910152979650505050505050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613b7657613b76613b3e565b60405290565b604051601f8201601f191681016001600160401b0381118282101715613ba457613ba4613b3e565b604052919050565b60006001600160401b03821115613bc557613bc5613b3e565b50601f01601f191660200190565b600082601f830112613be457600080fd5b8135613bf7613bf282613bac565b613b7c565b818152846020838601011115613c0c57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613c3c57600080fd5b8235915060208301356001600160401b03811115613c5957600080fd5b613c6585828601613bd3565b9150509250929050565b6001600160a01b0381168114610f7e57600080fd5b8035613c8f81613c6f565b919050565b60008060408385031215613ca757600080fd5b823591506020830135613cb981613c6f565b809150509250929050565b600060208284031215613cd657600080fd5b81356127cb81613c6f565b60008060408385031215613cf457600080fd5b8235613cff81613c6f565b91506020830135613cb981613c6f565b60008060408385031215613d2257600080fd5b8235613d2d81613c6f565b915060208301356001600160401b03811115613c5957600080fd5b63ffffffff81168114610f7e57600080fd5b600060c08284031215613d6c57600080fd5b50919050565b60008083601f840112613d8457600080fd5b5081356001600160401b03811115613d9b57600080fd5b602083019150836020828501011115610ea857600080fd5b6000806000806000806000610160888a031215613dcf57600080fd5b873596506020880135613de181613c6f565b95506040880135613df181613d48565b94506060880135613e0181613c6f565b9350613e108960808a01613d5a565b92506101408801356001600160401b03811115613e2c57600080fd5b613e388a828b01613d72565b989b979a50959850939692959293505050565b600080600080600080600080610160898b031215613e6857600080fd5b883597506020890135613e7a81613c6f565b965060408901356001600160401b0380821115613e9657600080fd5b818b0191508b601f830112613eaa57600080fd5b813581811115613eb957600080fd5b8c60208260051b8501011115613ece57600080fd5b6020830198509650613ee260608c01613c84565b9550613ef18c60808d01613d5a565b94506101408b0135915080821115613f0857600080fd5b50613f158b828c01613d72565b999c989b5096995094979396929594505050565b6000806000806000858703610300811215613f4357600080fd5b863595506101c0601f1982011215613f5a57600080fd5b6020870194506101e08701356001600160401b03811115613f7a57600080fd5b613f8689828a01613d72565b9095509350506101006101ff1982011215613fa057600080fd5b50610200860190509295509295909350565b600181811c90821680613fc657607f821691505b60208210811415613d6c57634e487b7160e01b600052602260045260246000fd5b65ffffffffffff81168114610f7e57600080fd5b8051613c8f81613d48565b60ff81168114610f7e57600080fd5b8051613c8f81614006565b8051613c8f81613c6f565b6000614039613bf284613bac565b905082815283838301111561404d57600080fd5b6127cb836020830184613a0e565b600082601f83011261406c57600080fd5b6127cb8383516020850161402b565b6000806000806000806000806000806101408b8d03121561409b57600080fd5b8a516140a681613fe7565b60208c0151909a506140b781613fe7565b60408c01519099506140c881613d48565b60608c01519098506140d981613d48565b60808c01519097506140ea81613fe7565b95506140f860a08c01613ffb565b945061410660c08c01613ffb565b935061411460e08c01614015565b92506141236101008c01614020565b6101208c01519092506001600160401b0381111561414057600080fd5b61414c8d828e0161405b565b9150509295989b9194979a5092959850565b634e487b7160e01b600052601160045260246000fd5b60006001600160c81b038281168482168115158284048211161561419a5761419a61415e565b02949350505050565b60006001600160c81b03838116908316818110156141c3576141c361415e565b039392505050565b6020808252602c908201526000805160206146d983398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201526000805160206146d983398151915260408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052601260045260246000fd5b60006001600160c81b038381168061426f5761426f61423f565b92169190910492915050565b60006020828403121561428d57600080fd5b81516127cb81613c6f565b8015158114610f7e57600080fd5b6000602082840312156142b857600080fd5b81356127cb81614298565b6000602082840312156142d557600080fd5b81356127cb81613fe7565b6000602082840312156142f257600080fd5b81356127cb81613d48565b60006020828403121561430f57600080fd5b81356127cb81614006565b600062ffffff8083168185168083038211156143385761433861415e565b01949350505050565b600081600019048311821515161561435b5761435b61415e565b500290565b60008261436f5761436f61423f565b500490565b60006020828403121561438657600080fd5b81516001600160401b038082111561439d57600080fd5b90830190608082860312156143b157600080fd5b6143b9613b54565b8251828111156143c857600080fd5b83019150601f820186136143db57600080fd5b6143ea8683516020850161402b565b815260208301516020820152604083015160408201526060830151606082015280935050505092915050565b60006020828403121561442857600080fd5b5051919050565b6000828210156144415761444161415e565b500390565b600063ffffffff838116908316818110156141c3576141c361415e565b600063ffffffff8083168185168183048111821515161561419a5761419a61415e565b600060ff821660ff84168160ff04811182151516156144a7576144a761415e565b029392505050565b600061ffff838116908316818110156141c3576141c361415e565b634e487b7160e01b600052603260045260246000fd5b600063ffffffff808316818114156144fa576144fa61415e565b6001019392505050565b600065ffffffffffff8083168185168083038211156143385761433861415e565b60006000198214156145395761453961415e565b5060010190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600063ffffffff8083168185168083038211156143385761433861415e565b60006001600160f01b038281168482168083038211156143385761433861415e565b60006001600160c81b038281168482168083038211156143385761433861415e565b8051613c8f81614298565b600060c0828403121561460b57600080fd5b60405160c081016001600160401b038111828210171561462d5761462d613b3e565b604052825161463b81613c6f565b815260208301516001600160601b038116811461465757600080fd5b6020820152604083015161466a81613c6f565b604082015261467b606084016145ee565b606082015261468c608084016145ee565b608082015261469d60a084016145ee565b60a08201529392505050565b600082516146bb818460208701613a0e565b9190910192915050565b6020815260006127cb6020830184613a3a56fe46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080a000a
Deployed Bytecode
0x6080604052600436106100ef5760003560e01c80630ae94103146100f457806313b5d9e61461012b5780631a8d379214610160578063312e109c146101825780633659cfe6146101de57806339986206146101fe578063485cc9551461021e5780634f1ef2861461023e57806352d1902d1461025157806361c4006814610274578063715018a6146102a95780637e4edf70146102be5780638da5cb5b146102f65780639cc163e51461030b578063c4804ce21461031e578063ceab8e1914610331578063da5988c814610351578063f12f63da146103dd578063f2fde38b146103fd578063fe7f6c331461041d575b600080fd5b34801561010057600080fd5b5061011461010f3660046138d4565b61043d565b604051610122929190613a66565b60405180910390f35b34801561013757600080fd5b5061014b6101463660046138d4565b6105e1565b60405161012299989796959493929190613a91565b34801561016c57600080fd5b5061018061017b366004613c29565b6108e2565b005b34801561018e57600080fd5b506101a261019d366004613c94565b610c14565b60408051928352815163ffffffff1660208085019190915282015162ffffff168382015201516001600160c81b03166060820152608001610122565b3480156101ea57600080fd5b506101806101f9366004613cc4565b610eaf565b34801561020a57600080fd5b506101806102193660046138d4565b610f81565b34801561022a57600080fd5b50610180610239366004613ce1565b6113ff565b61018061024c366004613d0f565b61151b565b34801561025d57600080fd5b506102666115d5565b604051908152602001610122565b34801561028057600080fd5b5061029461028f3660046138d4565b611683565b60408051928352901515602083015201610122565b3480156102b557600080fd5b50610180611698565b3480156102ca57600080fd5b506065546102de906001600160a01b031681565b6040516001600160a01b039091168152602001610122565b34801561030257600080fd5b506102de6116ac565b610180610319366004613db3565b6116bb565b61018061032c366004613e4b565b6116f1565b34801561033d57600080fd5b5061018061034c366004613cc4565b611728565b34801561035d57600080fd5b506103ae61036c366004613c94565b606860209081526000928352604080842090915290825290205463ffffffff811690600160201b810462ffffff1690600160381b90046001600160c81b031683565b6040805163ffffffff909416845262ffffff90921660208401526001600160c81b031690820152606001610122565b3480156103e957600080fd5b506101806103f8366004613f29565b611770565b34801561040957600080fd5b50610180610418366004613cc4565b611e8d565b34801561042957600080fd5b50610180610438366004613c94565b611f03565b610445613753565b50600081815260666020908152604080832081516101c081018352815465ffffffffffff8082168352600160301b820481168387015263ffffffff600160601b808404821685880152600160801b84048216606086810191909152600160a01b850484166080870152600160d01b90940490921660a0850152600185015480821660c0860152600160201b8104821660e0860152600160401b81049091166101008501526001600160a01b039190041661012083015260028301546001600160f01b03811661014084015260ff600160f01b82048116610160850152600160f81b9091048116151561018084015260039093015490921615156101a082015285855260679093529220805491929161055c90613fb2565b80601f016020809104026020016040519081016040528092919081815260200182805461058890613fb2565b80156105d55780601f106105aa576101008083540402835291602001916105d5565b820191906000526020600020905b8154815290600101906020018083116105b857829003601f168201915b50505050509050915091565b6105e9613753565b50600081815260666020908152604080832081516101c081018352815465ffffffffffff8082168352600160301b8204811695830195909552600160601b80820463ffffffff90811695840195909552600160801b82048516606080850191909152600160a01b830487166080850152600160d01b90920490951660a0830152600183015480851660c0840152600160201b8104851660e0840152600160401b8104909416610100830152939092046001600160a01b031661012083015260028101546001600160f01b038116610140840152600160f01b810460ff908116610160850152600160f81b909104811615156101808401526003909101541615156101a0820152918080808080806106ff8a612321565b909650925061070d8a612530565b6101808b015191965094508061073157506107318a8a60a001518b6080015161276f565b9150600082610757576107528a600001518b604001518c61010001516127d2565b61075d565b8960c001515b60008c815260676020526040902080549192506108079161077d90613fb2565b80601f01602080910402602001604051908101604052809291908181526020018280546107a990613fb2565b80156107f65780601f106107cb576101008083540402835291602001916107f6565b820191906000526020600020905b8154815290600101906020018083116107d957829003601f168201915b50505050508b610160015183612841565b97506108238a60a001518263ffffffff168c6101000151612889565b60008c815260676020526040902080549193506108d29161084390613fb2565b80601f016020809104026020016040519081016040528092919081815260200182805461086f90613fb2565b80156108bc5780601f10610891576101008083540402835291602001916108bc565b820191906000526020600020905b81548152906001019060200180831161089f57829003601f168201915b50505050508b61016001518c61010001516128b9565b9850509193959799909294969850565b6065546001600160a01b0316331461090457610904639a04794d60e01b612969565b600082815260666020526040902054600160601b900463ffffffff1615610935576109356366fa676560e11b612969565b6000806000806000806000806000808a806020019051810190610958919061407b565b99509950995099509950995099509950995099506000604051806101c001604052808c65ffffffffffff16600014610990578c610992565b425b65ffffffffffff90811682528c8116602083015263ffffffff808d1660408401528b81166060840152908a166080830152600060a0830181905260c0830181905289821660e08401529088166101008301526001600160a01b038616610120830152610140820181905260ff871661016083015261018082018190526101a0909101529050610a2381836001612973565b60008d8152606660209081526040808320845181548487015184880151606089015160808a015160a08b015165ffffffffffff908116600160d01b026001600160d01b03928216600160a01b02929092166001600160a01b0363ffffffff948516600160801b0263ffffffff60801b19968616600160601b90810297909716600160601b600160a01b0319988516600160301b026001600160601b0319909a1694909a16939093179790971795909516969096179590951784169290921793909317845560c088015160018501805460e08b01516101008c01516101208d01519096169096026001600160601b03958516600160401b02959095166001600160401b03968516600160201b026001600160401b031990921693909416929092179190911793909316171790556101408501516002820180546101608801516101808901511515600160f81b026001600160f81b0360ff909216600160f01b026001600160f81b03199093166001600160f01b039095169490941791909117169190911790556101a08501516003909101805491151560ff19909216919091179055606782529091208351610bd9928501906137c7565b506040518d907fae1d04d24b8c04c53f07b4b6c8509fb74edd038b61159d9cc6090d31bb9cb71e90600090a250505050505050505050505050565b6040805160608082018352600080835260208084018290528385018290528682526066815284822085516101c081018752815465ffffffffffff8082168352600160301b8204811683860152600160601b80830463ffffffff908116858c0152600160801b84048116858a0152600160a01b840483166080860152600160d01b909304821660a08501908152600186015480851660c0870152600160201b808204861660e0880152600160401b820486166101008801529290046001600160a01b0390811661012087015260028701546001600160f01b038116610140880152600160f01b810460ff908116610160890152600160f81b9091048116151561018088015260039097015490961615156101a08601528c8852606887528a8820958c1688529486528987208a519889018b52549283168852820462ffffff1694870194909452600160381b90046001600160c81b031696850196909652519194929116610d8757600093509150610ea89050565b60008681526067602052604081208054610e679190610da590613fb2565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd190613fb2565b8015610e1e5780601f10610df357610100808354040283529160200191610e1e565b820191906000526020600020905b815481529060010190602001808311610e0157829003601f168201915b5050505050846101600151610e3c8a8760a00151886080015161276f565b610e5d57610e58866000015187604001518861010001516127d2565b612841565b8560c00151612841565b9050600081836000015163ffffffff16610e819190614174565b90506000818460400151610e9591906141a3565b6001600160c81b03169650929450505050505b9250929050565b306001600160a01b037f000000000000000000000000d8f0a3aa4067be3d70a5b46a795ad9df9e65cd3c161415610f015760405162461bcd60e51b8152600401610ef8906141cb565b60405180910390fd5b7f000000000000000000000000d8f0a3aa4067be3d70a5b46a795ad9df9e65cd3c6001600160a01b0316610f33612b4e565b6001600160a01b031614610f595760405162461bcd60e51b8152600401610ef890614205565b610f6281612b6a565b60408051600080825260208201909252610f7e91839190612b72565b50565b60008181526066602090815260409182902082516101c081018452815465ffffffffffff8082168352600160301b8204811694830194909452600160601b80820463ffffffff90811696840196909652600160801b820486166060840152600160a01b820485166080840152600160d01b90910490931660a0820152600182015480851660c0830152600160201b8104851660e0830152600160401b8104909416610100820152919092046001600160a01b031661012082015260028201546001600160f01b038116610140830152600160f01b810460ff908116610160840152600160f81b9091048116151561018083015260039092015490911615156101a082018190528061109c575060a081015165ffffffffffff16155b156110b1576110b1631c7c1d0760e01b612969565b610180810151806110fc576110cf838360a00151846080015161276f565b905080156110fc57600083815260666020526040902060020180546001600160f81b0316600160f81b1790555b6000816111205761111b836000015184604001518561010001516127d2565b611126565b8260c001515b90508115801561114d575061114b8360a001518263ffffffff16856101000151612889565b155b1561116257611162631c7c1d0760e01b612969565b6000848152606660209081526040808320600301805460ff19166001179055606790915281208054611222919061119890613fb2565b80601f01602080910402602001604051908101604052809291908181526020018280546111c490613fb2565b80156112115780601f106111e657610100808354040283529160200191611211565b820191906000526020600020905b8154815290600101906020018083116111f457829003601f168201915b505050505085610160015184612841565b90506000818560a0015165ffffffffffff1661123e9190614174565b90508461014001516001600160f01b0316816001600160c81b0316111561126f5761126f631c7c1d0760e01b612969565b6000612710611280836101f4614174565b61128a9190614255565b905060008661012001516001600160a01b031682846112a991906141a3565b6001600160c81b031660405160006040518083038185875af1925050503d80600081146112f2576040519150601f19603f3d011682016040523d82523d6000602084013e6112f7565b606091505b505090508061131057611310637cd69c3960e11b612969565b600061131a6116ac565b6001600160a01b0316836001600160c81b031660405160006040518083038185875af1925050503d806000811461136d576040519150601f19603f3d011682016040523d82523d6000602084013e611372565b606091505b505090508061138b5761138b637cd69c3960e11b612969565b8761012001516001600160a01b0316897ffccb3c89d1529bc3eb407d46314f16504f8eb486bf9aa10978b72b5132203657878b60a001516040516113ec9291906001600160c81b0392909216825265ffffffffffff16602082015260400190565b60405180910390a3505050505050505050565b600054610100900460ff161580801561141f5750600054600160ff909116105b80611440575061142e30612cdd565b158015611440575060005460ff166001145b6114a35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610ef8565b6000805460ff1916600117905580156114c6576000805461ff0019166101001790555b6114d08383612cec565b8015611516576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b306001600160a01b037f000000000000000000000000d8f0a3aa4067be3d70a5b46a795ad9df9e65cd3c1614156115645760405162461bcd60e51b8152600401610ef8906141cb565b7f000000000000000000000000d8f0a3aa4067be3d70a5b46a795ad9df9e65cd3c6001600160a01b0316611596612b4e565b6001600160a01b0316146115bc5760405162461bcd60e51b8152600401610ef890614205565b6115c582612b6a565b6115d182826001612b72565b5050565b6000306001600160a01b037f000000000000000000000000d8f0a3aa4067be3d70a5b46a795ad9df9e65cd3c16146116705760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610ef8565b506000805160206146f983398151915290565b60008061168f83612321565b91509150915091565b6116a0612d3f565b6116aa6000612d9e565b565b6033546001600160a01b031690565b6065546001600160a01b031633146116dd576116dd639a04794d60e01b612969565b6116e8878787612df0565b50505050505050565b6065546001600160a01b0316331461171357611713639a04794d60e01b612969565b61171e888887612df0565b5050505050505050565b611730612d3f565b6001600160a01b03811661174e5761174e63040b3bcf60e31b612969565b606580546001600160a01b0319166001600160a01b0392909216919091179055565b600061177b86613428565b80519091506001600160a01b0316331480159061180f5750336001600160a01b031681600001516001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061427b565b6001600160a01b031614155b15611823576118236282b42960e81b612969565b60008681526066602090815260409182902082516101c081018452815465ffffffffffff8082168352600160301b8204811694830194909452600160601b80820463ffffffff90811696840196909652600160801b820486166060840152600160a01b820485166080840152600160d01b90910490931660a08201819052600183015480861660c0840152600160201b8104861660e0840152600160401b8104909516610100830152929093046001600160a01b031661012084015260028101546001600160f01b038116610140850152600160f01b810460ff908116610160860152600160f81b909104811615156101808501526003909101541615156101a0830152158015906119805750611941610100840160e085016142a6565b80611957575061195760608401604085016142a6565b8061196a575061196a60208401846142a6565b80611980575061198060a08401608085016142a6565b1561199557611995637d5ba07f60e01b612969565b6119a260208401846142a6565b156119e0576119b460208701876142c3565b65ffffffffffff16156119d3576119ce60208701876142c3565b6119d5565b425b65ffffffffffff1681525b6119f060408401602085016142a6565b15611a1357611a0560408701602088016142c3565b65ffffffffffff1660208201525b611a2360608401604085016142a6565b15611a4457611a3860608701604088016142e0565b63ffffffff1660408201525b611a5460808401606085016142a6565b15611a7557611a6960808701606088016142e0565b63ffffffff1660608201525b611a8560a08401608085016142a6565b15611aa857611a9a60a08701608088016142c3565b65ffffffffffff1660808201525b611ab860c0840160a085016142a6565b15611ada57611ace610100870160e088016142e0565b63ffffffff1660e08201525b611aea60e0840160c085016142a6565b15611b1157611b0161014087016101208801613cc4565b6001600160a01b03166101208201525b611b22610100840160e085016142a6565b15611b6157611b39610180870161016088016142fd565b60ff16610160820152611b54610120870161010088016142e0565b63ffffffff166101008201525b611bb28186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bad92505050610100870160e088016142a6565b612973565b611bbf60208401846142a6565b15611bf05780516000888152606660205260409020805465ffffffffffff191665ffffffffffff9092169190911790555b611c0060408401602085016142a6565b15611c4157602080820151600089815260669092526040909120805465ffffffffffff909216600160301b0265ffffffffffff60301b199092169190911790555b611c5160608401604085016142a6565b15611c8d576040808201516000898152606660205291909120805463ffffffff909216600160601b0263ffffffff60601b199092169190911790555b611c9d60808401606085016142a6565b15611cd85760608101516000888152606660205260409020805463ffffffff909216600160801b0263ffffffff60801b199092169190911790555b611ce860a08401608085016142a6565b15611d275760808101516000888152606660205260409020805465ffffffffffff909216600160a01b0265ffffffffffff60a01b199092169190911790555b611d3760c0840160a085016142a6565b15611d755760e08101516000888152606660205260409020600101805463ffffffff909216600160201b0263ffffffff60201b199092169190911790555b611d8560e0840160c085016142a6565b15611dc657610120810151600088815260666020526040902060010180546001600160a01b03909216600160601b026001600160601b039092169190911790555b611dd7610100840160e085016142a6565b15611e59576000878152606760205260409020611df590868661384b565b50610160810151600088815260666020526040902060028101805460ff909316600160f01b0260ff60f01b19909316929092179091556101008201516001909101805463ffffffff909216600160401b0263ffffffff60401b199092169190911790555b60405187907f14c26fbe57d45444878cd034a1d26785710ec308068cb07e6d1d3ebde07ee5fe90600090a250505050505050565b611e95612d3f565b6001600160a01b038116611efa5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610ef8565b610f7e81612d9e565b600082815260666020908152604080832081516101c081018352815465ffffffffffff8082168352600160301b8204811683870152600160601b80830463ffffffff90811685880152600160801b84048116606080870191909152600160a01b850484166080870152600160d01b909404831660a08601908152600187015480831660c0880152600160201b808204841660e0890152600160401b820484166101008901529390046001600160a01b0390811661012088015260028801546001600160f01b038116610140890152600160f01b810460ff9081166101608a0152600160f81b9091048116151561018089015260039098015490971615156101a08701528b8a5260688952878a20968b168a529588529786902086519384018752549788168352870462ffffff1695820195909552600160381b9095046001600160c81b031692850192909252519092911661206857612068631e425da960e31b612969565b610180820151806120b357612086858460a00151856080015161276f565b905080156120b357600085815260666020526040902060020180546001600160f81b0316600160f81b1790555b6000858152606760205260408120805461217c91906120d190613fb2565b80601f01602080910402602001604051908101604052809291908181526020018280546120fd90613fb2565b801561214a5780601f1061211f5761010080835404028352916020019161214a565b820191906000526020600020905b81548152906001019060200180831161212d57829003601f168201915b50505050508561016001518461217257610e58876000015188604001518961010001516127d2565b8660c00151612841565b9050600081846000015163ffffffff166121969190614174565b905060008185604001516121aa91906141a3565b90506001600160c81b0381166121ca576121ca63196274cd60e31b612969565b60008881526068602090815260408083206001600160a01b038b1684528252909120805466ffffffffffffff16600160381b6001600160c81b0386160217905585015161221890600161431a565b60008981526068602090815260408083206001600160a01b038c168085529252808320805462ffffff95909516600160201b0262ffffff60201b19909516949094179093559151909182916001600160c81b038516908381818185875af1925050503d80600081146122a6576040519150601f19603f3d011682016040523d82523d6000602084013e6122ab565b606091505b5091509150816122c5576122c5637cd69c3960e11b612969565b604080516001600160c81b038086168252871660208201526001600160a01b038b16918c917f5e52ef8f94736e46374f2129ca32a992be1653b810bbb26e3b64b1a80e070aca910160405180910390a350505050505050505050565b600081815260666020908152604080832081516101c081018352815465ffffffffffff8082168352600160301b8204811695830195909552600160601b80820463ffffffff90811695840195909552600160801b820485166060840152600160a01b820486166080840152600160d01b90910490941660a0820152600182015480841660c0830152600160201b8104841660e0830152600160401b8104909316610100820152929091046001600160a01b031661012083015260028101546001600160f01b038116610140840152600160f01b810460ff908116610160850152600160f81b90910481161515610180840152600390910154161580156101a0830152829190612437575060009360019350915050565b60a081015165ffffffffffff166124545750600093849350915050565b6000816101800151806124755750612475858360a00151846080015161276f565b905060008161249b57612496836000015184604001518561010001516127d2565b6124a1565b8260c001515b905060006124c660676000898152602001908152602001600020805461119890613fb2565b9050612710818560a0015165ffffffffffff166124e39190614174565b6124f8906001600160c81b031661251c614341565b6125029190614360565b838061252357506125238560a001518463ffffffff16876101000151612889565b9550955050505050915091565b600080600061253e84613428565b80519091506001600160a01b031661258f5760405162461bcd60e51b8152602060048201526014602482015273159958dd1bdc88191bd95cdb89dd08195e1a5cdd60621b6044820152606401610ef8565b80606001511561262e578051602082015160405163ddf990f960e01b81526001600160601b0390911660048201526000916001600160a01b03169063ddf990f990602401600060405180830381865afa1580156125f0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526126189190810190614374565b9050806040015193508060200151925050612769565b80600001516001600160a01b031663047fc9aa6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561268c575060408051601f3d908101601f1916820190925261268991810190614416565b60015b6126fd5780600001516001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f69190614416565b9250612700565b92505b80600001516001600160a01b0316632ddcb21f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612742573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127669190614416565b91505b50915091565b600065ffffffffffff82161580159061279857508165ffffffffffff168365ffffffffffff1610155b156127a5575060016127cb565b6000806127b186612530565b91509150806000141580156127c65750808210155b925050505b9392505050565b60008365ffffffffffff1642116127eb575060006127cb565b600063ffffffff841661280665ffffffffffff87164261442f565b6128109190614360565b90508263ffffffff1681106128325761282a600184614446565b9150506127cb565b90506127cb565b509392505050565b60008061285160ff851684614463565b63ffffffff168581016020015190915061286c856008614486565b61287b9060ff166101006144af565b61ffff161c95945050505050565b6000808465ffffffffffff161180156128b157506128a8600183614446565b63ffffffff1683145b949350505050565b60608163ffffffff166001600160401b038111156128d9576128d9613b3e565b604051908082528060200260200182016040528015612902578160200160208202803683370190505b50905060005b8263ffffffff168163ffffffff16101561283957612927858583612841565b828263ffffffff168151811061293f5761293f6144ca565b6001600160c81b039092166020928302919091019091015280612961816144e0565b915050612908565b8060005260046000fd5b604083015163ffffffff16158061299657506101208301516001600160a01b0316155b806129ac5750600283610100015163ffffffff16105b806129bf5750602083610160015160ff16115b156129d4576129d4634b3c503560e11b612969565b602083015165ffffffffffff1615612a4357826020015165ffffffffffff1683604001516001856101000151612a0a9190614446565b612a149190614463565b8451612a269163ffffffff1690614504565b65ffffffffffff1610612a4357612a43634b3c503560e11b612969565b801561151657815183610100015184610160015160ff16612a649190614463565b63ffffffff1614612a7f57612a7f634b3c503560e11b612969565b6000612a96838561016001518661010001516128b9565b9050600081600081518110612aad57612aad6144ca565b602090810291909101015161010086015190915063ffffffff1660015b86610100015163ffffffff168110156116e857826001600160c81b0316848281518110612af957612af96144ca565b60200260200101516001600160c81b031610612b1f57612b1f634b3c503560e11b612969565b838181518110612b3157612b316144ca565b602002602001015192508080612b4690614525565b915050612aca565b6000805160206146f9833981519152546001600160a01b031690565b610f7e612d3f565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612ba557611516836134c8565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612bff575060408051601f3d908101601f19168201909252612bfc91810190614416565b60015b612c625760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610ef8565b6000805160206146f98339815191528114612cd15760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610ef8565b50611516838383613562565b6001600160a01b03163b151590565b600054610100900460ff16612d135760405162461bcd60e51b8152600401610ef890614540565b612d1b61358d565b606580546001600160a01b0319166001600160a01b0384161790556115d181612d9e565b33612d486116ac565b6001600160a01b0316146116aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610ef8565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600083815260666020908152604080832081516101c081018352815465ffffffffffff8082168352600160301b8204811683870152600160601b80830463ffffffff90811685880152600160801b84048116606080870191909152600160a01b850484166080870152600160d01b90940490921660a08501908152600186015480841660c0870152600160201b808204851660e0880152600160401b820485166101008801529290046001600160a01b0390811661012087015260028701546001600160f01b038116610140880152600160f01b810460ff908116610160890152600160f81b9091048116151561018088015260039097015490961615156101a08601528b895260688852868920958b1689529487528588208651938401875254808316845290810462ffffff1696830196909652600160381b9095046001600160c81b031693810193909352905190939192612f509190861690614504565b835190915065ffffffffffff16421080612f8b5750826020015165ffffffffffff1642118015612f8b5750602083015165ffffffffffff1615155b80612fbf5750608083015165ffffffffffff1615801590612fbf5750826080015165ffffffffffff168165ffffffffffff16115b80612ffc5750606083015163ffffffff1615801590612ffc5750826060015163ffffffff16848360000151612ff4919061458b565b63ffffffff16115b8061302a575060e083015163ffffffff161580159061302a57508260e0015163ffffffff168463ffffffff16115b8061303757508261018001515b1561304c5761304c63201dc6f560e01b612969565b6000613066846000015185604001518661010001516127d2565b90506000613115606760008a8152602001908152602001600020805461308b90613fb2565b80601f01602080910402602001604051908101604052809291908181526020018280546130b790613fb2565b80156131045780601f106130d957610100808354040283529160200191613104565b820191906000526020600020905b8154815290600101906020018083116130e757829003601f168201915b505050505086610160015184612841565b9050600061312963ffffffff881683614174565b905034816001600160c81b0316111561314c5761314c637e2897ef60e11b612969565b8263ffffffff168660c0015163ffffffff1614613188576000898152606660205260409020600101805463ffffffff191663ffffffff85161790555b600089815260666020526040902080546001600160d01b0316600160d01b65ffffffffffff8716021790556101408601516131cd906001600160c81b038316906145aa565b60008a815260666020526040902060020180546001600160f01b0319166001600160f01b039290921691909117905584518790869061320d90839061458b565b63ffffffff1690525060408501805134919061322a9083906145cc565b6001600160c81b0390811690915260008b81526068602090815260408083206001600160a01b038e16845282529182902089518154928b0151938b0151909416600160381b0266ffffffffffffff62ffffff909416600160201b0266ffffffffffffff1990931663ffffffff909516949094179190911791909116919091179055506101a0860151156133d75760006127106132c8836101f4614174565b6132d29190614255565b905060008761012001516001600160a01b031682846132f191906141a3565b6001600160c81b031660405160006040518083038185875af1925050503d806000811461333a576040519150601f19603f3d011682016040523d82523d6000602084013e61333f565b606091505b505090508061335857613358637cd69c3960e11b612969565b60006133626116ac565b6001600160a01b0316836001600160c81b031660405160006040518083038185875af1925050503d80600081146133b5576040519150601f19603f3d011682016040523d82523d6000602084013e6133ba565b606091505b50509050806133d3576133d3637cd69c3960e11b612969565b5050505b604080516001600160c81b038416815263ffffffff891660208201526001600160a01b038a16918b917f71c0c8850819ac31eeb7ba034624f403ddf922c2fbfe1b6af1644a61a8e019ee91016113ec565b6040805160c081018252600080825260208201819052818301819052606082018190526080820181905260a0820152606554915162820a0360e31b81526004810184905290916001600160a01b03169063041050189060240160c060405180830381865afa15801561349e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c291906145f9565b92915050565b6134d181612cdd565b6135335760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610ef8565b6000805160206146f983398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61356b836135bc565b6000825111806135785750805b156115165761358783836135fc565b50505050565b600054610100900460ff166135b45760405162461bcd60e51b8152600401610ef890614540565b6116aa613621565b6135c5816134c8565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606127cb838360405180606001604052806027815260200161471960279139613651565b600054610100900460ff166136485760405162461bcd60e51b8152600401610ef890614540565b6116aa33612d9e565b6060600080856001600160a01b03168560405161366e91906146a9565b600060405180830381855af49150503d80600081146136a9576040519150601f19603f3d011682016040523d82523d6000602084013e6136ae565b606091505b50915091506127c6868383876060831561372457825161371d576136d185612cdd565b61371d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610ef8565b50816128b1565b6128b183838151156137395781518083602001fd5b8060405162461bcd60e51b8152600401610ef891906146c5565b604080516101c081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915290565b8280546137d390613fb2565b90600052602060002090601f0160209004810192826137f5576000855561383b565b82601f1061380e57805160ff191683800117855561383b565b8280016001018555821561383b579182015b8281111561383b578251825591602001919060010190613820565b506138479291506138bf565b5090565b82805461385790613fb2565b90600052602060002090601f016020900481019282613879576000855561383b565b82601f106138925782800160ff1982351617855561383b565b8280016001018555821561383b579182015b8281111561383b5782358255916020019190600101906138a4565b5b8082111561384757600081556001016138c0565b6000602082840312156138e657600080fd5b5035919050565b805165ffffffffffff1682526020810151613912602084018265ffffffffffff169052565b50604081015161392a604084018263ffffffff169052565b506060810151613942606084018263ffffffff169052565b50608081015161395c608084018265ffffffffffff169052565b5060a081015161397660a084018265ffffffffffff169052565b5060c081015161398e60c084018263ffffffff169052565b5060e08101516139a660e084018263ffffffff169052565b506101008181015163ffffffff1690830152610120808201516001600160a01b031690830152610140808201516001600160f01b0316908301526101608082015160ff1690830152610180808201511515908301526101a08082015180151582850152613587565b60005b83811015613a29578181015183820152602001613a11565b838111156135875750506000910152565b60008151808452613a52816020860160208601613a0e565b601f01601f19169290920160200192915050565b60006101e0613a7583866138ed565b806101c0840152613a8881840185613a3a565b95945050505050565b60006102c0808301613aa3848e6138ed565b6101c08401919091528a51908190526102e0830190602090818d0160005b82811015613ae65781516001600160c81b031685529383019390830190600101613ac1565b5050506001600160c81b038b166101e0850152509050876102008301528661022083015285610240830152613b2061026083018615159052565b9215156102808201529015156102a090910152979650505050505050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613b7657613b76613b3e565b60405290565b604051601f8201601f191681016001600160401b0381118282101715613ba457613ba4613b3e565b604052919050565b60006001600160401b03821115613bc557613bc5613b3e565b50601f01601f191660200190565b600082601f830112613be457600080fd5b8135613bf7613bf282613bac565b613b7c565b818152846020838601011115613c0c57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613c3c57600080fd5b8235915060208301356001600160401b03811115613c5957600080fd5b613c6585828601613bd3565b9150509250929050565b6001600160a01b0381168114610f7e57600080fd5b8035613c8f81613c6f565b919050565b60008060408385031215613ca757600080fd5b823591506020830135613cb981613c6f565b809150509250929050565b600060208284031215613cd657600080fd5b81356127cb81613c6f565b60008060408385031215613cf457600080fd5b8235613cff81613c6f565b91506020830135613cb981613c6f565b60008060408385031215613d2257600080fd5b8235613d2d81613c6f565b915060208301356001600160401b03811115613c5957600080fd5b63ffffffff81168114610f7e57600080fd5b600060c08284031215613d6c57600080fd5b50919050565b60008083601f840112613d8457600080fd5b5081356001600160401b03811115613d9b57600080fd5b602083019150836020828501011115610ea857600080fd5b6000806000806000806000610160888a031215613dcf57600080fd5b873596506020880135613de181613c6f565b95506040880135613df181613d48565b94506060880135613e0181613c6f565b9350613e108960808a01613d5a565b92506101408801356001600160401b03811115613e2c57600080fd5b613e388a828b01613d72565b989b979a50959850939692959293505050565b600080600080600080600080610160898b031215613e6857600080fd5b883597506020890135613e7a81613c6f565b965060408901356001600160401b0380821115613e9657600080fd5b818b0191508b601f830112613eaa57600080fd5b813581811115613eb957600080fd5b8c60208260051b8501011115613ece57600080fd5b6020830198509650613ee260608c01613c84565b9550613ef18c60808d01613d5a565b94506101408b0135915080821115613f0857600080fd5b50613f158b828c01613d72565b999c989b5096995094979396929594505050565b6000806000806000858703610300811215613f4357600080fd5b863595506101c0601f1982011215613f5a57600080fd5b6020870194506101e08701356001600160401b03811115613f7a57600080fd5b613f8689828a01613d72565b9095509350506101006101ff1982011215613fa057600080fd5b50610200860190509295509295909350565b600181811c90821680613fc657607f821691505b60208210811415613d6c57634e487b7160e01b600052602260045260246000fd5b65ffffffffffff81168114610f7e57600080fd5b8051613c8f81613d48565b60ff81168114610f7e57600080fd5b8051613c8f81614006565b8051613c8f81613c6f565b6000614039613bf284613bac565b905082815283838301111561404d57600080fd5b6127cb836020830184613a0e565b600082601f83011261406c57600080fd5b6127cb8383516020850161402b565b6000806000806000806000806000806101408b8d03121561409b57600080fd5b8a516140a681613fe7565b60208c0151909a506140b781613fe7565b60408c01519099506140c881613d48565b60608c01519098506140d981613d48565b60808c01519097506140ea81613fe7565b95506140f860a08c01613ffb565b945061410660c08c01613ffb565b935061411460e08c01614015565b92506141236101008c01614020565b6101208c01519092506001600160401b0381111561414057600080fd5b61414c8d828e0161405b565b9150509295989b9194979a5092959850565b634e487b7160e01b600052601160045260246000fd5b60006001600160c81b038281168482168115158284048211161561419a5761419a61415e565b02949350505050565b60006001600160c81b03838116908316818110156141c3576141c361415e565b039392505050565b6020808252602c908201526000805160206146d983398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201526000805160206146d983398151915260408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052601260045260246000fd5b60006001600160c81b038381168061426f5761426f61423f565b92169190910492915050565b60006020828403121561428d57600080fd5b81516127cb81613c6f565b8015158114610f7e57600080fd5b6000602082840312156142b857600080fd5b81356127cb81614298565b6000602082840312156142d557600080fd5b81356127cb81613fe7565b6000602082840312156142f257600080fd5b81356127cb81613d48565b60006020828403121561430f57600080fd5b81356127cb81614006565b600062ffffff8083168185168083038211156143385761433861415e565b01949350505050565b600081600019048311821515161561435b5761435b61415e565b500290565b60008261436f5761436f61423f565b500490565b60006020828403121561438657600080fd5b81516001600160401b038082111561439d57600080fd5b90830190608082860312156143b157600080fd5b6143b9613b54565b8251828111156143c857600080fd5b83019150601f820186136143db57600080fd5b6143ea8683516020850161402b565b815260208301516020820152604083015160408201526060830151606082015280935050505092915050565b60006020828403121561442857600080fd5b5051919050565b6000828210156144415761444161415e565b500390565b600063ffffffff838116908316818110156141c3576141c361415e565b600063ffffffff8083168185168183048111821515161561419a5761419a61415e565b600060ff821660ff84168160ff04811182151516156144a7576144a761415e565b029392505050565b600061ffff838116908316818110156141c3576141c361415e565b634e487b7160e01b600052603260045260246000fd5b600063ffffffff808316818114156144fa576144fa61415e565b6001019392505050565b600065ffffffffffff8083168185168083038211156143385761433861415e565b60006000198214156145395761453961415e565b5060010190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600063ffffffff8083168185168083038211156143385761433861415e565b60006001600160f01b038281168482168083038211156143385761433861415e565b60006001600160c81b038281168482168083038211156143385761433861415e565b8051613c8f81614298565b600060c0828403121561460b57600080fd5b60405160c081016001600160401b038111828210171561462d5761462d613b3e565b604052825161463b81613c6f565b815260208301516001600160601b038116811461465757600080fd5b6020820152604083015161466a81613c6f565b604082015261467b606084016145ee565b606082015261468c608084016145ee565b608082015261469d60a084016145ee565b60a08201529392505050565b600082516146bb818460208701613a0e565b9190910192915050565b6020815260006127cb6020830184613a3a56fe46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080a000a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.