ERC-721
Overview
Max Total Supply
0 DRIVERS
Holders
19
Total Transfers
-
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
DriversLimitedEditions
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.17; /** ########## ########## ##### ##### ##### ############ ########## ########## ############ ############ ##### ##### ##### ############ ############ ############ ##### ##### ##### ###### ##### ##### ##### ############ ##### ###### ###### ###### ##### ##### ##### ##### ##### ##### ##### ##### ##### ##### ###### ###### ##### ##### ##### ##### ##### #### #### ##### ##### ##### ####### ##### ##### ##### ##### ##### #### #### ########## ##### ##### ########## ##### ##### ########### ##### #### #### ########## ########### ########### ##### ##### ############ ##### #### #### ##### ############ ####### ##### ##### ##### ##### ##### #### #### ##### ##### ##### ###### ###### ##### ##### ##### ##### ##### ########## ############ ##### ##### ###### ###### ############ ##### ##### ##### ######## ############ ##### ##### ############ ########## ##### ##### ##### #### ############ ##### ##### ########## By Everfresh */ import "./ERC721Base.sol"; import "fount-contracts/utils/Withdraw.sol"; import "./interfaces/IDriversPayments.sol"; /** * @author Fount Gallery * @title Drivers Limited Editions by Everfresh * @notice Drivers is celebrated motion artist Everfresh's first Fount Gallery release. Driven by * the rhythm of skate culture and dance, the Drivers collection delivers an immersive world of * form and flow. * * Features: * - Mixed 1/1 and limited edition NFTs * - Auctions with "Buy it now" for 1/1 NFTs * - Flexible collecting conditions with EIP-712 signatures or on-chain Fount Card checks * - Swappable metadata contract * - On-chain royalties standard (EIP-2981) * - Support for OpenSea's Operator Filterer to allow royalties */ contract DriversLimitedEditions is ERC721Base, Withdraw { /* ------------------------------------------------------------------------ S T O R A G E ------------------------------------------------------------------------ */ /// @dev Cap for edition sizes. Also used to generate token ids for editions. uint256 internal constant MAX_EDITION_SIZE = 1000; /// @dev Stores information about a sale for a given token struct TokenData { uint128 price; uint16 editionSize; uint16 collected; bool fountExclusive; bool requiresSig; bool freeToCollect; } /// @dev Mapping of base token id to token data mapping(uint256 => TokenData) internal _baseIdToTokenData; /// @dev General auction config uint256 public auctionTimeBuffer = 5 minutes; uint256 public auctionIncPercentage = 10; /// @dev Auction config for a specific token auction struct AuctionData { uint32 duration; uint32 startTime; uint32 firstBidTime; address highestBidder; uint128 highestBid; uint128 reservePrice; } /// @dev Mapping of base token id to auction data mapping(uint256 => AuctionData) public auctions; /// @dev Counter to keep track of active auctions. Prevents withdrawals unless zero. uint256 public activeAuctions; /// @notice Address where proceeds should be sent address public payments; /// @dev Toggle to allow collecting bool internal _isSaleLive; /* ------------------------------------------------------------------------ M O D I F I E R S ------------------------------------------------------------------------ */ /** * @dev Makes sure that the sale is live before proceeding */ modifier onlyWhenSaleIsLive() { if (!_isSaleLive) revert SaleNotLive(); _; } /* ------------------------------------------------------------------------ E R R O R S ------------------------------------------------------------------------ */ /** TOKEN DATA ---------------------------------------------------------- */ error TokenDataDoesNotExist(); error TokenDataAlreadyExists(); error InvalidBaseId(); error CannotSetEditionSizeToZero(); /** SALE CONDITIONS ---------------------------------------------------- */ error SaleNotLive(); error RequiresFountCard(); error RequiresSignature(); error InvalidSignature(); /** PURCHASING --------------------------------------------------------- */ error NotForSale(); error IncorrectPaymentAmount(); /** ONE OF ONES -------------------------------------------------------- */ error NotOneOfOne(); /** AUCTIONS ----------------------------------------------------------- */ error AuctionDoesNotExist(); error AuctionNotStarted(); error AuctionAlreadyExists(); error AuctionAlreadyStarted(); error AuctionReserveNotMet(uint256 reserve, uint256 sent); error AuctionMinimumBidNotMet(uint256 minBid, uint256 sent); error AuctionNotEnded(); error AuctionEnded(); error AuctionAlreadySettled(); error AlreadySold(); error CannotSetAuctionDurationToZero(); error CannotSetAuctionStartTimeToZero(); error CannotSetAuctionReservePriceToZero(); error CannotWithdrawWithActiveAuctions(); /** EDITIONS ----------------------------------------------------------- */ error NotEdition(); error EditionSoldOut(); error EditionSizeLessThanCurrentlySold(); error EditionSizeExceedsMaxValue(); /** PAYMENTS ----------------------------------------------------------- */ error CannotSetPaymentAddressToZero(); /* ------------------------------------------------------------------------ E V E N T S ------------------------------------------------------------------------ */ event TokenDataAdded(uint256 indexed id, TokenData tokenData); event TokenDataSalePriceUpdated(uint256 indexed id, TokenData tokenData); event TokenDataSaleConditionsUpdated(uint256 indexed id, TokenData tokenData); event AuctionCreated(uint256 indexed id, AuctionData auction); event AuctionBid(uint256 indexed id, AuctionData auction); event AuctionSettled(uint256 indexed id, AuctionData auction); event AuctionSoldEarly(uint256 indexed id, AuctionData auction); event AuctionCancelled(uint256 indexed id); event AuctionDurationUpdated(uint256 indexed id, uint256 indexed duration); event AuctionStartTimeUpdated(uint256 indexed id, uint256 indexed startTime); event AuctionReservePriceUpdated(uint256 indexed id, uint256 indexed reservePrice); event CollectedOneOfOne(uint256 indexed id); event CollectedEdition( uint256 indexed baseId, uint256 indexed editionNumber, uint256 indexed tokenId ); /* ------------------------------------------------------------------------ I N I T ------------------------------------------------------------------------ */ /** * @param owner_ The owner of the contract * @param admin_ The admin of the contract * @param payments_ The address where payments should be sent * @param royaltiesAmount_ The royalty percentage with two decimals (10,000 = 100%) * @param metadata_ The initial metadata contract address * @param fountCard_ The address of the Fount Gallery Patron Card */ constructor( address owner_, address admin_, address payments_, uint256 royaltiesAmount_, address metadata_, address fountCard_ ) ERC721Base(owner_, admin_, payments_, royaltiesAmount_, metadata_, fountCard_) { payments = payments_; } /* ------------------------------------------------------------------------ O N E O F O N E S ------------------------------------------------------------------------ */ /** BUY NOW ------------------------------------------------------------ */ /** * @notice Collects a 1/1 NFT that's available for sale * @dev Calls internal `_collectOneOfOne` for additional logic and minting. * * Reverts if: * - the sale requires an off-chain signature * - see `_collectOneOfOne` for other conditions * * @param baseId The base id of the token to collect * @param to The address to collect the token to */ function collectOneOfOne(uint256 baseId, address to) external payable onlyWhenSaleIsLive { TokenData memory tokenData = _baseIdToTokenData[baseId]; if (tokenData.requiresSig) revert RequiresSignature(); _collectOneOfOne(baseId, to, tokenData); } /** * @notice Collects a 1/1 NFT that's available for sale using an off-chain signature * @dev Calls internal `_collectOneOfOne` for additional logic and minting. * * Reverts if: * - the signature provided is not valid * - see `_collectOneOfOne` for other conditions * * @param baseId The base id of the token to collect * @param to The address to collect the token to * @param signature The off-chain signature that permits a mint */ function collectOneOfOne( uint256 baseId, address to, bytes calldata signature ) external payable onlyWhenSaleIsLive { TokenData memory tokenData = _baseIdToTokenData[baseId]; if (tokenData.requiresSig && !_verifyMintSignature(baseId, to, signature)) { revert InvalidSignature(); } _collectOneOfOne(baseId, to, tokenData); } /** * @notice Internal logic for minting 1/1 NFTs * @dev Handles collecting a 1/1 when there's also an active auction e.g. "Buy it now" * * Reverts if: * - the token is not a 1/1 * - msg.value does not equal the required amount * - the token requires a Fount Card, but `to` does not hold one * - the token has already been minted * * @param baseId The base id of the token to collect * @param to The address to collect the token to * @param tokenData Information about the token */ function _collectOneOfOne( uint256 baseId, address to, TokenData memory tokenData ) internal { if (tokenData.editionSize != 1) revert NotOneOfOne(); if (!tokenData.freeToCollect && tokenData.price == 0) revert NotForSale(); if (tokenData.price != msg.value) revert IncorrectPaymentAmount(); if (tokenData.fountExclusive && !_isFountCardHolder(to)) revert RequiresFountCard(); // If there is an auction for this token and it has bids, // then refund the highest bidder, and end the auction early. AuctionData memory auction = auctions[baseId]; if (auction.firstBidTime > 0) { // End the auction by setting the duration to "end" at the current block timestamp. // This will prevent new bids on the auction since it will revert with `AuctionEnded`. auction.duration = uint32(block.timestamp - auction.firstBidTime); auctions[baseId] = auction; // Refund the highest bidder _transferETHWithFallback(auction.highestBidder, auction.highestBid); // Decrease the active auctions count unchecked { --activeAuctions; } emit AuctionSoldEarly(baseId, auction); } // Record the mint in the token data unchecked { ++tokenData.collected; } _baseIdToTokenData[baseId] = tokenData; // Transfer the NFT from Everfresh to the `to` address _transferFromArtist(to, baseId); emit CollectedOneOfOne(baseId); } /** AUCTION BIDS ------------------------------------------------------- */ /** * @notice Places a bid for a token * @dev Calls internal `_placeBid` function for logic. * * Reverts if: * - the token requires an off-chain signature * - see `_placeBid` for other conditions * * @param baseId The base id of the token to register a bid for */ function placeBid(uint256 baseId) external payable onlyWhenSaleIsLive { TokenData memory tokenData = _baseIdToTokenData[baseId]; if (tokenData.requiresSig) revert RequiresSignature(); _placeBid(baseId, tokenData); } /** * @notice Places a bid for a token with an off-chain signature * @dev Calls internal `_placeBid` function for logic. * * Reverts if: * - the token requires an off-chain signature and the signature is invalid * - see `_placeBid` for other conditions * * @param baseId The base id of the token to register a bid for * @param signature The off-chain signature that permits a mint */ function placeBid(uint256 baseId, bytes calldata signature) external payable onlyWhenSaleIsLive { TokenData memory tokenData = _baseIdToTokenData[baseId]; if (tokenData.requiresSig && !_verifyMintSignature(baseId, msg.sender, signature)) { revert InvalidSignature(); } _placeBid(baseId, tokenData); } /** * @notice Internal function to place a bid for a token * @dev Takes the amount of ETH sent as the bid. If the bid is the new highest bid, * then the previous highest bidder is refunded (in WETH if the refund fails with ETH). * If a bid is placed within the auction time buffer then the buffer is added to the * time remaining on the auction e.g. extends by 5 minutes. * * Reverts if: * - the token requires a Fount Card, but msg.sender does not hold one * - the auction has not yet started * - the auction has ended * - the auction reserve bid has not been met if it's the first bid * - the bid does not meet the minimum (increment percentage of current highest bid) * * @param baseId The base id of the token to register a bid for * @param tokenData Information about the token */ function _placeBid(uint256 baseId, TokenData memory tokenData) internal { // Check msg.sender qualifies to bid if (tokenData.fountExclusive && !_isFountCardHolder(msg.sender)) revert RequiresFountCard(); // Load the auction AuctionData memory auction = auctions[baseId]; // Check auction is ready to accept bids if (auction.startTime == 0 || auction.startTime > block.timestamp) { revert AuctionNotStarted(); } // If first bid, start the auction if (auction.firstBidTime == 0) { // Check the first bid meets the reserve if (auction.reservePrice > msg.value) { revert AuctionReserveNotMet(auction.reservePrice, msg.value); } // Save the bid time auction.firstBidTime = uint32(block.timestamp); } else { // Check it hasn't ended if (block.timestamp > (auction.firstBidTime + auction.duration)) revert AuctionEnded(); // Check the value sent meets the minimum price increase uint256 highestBid = auction.highestBid; uint256 minBid; unchecked { minBid = highestBid + ((highestBid * auctionIncPercentage) / 100); } if (minBid > msg.value) revert AuctionMinimumBidNotMet(minBid, msg.value); // Refund the previous highest bid _transferETHWithFallback(auction.highestBidder, highestBid); } // Save the new highest bid and bidder auction.highestBid = uint96(msg.value); auction.highestBidder = msg.sender; // Calculate the time remaining uint256 timeRemaining; unchecked { timeRemaining = auction.firstBidTime + auction.duration - block.timestamp; } // If bid is placed within the time buffer of the auction ending, increase the duration if (timeRemaining < auctionTimeBuffer) { unchecked { auction.duration += uint32(auctionTimeBuffer - timeRemaining); } } // Save the new auction data auctions[baseId] = auction; // Emit event emit AuctionBid(baseId, auction); } /** AUCTION SETTLEMENT ------------------------------------------------- */ /** * @notice Allows the winner to settle the auction which mints of their new NFT * @dev Mints the NFT to the highest bidder (winner) only once the auction is over. * Can be called by anyone so Fount Gallery can pay the gas if needed. * * Reverts if: * - the auction hasn't started yet * - the auction is not over * - the token has already been sold via `collectOneOfOne` * * @param baseId The base id of token to settle the auction for */ function settleAuction(uint256 baseId) external { AuctionData memory auction = auctions[baseId]; // Check auction has started if (auction.firstBidTime == 0) revert AuctionNotStarted(); // Check auction has ended if (auction.firstBidTime + auction.duration > block.timestamp) revert AuctionNotEnded(); // Transfer the NFT to the highest bidder if (_ownerOf[baseId] != everfresh) revert AlreadySold(); _transferFromArtist(auction.highestBidder, baseId); emit CollectedOneOfOne(baseId); // Decrease the active auctions count unchecked { --activeAuctions; } // Emit event emit AuctionSettled(baseId, auction); } /* ------------------------------------------------------------------------ L I M I T E D E D I T I O N S ------------------------------------------------------------------------ */ /** * @notice Mints the next edition of a limited edition NFT * @dev Calls internal `_collectEdition` for logic. * * Reverts if: * - the edition requires an off-chain signature * - see `_collectEdition` for other conditions * * @param baseId The base NFT id of the edition * @param to The address to mint the token to */ function collectEdition(uint256 baseId, address to) external payable onlyWhenSaleIsLive { TokenData memory tokenData = _baseIdToTokenData[baseId]; if (tokenData.requiresSig) revert RequiresSignature(); _collectEdition(baseId, to, tokenData); } /** * @notice Mints the next edition of a limited edition NFT with an off-chain signature * @dev Calls internal `_collectEdition` for logic. * * Reverts if: * - the edition requires an off-chain signature and the signature is invalid * - see `_collectEdition` for other conditions * * @param baseId The base NFT id of the edition * @param to The address to mint the token to * @param signature The off-chain signature which permits a mint */ function collectEdition( uint256 baseId, address to, bytes calldata signature ) external payable onlyWhenSaleIsLive { TokenData memory tokenData = _baseIdToTokenData[baseId]; if (tokenData.requiresSig && !_verifyMintSignature(baseId, to, signature)) { revert InvalidSignature(); } _collectEdition(baseId, to, tokenData); } /** * @notice Internal function to collect the next edition with some conditions * @dev Allows collecting to a different address from msg.sender. * * Reverts if: * - the token is not an edition * - the edition is sold out * - msg.value does not equal the required amount * - the edition requires a Fount Card, but `to` does not hold one * * @param baseId The base NFT id of the edition * @param to The address to collect the token to * @param tokenData Information about the token */ function _collectEdition( uint256 baseId, address to, TokenData memory tokenData ) internal { // Check to see if the next edition is collectable and the price is correct if (tokenData.editionSize < 2) revert NotEdition(); if (tokenData.collected + 1 > tokenData.editionSize) revert EditionSoldOut(); if (!tokenData.freeToCollect && tokenData.price == 0) revert NotForSale(); if (tokenData.price != msg.value) revert IncorrectPaymentAmount(); // Check if it's a Fount Gallery exclusive if (tokenData.fountExclusive && !_isFountCardHolder(to)) revert RequiresFountCard(); // Get the next edition number and token id uint256 editionNumber = tokenData.collected + 1; uint256 tokenId = _getEditionTokenId(baseId, editionNumber); // Add the new mint to the token data unchecked { ++tokenData.collected; } _baseIdToTokenData[baseId] = tokenData; // Transfer the NFT from Everfresh to the `to` address _transferFromArtist(to, tokenId); emit CollectedEdition(baseId, editionNumber, tokenId); } /** UTILS -------------------------------------------------------------- */ /** * @notice Internal function to get the token id for an edition * @param baseId The base NFT id of the edition * @param editionNumber The edition number to make the token id for * @return tokenId The token id for the edition */ function _getEditionTokenId(uint256 baseId, uint256 editionNumber) internal pure returns (uint256) { return baseId * MAX_EDITION_SIZE + editionNumber; } /** * @notice Get the token id for a specific edition number * @param baseId The base NFT id of the edition * @param editionNumber The edition number to make the token id for * @return tokenId The token id for the edition */ function getEditionTokenId(uint256 baseId, uint256 editionNumber) external pure returns (uint256) { return _getEditionTokenId(baseId, editionNumber); } /** * @notice Get the edition number from a token id * @dev Returns `0` if it's not an edition * @param tokenId The token id for the edition * @return editionNumber The edition number e.g. 2 of 10 */ function getEditionNumberFromTokenId(uint256 tokenId) external pure returns (uint256) { if (tokenId >= MAX_EDITION_SIZE) return 0; return tokenId % MAX_EDITION_SIZE; } /** * @notice Get the base NFT id from a token id * @dev Returns the token id argument if it's not an edition * @param tokenId The token id for the edition * @return baseId The base NFT id e.g. 2 from "2004" */ function getEditionBaseIdFromTokenId(uint256 tokenId) external pure returns (uint256) { if (tokenId >= MAX_EDITION_SIZE) return tokenId; return tokenId / MAX_EDITION_SIZE; } /* ------------------------------------------------------------------------ A D M I N ------------------------------------------------------------------------ */ /** ADD TOKEN DATA ----------------------------------------------------- */ /** * @notice Admin function to make a token available for sale * @dev As soon as the token data is registered, the NFT will be available to collect provided * a price has been set. This prevents auctions without a "buy it now" price from being * purchased for free unintentionally. * * If a free mint is intended, set `price` to zero and `freeMint` to true. * * Reverts if: * - the edition size exeeds the max allowed value (`MAX_EDITION_SIZE`) * - the token data already exists (to update token data, use the other admin * functions to set price and sale conditions) * * @param baseId The base NFT id * @param price The sale price (buy it now for auctions) * @param editionSize The size of the edition. Set to 1 for one of one NFTs. * @param fountExclusive If the sale requires a Fount Gallery Patron card * @param requiresSig If the sale requires an off-chain signature * @param freeMint If the sale requires an off-chain signature */ function addTokenForSale( uint256 baseId, uint128 price, uint16 editionSize, bool fountExclusive, bool requiresSig, bool freeMint ) external onlyOwnerOrAdmin { // Check the baseId is valid if (baseId > type(uint256).max / MAX_EDITION_SIZE) revert InvalidBaseId(); // Check a valid edition size has been used if (editionSize == 0) revert CannotSetEditionSizeToZero(); // Check the edition size does not exceed the max if (editionSize > MAX_EDITION_SIZE - 1) revert EditionSizeExceedsMaxValue(); TokenData memory tokenData = _baseIdToTokenData[baseId]; // Check the token data is empty before adding if (tokenData.editionSize != 0) revert TokenDataAlreadyExists(); // Set the new token data tokenData.price = price; tokenData.editionSize = editionSize; tokenData.fountExclusive = fountExclusive; tokenData.requiresSig = requiresSig; tokenData.freeToCollect = freeMint; _baseIdToTokenData[baseId] = tokenData; emit TokenDataAdded(baseId, tokenData); // Mint to Everfresh if (editionSize == 1) { _mint(everfresh, baseId); } else { for (uint256 i = 0; i < editionSize; i++) { _mint(everfresh, _getEditionTokenId(baseId, i + 1)); } } } /** SET SALE PRICE ----------------------------------------------------- */ /** * @notice Admin function to update the sale price for a token * @dev Reverts if the token data does not exist. Must be added with `addTokenForSale` first. * @param baseId The base NFT id * @param price The new sale price * @param freeMint If the NFT can be minted for free */ function setTokenSalePrice( uint256 baseId, uint128 price, bool freeMint ) external onlyOwnerOrAdmin { TokenData memory tokenData = _baseIdToTokenData[baseId]; // Check the token data already exists. // If not, it should be created with `addTokenForSale` first. if (tokenData.editionSize == 0) revert TokenDataDoesNotExist(); // Set the new sale price tokenData.price = price; tokenData.freeToCollect = freeMint; _baseIdToTokenData[baseId] = tokenData; emit TokenDataSalePriceUpdated(baseId, tokenData); } /** SET SALE CONDITIONS ------------------------------------------------ */ /** * @notice Admin function to update the sale conditions for a token * @dev Reverts if the token data does not exist. Must be added with `addTokenForSale` first. * @param baseId The base NFT id * @param fountExclusive If the sale requires a Fount Gallery Patron card * @param requiresSig If the sale requires an off-chain signature */ function setTokenSaleConditions( uint256 baseId, bool fountExclusive, bool requiresSig ) external onlyOwnerOrAdmin { TokenData memory tokenData = _baseIdToTokenData[baseId]; // Check the token data already exists. // If not, it should be created with `addTokenForSale` first. if (tokenData.editionSize == 0) revert TokenDataDoesNotExist(); tokenData.fountExclusive = fountExclusive; tokenData.requiresSig = requiresSig; _baseIdToTokenData[baseId] = tokenData; emit TokenDataSaleConditionsUpdated(baseId, tokenData); } /** AUCTION CREATION --------------------------------------------------- */ /** * @notice Admin function to create an auction for a 1/1 * @dev Can only create auctions for 1/1 NFTs, not editions. * * Reverts if: * - the token is not a 1/1 * - the auction already exists * * @param baseId The base NFT id */ function createAuction( uint256 baseId, uint32 duration, uint32 startTime, uint128 reservePrice ) external onlyOwnerOrAdmin { if (duration == 0) revert CannotSetAuctionDurationToZero(); if (startTime == 0) revert CannotSetAuctionStartTimeToZero(); // Check if the token data exists and it's a 1/1 TokenData memory tokenData = _baseIdToTokenData[baseId]; if (tokenData.editionSize != 1) revert NotOneOfOne(); // Load the auction data AuctionData memory auction = auctions[baseId]; // Check there's no auction already if (auction.startTime > 0) revert AuctionAlreadyExists(); // Create the auction data auction.duration = duration; auction.startTime = startTime; auction.reservePrice = reservePrice; auctions[baseId] = auction; // Increment active auctions counter unchecked { ++activeAuctions; } // Emit created event emit AuctionCreated(baseId, auction); } /** AUCTION CANCELLATION ----------------------------------------------- */ /** * @notice Admin function to cancel an auction * @dev Calls internal `_cancelAuction` for logic. * @param baseId The base NFT id */ function cancelAuction(uint256 baseId) external onlyOwnerOrAdmin { AuctionData memory auction = auctions[baseId]; _cancelAuction(baseId, auction); } /** * @notice Internal function for cancelling an auction * @dev Cancels the auction by refunding the highest bid and deleting the data * * Reverts if: * - the auctions has ended (in case it hasn't been settled yet) * * @param baseId The base NFT id * @param auction The auction data to determine conditions and refunds */ function _cancelAuction(uint256 baseId, AuctionData memory auction) internal { if (auction.firstBidTime > 0) { // Prevent cancelling if the auction has ended in case it hasn't been settled yet if (block.timestamp > (auction.firstBidTime + auction.duration)) revert AuctionEnded(); // Refund the highest bidder _transferETHWithFallback(auction.highestBidder, auction.highestBid); } // Delete the auction data and reduce the active auction count delete auctions[baseId]; unchecked { --activeAuctions; } emit AuctionCancelled(baseId); } /** AUCTION DURATION --------------------------------------------------- */ /** * @notice Admin function to set the duration of a specific auction * @dev Emits an `AuctionDurationUpdated` event if successful * * Reverts if: * - `duration` is zero * - the auction does not exist * - the auction already has bids * * @param baseId The base NFT id * @param duration The new auction duration */ function setAuctionDuration(uint256 baseId, uint32 duration) external onlyOwnerOrAdmin { if (duration == 0) revert CannotSetAuctionDurationToZero(); AuctionData memory auction = auctions[baseId]; if (auction.startTime == 0) revert AuctionDoesNotExist(); if (auction.firstBidTime > 0) revert AuctionAlreadyStarted(); auction.duration = duration; auctions[baseId] = auction; emit AuctionDurationUpdated(baseId, duration); } /** AUCTION START TIME ------------------------------------------------- */ /** * @notice Admin function to set the start time of a specific auction * @dev Emits an `AuctionStartTimeUpdated` event if successful * * Reverts if: * - `startTime` is zero * - the auction does not exist * - the auction already has bids * * @param baseId The base NFT id * @param startTime The new auction start time */ function setAuctionStartTime(uint256 baseId, uint32 startTime) external onlyOwnerOrAdmin { if (startTime == 0) revert CannotSetAuctionStartTimeToZero(); AuctionData memory auction = auctions[baseId]; if (auction.startTime == 0) revert AuctionDoesNotExist(); if (auction.firstBidTime > 0) revert AuctionAlreadyStarted(); auction.startTime = startTime; auctions[baseId] = auction; emit AuctionStartTimeUpdated(baseId, startTime); } /** AUCTION RESERVE PRICE ---------------------------------------------- */ /** * @notice Admin function to set the reserve price of a specific auction * @dev Emits an `AuctionReservePriceUpdated` event if successful * * Reverts if: * - `reservePrice` is zero * - the auction does not exist * - the auction already has bids * * @param baseId The base NFT id * @param reservePrice The new auction start time */ function setAuctionReservePrice(uint256 baseId, uint128 reservePrice) external onlyOwnerOrAdmin { if (reservePrice == 0) revert CannotSetAuctionReservePriceToZero(); AuctionData memory auction = auctions[baseId]; if (auction.startTime == 0) revert AuctionDoesNotExist(); if (auction.firstBidTime > 0) revert AuctionAlreadyStarted(); auction.reservePrice = reservePrice; auctions[baseId] = auction; emit AuctionReservePriceUpdated(baseId, reservePrice); } /** TAKE SALE LIVE ----------------------------------------------------- */ /** * @notice Admin function to set the sale live state * @dev If set to false, then collecting will be paused. * @param isLive Whether the sale is live or not */ function setSaleLiveState(bool isLive) external onlyOwnerOrAdmin { _isSaleLive = isLive; } /** PAYMENTS ----------------------------------------------------------- */ /** * @notice Admin function to set the payment address for withdrawing funds * @param paymentAddress The new address where payments should be sent upon withdrawal */ function setPaymentAddress(address paymentAddress) external onlyOwnerOrAdmin { if (paymentAddress == address(0)) revert CannotSetPaymentAddressToZero(); payments = paymentAddress; } /* ------------------------------------------------------------------------ G E T T E R S ------------------------------------------------------------------------ */ function tokenPrice(uint256 baseId) external view returns (uint256) { return _baseIdToTokenData[baseId].price; } function tokenIsOneOfOne(uint256 baseId) external view returns (bool) { return _baseIdToTokenData[baseId].editionSize == 1; } function tokenIsEdition(uint256 baseId) external view returns (bool) { return _baseIdToTokenData[baseId].editionSize > 1; } function tokenEditionSize(uint256 baseId) external view returns (uint256) { return _baseIdToTokenData[baseId].editionSize; } function tokenCollectedCount(uint256 baseId) external view returns (uint256) { return _baseIdToTokenData[baseId].collected; } function tokenIsFountExclusive(uint256 baseId) external view returns (bool) { return _baseIdToTokenData[baseId].fountExclusive; } function tokenRequiresOffChainSignatureToCollect(uint256 baseId) external view returns (bool) { return _baseIdToTokenData[baseId].requiresSig; } function tokenIsFreeToCollect(uint256 baseId) external view returns (bool) { TokenData memory tokenData = _baseIdToTokenData[baseId]; return tokenData.price == 0 && tokenData.freeToCollect; } function auctionHasStarted(uint256 baseId) external view returns (bool) { return auctions[baseId].firstBidTime > 0; } function auctionStartTime(uint256 baseId) external view returns (uint256) { return auctions[baseId].startTime; } function auctionHasEnded(uint256 baseId) external view returns (bool) { AuctionData memory auction = auctions[baseId]; bool hasStarted = auctions[baseId].firstBidTime > 0; return hasStarted && block.timestamp >= auction.firstBidTime + auction.duration; } function auctionEndTime(uint256 baseId) external view returns (uint256) { AuctionData memory auction = auctions[baseId]; bool hasStarted = auctions[baseId].firstBidTime > 0; return hasStarted ? auction.startTime + auction.duration : 0; } function auctionDuration(uint256 baseId) external view returns (uint256) { return auctions[baseId].duration; } function auctionFirstBidTime(uint256 baseId) external view returns (uint256) { return auctions[baseId].firstBidTime; } function auctionHighestBidder(uint256 baseId) external view returns (address) { return auctions[baseId].highestBidder; } function auctionHighestBid(uint256 baseId) external view returns (uint256) { return auctions[baseId].highestBid; } function auctionReservePrice(uint256 baseId) external view returns (uint256) { return auctions[baseId].reservePrice; } /* ------------------------------------------------------------------------ W I T H D R A W ------------------------------------------------------------------------ */ /** * @notice Admin function to withdraw ETH from this contract * @dev Withdraws to the `payments` address. * * Reverts if: * - there are active auctions * - the payments address is set to zero * */ function withdrawETH() public onlyOwnerOrAdmin { // Check there are no active auctions if (activeAuctions > 0) revert CannotWithdrawWithActiveAuctions(); // Send the eth to the payments address _withdrawETH(payments); } /** * @notice Admin function to withdraw ETH from this contract and release from payments contract * @dev Withdraws to the `payments` address, then calls `releaseAllETH` as a splitter. * * Reverts if: * - there are active auctions * - the payments address is set to zero * */ function withdrawAndReleaseAllETH() public onlyOwnerOrAdmin { // Check there are no active auctions if (activeAuctions > 0) revert CannotWithdrawWithActiveAuctions(); // Send the eth to the payments address _withdrawETH(payments); // And then release all the ETH to the payees IDriversPayments(payments).releaseAllETH(); } /** * @notice Admin function to withdraw ERC-20 tokens from this contract * @dev Withdraws to the `payments` address. * * Reverts if: * - the payments address is set to zero * */ function withdrawTokens(address tokenAddress) public onlyOwnerOrAdmin { // Send the tokens to the payments address _withdrawToken(tokenAddress, payments); } /** * @notice Admin function to withdraw ERC-20 tokens from this contract * @param to The address to send the ERC-20 tokens to */ function withdrawTokens(address tokenAddress, address to) public onlyOwnerOrAdmin { _withdrawToken(tokenAddress, to); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Optimized and flexible operator filterer to abide to OpenSea's /// mandatory on-chain royalty enforcement in order for new collections to /// receive royalties. /// For more information, see: /// See: https://github.com/ProjectOpenSea/operator-filter-registry abstract contract OperatorFilterer { /// @dev The default OpenSea operator blocklist subscription. address internal constant _DEFAULT_SUBSCRIPTION = 0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6; /// @dev The OpenSea operator filter registry. address internal constant _OPERATOR_FILTER_REGISTRY = 0x000000000000AAeB6D7670E522A718067333cd4E; /// @dev Registers the current contract to OpenSea's operator filter, /// and subscribe to the default OpenSea operator blocklist. /// Note: Will not revert nor update existing settings for repeated registration. function _registerForOperatorFiltering() internal virtual { _registerForOperatorFiltering(_DEFAULT_SUBSCRIPTION, true); } /// @dev Registers the current contract to OpenSea's operator filter. /// Note: Will not revert nor update existing settings for repeated registration. function _registerForOperatorFiltering(address subscriptionOrRegistrantToCopy, bool subscribe) internal virtual { /// @solidity memory-safe-assembly assembly { let functionSelector := 0x7d3e3dbe // `registerAndSubscribe(address,address)`. // Clean the upper 96 bits of `subscriptionOrRegistrantToCopy` in case they are dirty. subscriptionOrRegistrantToCopy := shr(96, shl(96, subscriptionOrRegistrantToCopy)) for {} iszero(subscribe) {} { if iszero(subscriptionOrRegistrantToCopy) { functionSelector := 0x4420e486 // `register(address)`. break } functionSelector := 0xa0af2903 // `registerAndCopyEntries(address,address)`. break } // Store the function selector. mstore(0x00, shl(224, functionSelector)) // Store the `address(this)`. mstore(0x04, address()) // Store the `subscriptionOrRegistrantToCopy`. mstore(0x24, subscriptionOrRegistrantToCopy) // Register into the registry. if iszero(call(gas(), _OPERATOR_FILTER_REGISTRY, 0, 0x00, 0x44, 0x00, 0x04)) { // If the function selector has not been overwritten, // it is an out-of-gas error. if eq(shr(224, mload(0x00)), functionSelector) { // To prevent gas under-estimation. revert(0, 0) } } // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, because of Solidity's memory size limits. mstore(0x24, 0) } } /// @dev Modifier to guard a function and revert if the caller is a blocked operator. modifier onlyAllowedOperator(address from) virtual { if (from != msg.sender) { if (!_isPriorityOperator(msg.sender)) { if (_operatorFilteringEnabled()) _revertIfBlocked(msg.sender); } } _; } /// @dev Modifier to guard a function from approving a blocked operator.. modifier onlyAllowedOperatorApproval(address operator) virtual { if (!_isPriorityOperator(operator)) { if (_operatorFilteringEnabled()) _revertIfBlocked(operator); } _; } /// @dev Helper function that reverts if the `operator` is blocked by the registry. function _revertIfBlocked(address operator) private view { /// @solidity memory-safe-assembly assembly { // Store the function selector of `isOperatorAllowed(address,address)`, // shifted left by 6 bytes, which is enough for 8tb of memory. // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL). mstore(0x00, 0xc6171134001122334455) // Store the `address(this)`. mstore(0x1a, address()) // Store the `operator`. mstore(0x3a, operator) // `isOperatorAllowed` always returns true if it does not revert. if iszero(staticcall(gas(), _OPERATOR_FILTER_REGISTRY, 0x16, 0x44, 0x00, 0x00)) { // Bubble up the revert if the staticcall reverts. returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) } // We'll skip checking if `from` is inside the blacklist. // Even though that can block transferring out of wrapper contracts, // we don't want tokens to be stuck. // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, if less than 8tb of memory is used. mstore(0x3a, 0) } } /// @dev For deriving contracts to override, so that operator filtering /// can be turned on / off. /// Returns true by default. function _operatorFilteringEnabled() internal view virtual returns (bool) { return true; } /// @dev For deriving contracts to override, so that preferred marketplaces can /// skip operator filtering, helping users save gas. /// Returns false for all inputs by default. function _isPriorityOperator(address) internal view virtual returns (bool) { return false; } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.15; /** * @author Sam King (samkingstudio.eth) for Fount Gallery * @title Simple owner and admin authentication * @notice Allows the management of a contract by using simple ownership and admin modifiers. */ abstract contract Auth { /* ------------------------------------------------------------------------ S T O R A G E ------------------------------------------------------------------------ */ /// @notice Current owner of the contract address public owner; /// @notice Current admins of the contract mapping(address => bool) public admins; /* ------------------------------------------------------------------------ E V E N T S ------------------------------------------------------------------------ */ /** * @notice When the contract owner is updated * @param user The account that updated the new owner * @param newOwner The new owner of the contract */ event OwnerUpdated(address indexed user, address indexed newOwner); /** * @notice When an admin is added to the contract * @param user The account that added the new admin * @param newAdmin The admin that was added */ event AdminAdded(address indexed user, address indexed newAdmin); /** * @notice When an admin is removed from the contract * @param user The account that removed an admin * @param prevAdmin The admin that got removed */ event AdminRemoved(address indexed user, address indexed prevAdmin); /* ------------------------------------------------------------------------ M O D I F I E R S ------------------------------------------------------------------------ */ /** * @dev Only the owner can call */ modifier onlyOwner() { require(msg.sender == owner, "UNAUTHORIZED"); _; } /** * @dev Only an admin can call */ modifier onlyAdmin() { require(admins[msg.sender], "UNAUTHORIZED"); _; } /** * @dev Only the owner or an admin can call */ modifier onlyOwnerOrAdmin() { require((msg.sender == owner || admins[msg.sender]), "UNAUTHORIZED"); _; } /* ------------------------------------------------------------------------ I N I T ------------------------------------------------------------------------ */ /** * @dev Sets the initial owner and a first admin upon creation. * @param owner_ The initial owner of the contract * @param admin_ An initial admin of the contract */ constructor(address owner_, address admin_) { owner = owner_; emit OwnerUpdated(address(0), owner_); admins[admin_] = true; emit AdminAdded(address(0), admin_); } /* ------------------------------------------------------------------------ A D M I N ------------------------------------------------------------------------ */ /** * @notice Transfers ownership of the contract to `newOwner` * @dev Can only be called by the current owner or an admin * @param newOwner The new owner of the contract */ function setOwner(address newOwner) public virtual onlyOwnerOrAdmin { owner = newOwner; emit OwnerUpdated(msg.sender, newOwner); } /** * @notice Adds `newAdmin` as an amdin of the contract * @dev Can only be called by the current owner or an admin * @param newAdmin A new admin of the contract */ function addAdmin(address newAdmin) public virtual onlyOwnerOrAdmin { admins[newAdmin] = true; emit AdminAdded(address(0), newAdmin); } /** * @notice Removes `prevAdmin` as an amdin of the contract * @dev Can only be called by the current owner or an admin * @param prevAdmin The admin to remove */ function removeAdmin(address prevAdmin) public virtual onlyOwnerOrAdmin { admins[prevAdmin] = false; emit AdminRemoved(address(0), prevAdmin); } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.15; import "openzeppelin/token/ERC1155/IERC1155.sol"; /** * @author Sam King (samkingstudio.eth) for Fount Gallery * @title Fount Gallery Card Check * @notice Utility functions to check ownership of a Fount Gallery Patron Card NFT */ contract FountCardCheck { /// @dev Address of the Fount Gallery Patron Card contract IERC1155 internal _fountCard; /// @dev Does not own a Fount Gallery Patron Card error NotFountCardHolder(); /** * @dev Does not own enough Fount Gallery Patron Cards * @param required The minimum amount of cards that need to be owned * @param owned The actualy amount of cards owned */ error DoesNotHoldEnoughFountCards(uint256 required, uint256 owned); /** * @dev Init with the Fount Gallery Patron Card contract address * @param fountCard The Fount Gallery Patron Card contract address */ constructor(address fountCard) { _fountCard = IERC1155(fountCard); } /** * @dev Modifier that only allows the caller to do something if they hold * a Fount Gallery Patron Card */ modifier onlyWhenFountCardHolder() { if (_getFountCardBalance(msg.sender) < 1) revert NotFountCardHolder(); _; } /** * @dev Modifier that only allows the caller to do something if they hold * at least a specific amount Fount Gallery Patron Cards * @param minAmount The minimum amount of cards that need to be owned */ modifier onlyWhenHoldingMinFountCards(uint256 minAmount) { uint256 balance = _getFountCardBalance(msg.sender); if (minAmount > balance) revert DoesNotHoldEnoughFountCards(minAmount, balance); _; } /** * @dev Get the number of Fount Gallery Patron Cards an address owns * @param owner The owner address to query * @return balance The balance of the owner */ function _getFountCardBalance(address owner) internal view returns (uint256 balance) { balance = _fountCard.balanceOf(owner, 1); } /** * @dev Check if an address holds at least one Fount Gallery Patron Card * @param owner The owner address to query * @return isHolder If the owner holds at least one card */ function _isFountCardHolder(address owner) internal view returns (bool isHolder) { isHolder = _getFountCardBalance(owner) > 0; } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.15; /** * @author Sam King (samkingstudio.eth) for Fount Gallery * @title Swappable metadata module * @notice Allows the use of a separate and swappable metadata contract */ abstract contract SwappableMetadata { /* ------------------------------------------------------------------------ S T O R A G E ------------------------------------------------------------------------ */ /// @notice Address of metadata contract address public metadata; /// @notice Flag for whether the metadata address can be updated or not bool public isMetadataLocked; /* ------------------------------------------------------------------------ E R R O R S ------------------------------------------------------------------------ */ error MetadataLocked(); /* ------------------------------------------------------------------------ E V E N T S ------------------------------------------------------------------------ */ /** * @dev When the metadata contract has been set * @param metadataContract The new metadata contract address */ event MetadataContractSet(address indexed metadataContract); /** * @dev When the metadata contract has been locked and is no longer swappable * @param metadataContract The final locked metadata contract address */ event MetadataContractLocked(address indexed metadataContract); /* ------------------------------------------------------------------------ I N I T ------------------------------------------------------------------------ */ /** * @param metadata_ The address of the initial metadata contract */ constructor(address metadata_) { metadata = metadata_; emit MetadataContractSet(metadata_); } /* ------------------------------------------------------------------------ A D M I N ------------------------------------------------------------------------ */ /** * @notice Sets the metadata address * @param metadata_ The new address of the metadata contract */ function _setMetadataAddress(address metadata_) internal { if (isMetadataLocked) revert MetadataLocked(); metadata = metadata_; emit MetadataContractSet(metadata_); } /** * @notice Sets the metadata address * @param metadata The new address of the metadata contract */ function setMetadataAddress(address metadata) public virtual; /** * @dev Locks the metadata address preventing further updates */ function _lockMetadata() internal { isMetadataLocked = true; emit MetadataContractLocked(metadata); } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.15; import "openzeppelin/interfaces/IERC2981.sol"; /** * @author Sam King (samkingstudio.eth) for Fount Gallery * @title Royalty payments * @notice Support for the royalty standard (ERC-2981) */ abstract contract Royalties is IERC2981 { /* ------------------------------------------------------------------------ S T O R A G E ------------------------------------------------------------------------ */ /// @dev Store information about token royalties struct RoyaltyInfo { address receiver; uint96 amount; } /// @dev The current royalty information RoyaltyInfo internal _royaltyInfo; /// @dev Interface id for the royalty information standard /// bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a bytes4 internal constant ROYALTY_INTERFACE_ID = 0x2a55205a; /* ------------------------------------------------------------------------ E R R O R S ------------------------------------------------------------------------ */ error MoreThanOneHundredPercentRoyalty(); /* ------------------------------------------------------------------------ E V E N T S ------------------------------------------------------------------------ */ event RoyaltyInfoSet(address indexed receiver, uint256 indexed amount); event RoyaltyInfoUpdated(address indexed receiver, uint256 indexed amount); /* ------------------------------------------------------------------------ I N I T ------------------------------------------------------------------------ */ /** * @param royaltiesReceiver The receiver of royalty payments * @param royaltiesAmount The royalty percentage with two decimals (10,000 = 100%) */ constructor(address royaltiesReceiver, uint256 royaltiesAmount) { _royaltyInfo = RoyaltyInfo(royaltiesReceiver, uint96(royaltiesAmount)); emit RoyaltyInfoSet(royaltiesReceiver, royaltiesAmount); } /* ------------------------------------------------------------------------ E R C 2 9 8 1 ------------------------------------------------------------------------ */ /// @notice EIP-2981 royalty standard for on-chain royalties function royaltyInfo(uint256, uint256 salePrice) public view virtual returns (address receiver, uint256 royaltyAmount) { receiver = _royaltyInfo.receiver; royaltyAmount = (salePrice * _royaltyInfo.amount) / 100_00; } /* ------------------------------------------------------------------------ A D M I N ------------------------------------------------------------------------ */ /** * @dev Internal function to set the royalty information * @param receiver The receiver of royalty payments * @param amount The royalty percentage with two decimals (10,000 = 100%) */ function _setRoyaltyInfo(address receiver, uint256 amount) internal { if (amount > 100_00) revert MoreThanOneHundredPercentRoyalty(); _royaltyInfo = RoyaltyInfo(receiver, uint24(amount)); emit RoyaltyInfoUpdated(receiver, amount); } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.15; import "openzeppelin/token/ERC20/IERC20.sol"; import "openzeppelin/token/ERC721/IERC721.sol"; import "openzeppelin/token/ERC1155/IERC1155.sol"; /** * @author Sam King (samkingstudio.eth) for Fount Gallery * @title Withdraw ETH and tokens module * @notice Allows the withdrawal of ETH, ERC20, ERC721, an ERC1155 tokens */ abstract contract Withdraw { /* ------------------------------------------------------------------------ E R R O R S ------------------------------------------------------------------------ */ error CannotWithdrawToZeroAddress(); error WithdrawFailed(); error BalanceTooLow(); error ZeroBalance(); /* ------------------------------------------------------------------------ W I T H D R A W ------------------------------------------------------------------------ */ function _withdrawETH(address to) internal { // Prevent withdrawing to the zero address if (to == address(0)) revert CannotWithdrawToZeroAddress(); // Check there is eth to withdraw uint256 balance = address(this).balance; if (balance == 0) revert ZeroBalance(); // Transfer funds (bool success, ) = payable(to).call{value: balance}(""); if (!success) revert WithdrawFailed(); } function _withdrawToken(address tokenAddress, address to) internal { // Prevent withdrawing to the zero address if (to == address(0)) revert CannotWithdrawToZeroAddress(); // Check there are tokens to withdraw uint256 balance = IERC20(tokenAddress).balanceOf(address(this)); if (balance == 0) revert ZeroBalance(); // Transfer tokens bool success = IERC20(tokenAddress).transfer(to, balance); if (!success) revert WithdrawFailed(); } function _withdrawERC721Token( address tokenAddress, uint256 id, address to ) internal { // Prevent withdrawing to the zero address if (to == address(0)) revert CannotWithdrawToZeroAddress(); // Check the NFT is in this contract address owner = IERC721(tokenAddress).ownerOf(id); if (owner != address(this)) revert ZeroBalance(); // Transfer NFT IERC721(tokenAddress).transferFrom(address(this), to, id); } function _withdrawERC1155Token( address tokenAddress, uint256 id, uint256 amount, address to ) internal { // Prevent withdrawing to the zero address if (to == address(0)) revert CannotWithdrawToZeroAddress(); // Check the tokens are owned by this contract, and there's at least `amount` uint256 balance = IERC1155(tokenAddress).balanceOf(address(this), id); if (balance == 0) revert ZeroBalance(); if (amount > balance) revert BalanceTooLow(); // Transfer tokens IERC1155(tokenAddress).safeTransferFrom(address(this), to, id, amount, ""); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; address private immutable _CACHED_THIS; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _CACHED_THIS = address(this); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _ownerOf; mapping(address => uint256) internal _balanceOf; function ownerOf(uint256 id) public view virtual returns (address owner) { require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); } function balanceOf(address owner) public view virtual returns (uint256) { require(owner != address(0), "ZERO_ADDRESS"); return _balanceOf[owner]; } /*////////////////////////////////////////////////////////////// ERC721 APPROVAL STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner = _ownerOf[id]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[from]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(_ownerOf[id] == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. unchecked { _balanceOf[to]++; } _ownerOf[id] = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner = _ownerOf[id]; require(owner != address(0), "NOT_MINTED"); // Ownership check above ensures no underflow. unchecked { _balanceOf[owner]--; } delete _ownerOf[id]; delete getApproved[id]; emit Transfer(owner, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint( address to, uint256 id, bytes memory data ) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } } /// @notice A generic interface for a contract which properly accepts ERC721 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721TokenReceiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.17; import "solmate/tokens/ERC721.sol"; import "fount-contracts/auth/Auth.sol"; import "fount-contracts/community/FountCardCheck.sol"; import "fount-contracts/extensions/SwappableMetadata.sol"; import "fount-contracts/utils/Royalties.sol"; import "closedsea/OperatorFilterer.sol"; import "openzeppelin/utils/cryptography/ECDSA.sol"; import "openzeppelin/utils/cryptography/EIP712.sol"; import "openzeppelin/token/ERC20/IERC20.sol"; import "./interfaces/IMetadata.sol"; import "./interfaces/IWETH.sol"; /** * @author Fount Gallery * @title ERC721Base * @notice Base contract for Drivers Limited Editions to inherit from * * Features: * - EIP-712 signature minting and verification * - On-chain checking of Fount Gallery Patron cards for minting * - Swappable metadata contract * - On-chain royalties standard (EIP-2981) * - Support for OpenSea's Operator Filterer to allow royalties * - Safe transferring of ETH with WETH fallback */ abstract contract ERC721Base is ERC721, Auth, FountCardCheck, SwappableMetadata, Royalties, EIP712, OperatorFilterer { /* ------------------------------------------------------------------------ S T O R A G E ------------------------------------------------------------------------ */ /// @notice everfresh.eth address public everfresh = 0xBb3444a06E9928dDA9a739CdAb3E0c5cf6890099; /// @notice Contract information string public contractURI; /// @notice EIP-712 signing domain string public constant SIGNING_DOMAIN = "DriversLimitedEditions"; /// @notice EIP-712 signature version string public constant SIGNATURE_VERSION = "1"; /// @notice EIP-712 signed data type hash for minting with an off-chain signature bytes32 public constant MINT_SIGNATURE_TYPEHASH = keccak256("MintSignatureData(uint256 id,address to,uint256 nonce)"); /// @dev EIP-712 signed data struct for minting with an off-chain signature struct MintSignatureData { uint256 id; address to; uint256 nonce; bytes signature; } /// @notice Approved signer public addresses mapping(address => bool) public approvedSigners; /// @notice Nonce management to avoid signature replay attacks mapping(address => uint256) public nonces; /// @notice If operator filtering is applied bool public operatorFilteringEnabled; /// @notice Wrapped ETH contract address for safe ETH transfer fallbacks address public weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; /* ------------------------------------------------------------------------ E V E N T S ------------------------------------------------------------------------ */ event Init(); /* ------------------------------------------------------------------------ I N I T ------------------------------------------------------------------------ */ /** * @param owner_ The owner of the contract * @param admin_ The admin of the contract * @param royaltiesReceiver_ The address where royalties should be sent * @param royaltiesAmount_ The royalty percentage with two decimals (10,000 = 100%) * @param metadata_ The initial metadata contract address * @param fountCard_ The address of the Fount Gallery Patron Card */ constructor( address owner_, address admin_, address royaltiesReceiver_, uint256 royaltiesAmount_, address metadata_, address fountCard_ ) ERC721("Drivers Limited Editions by Everfresh", "DRIVERS") Auth(owner_, admin_) FountCardCheck(fountCard_) SwappableMetadata(metadata_) Royalties(royaltiesReceiver_, royaltiesAmount_) EIP712(SIGNING_DOMAIN, SIGNATURE_VERSION) { _registerForOperatorFiltering(); operatorFilteringEnabled = true; emit Init(); } /* ------------------------------------------------------------------------ A R T I S T M I N T I N G ------------------------------------------------------------------------ */ function _transferFromArtist(address to, uint256 id) internal { require(everfresh == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[everfresh]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(everfresh, to, id); } /* ------------------------------------------------------------------------ S I G N A T U R E V E R I F I C A T I O N ------------------------------------------------------------------------ */ /** * @notice Internal function to verify an EIP-712 minting signature * @param id The base NFT id * @param to The account that has approval to mint * @param signature The EIP-712 signature * @return bool If the signature is verified or not */ function _verifyMintSignature( uint256 id, address to, bytes calldata signature ) internal returns (bool) { MintSignatureData memory data = MintSignatureData({ id: id, to: to, nonce: nonces[to], signature: signature }); // Hash the data for verification bytes32 digest = _hashTypedDataV4( keccak256(abi.encode(MINT_SIGNATURE_TYPEHASH, data.id, data.to, nonces[data.to]++)) ); // Verifiy signature is ok address addr = ECDSA.recover(digest, data.signature); return approvedSigners[addr] && addr != address(0); } /* ------------------------------------------------------------------------ A D M I N ------------------------------------------------------------------------ */ /** SIGNERS ------------------------------------------------------------ */ /** * @notice Admin function to set an EIP-712 signer address * @param signer The address of the new signer * @param approved If the signer is approved */ function setSigner(address signer, bool approved) external onlyOwnerOrAdmin { approvedSigners[signer] = approved; } /** METADATA ----------------------------------------------------------- */ /** * @notice Admin function to set the metadata contract address * @param metadata The new metadata contract address */ function setMetadataAddress(address metadata) public override onlyOwnerOrAdmin { _setMetadataAddress(metadata); } /** * @notice Admin function to set the contract URI for marketplaces * @param contractURI_ The new contract URI */ function setContractURI(string memory contractURI_) external onlyOwnerOrAdmin { contractURI = contractURI_; } /** ROYALTIES ---------------------------------------------------------- */ /** * @notice Admin function to set the royalty information * @param receiver The receiver of royalty payments * @param amount The royalty percentage with two decimals (10,000 = 100%) */ function setRoyaltyInfo(address receiver, uint256 amount) external onlyOwnerOrAdmin { _setRoyaltyInfo(receiver, amount); } /** * @notice Admin function to set whether OpenSea's Operator Filtering should be enabled * @param enabled If the operator filtering should be enabled */ function setOperatorFilteringEnabled(bool enabled) external onlyOwnerOrAdmin { operatorFilteringEnabled = enabled; } function registerForOperatorFiltering(address subscriptionOrRegistrantToCopy, bool subscribe) external onlyOwnerOrAdmin { _registerForOperatorFiltering(subscriptionOrRegistrantToCopy, subscribe); } /* ------------------------------------------------------------------------ S A F E T R A N S F E R S ------------------------------------------------------------------------ */ /** * @notice Safely transfer ETH by wrapping as WETH if the ETH transfer fails * @param to The address to transfer ETH/WETH to * @param amount The amount of ETH/WETH to transfer */ function _transferETHWithFallback(address to, uint256 amount) internal { if (!_transferETH(to, amount)) { IWETH(weth).deposit{value: amount}(); IERC20(weth).transfer(to, amount); } } /** * @notice Transfer ETH and return the success status. * @param to The address to transfer ETH to * @param amount The amount of ETH to transfer */ function _transferETH(address to, uint256 amount) internal returns (bool) { (bool success, ) = payable(to).call{value: amount}(new bytes(0)); return success; } /* ------------------------------------------------------------------------ R O T A L T I E S ------------------------------------------------------------------------ */ /** * @notice Add interface for on-chain royalty standard */ function supportsInterface(bytes4 interfaceId) public view override(ERC721, IERC165) returns (bool) { return interfaceId == ROYALTY_INTERFACE_ID || super.supportsInterface(interfaceId); } /** * @notice Repeats the OpenSea Operator Filtering registration */ function repeatRegistration() public { _registerForOperatorFiltering(); } /** * @notice Override ERC-721 `setApprovalForAll` to support OpenSea Operator Filtering */ function setApprovalForAll(address operator, bool approved) public override onlyAllowedOperatorApproval(operator) { super.setApprovalForAll(operator, approved); } /** * @notice Override ERC-721 `approve` to support OpenSea Operator Filtering */ function approve(address operator, uint256 id) public override onlyAllowedOperatorApproval(operator) { super.approve(operator, id); } /** * @notice Override ERC-721 `transferFrom` to support OpenSea Operator Filtering */ function transferFrom( address from, address to, uint256 id ) public override onlyAllowedOperator(from) { super.transferFrom(from, to, id); } /** * @notice Override ERC-721 `safeTransferFrom` to support OpenSea Operator Filtering */ function safeTransferFrom( address from, address to, uint256 id ) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, id); } /** * @notice Override ERC-721 `safeTransferFrom` to support OpenSea Operator Filtering */ function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, id, data); } /** * @dev Overrde `OperatorFilterer._operatorFilteringEnabled` to return whether * the operator filtering is enabled in this contract. */ function _operatorFilteringEnabled() internal view virtual override returns (bool) { return operatorFilteringEnabled; } /* ------------------------------------------------------------------------ E R C 7 2 1 ------------------------------------------------------------------------ */ /** * @notice Returns the token metadata * @return id The token id to get metadata for */ function tokenURI(uint256 id) public view override returns (string memory) { return IMetadata(metadata).tokenURI(id); } /** * @notice Burn a token. You can only burn tokens you own. * @param id The token id to burn */ function burn(uint256 id) external { require(ownerOf(id) == msg.sender, "NOT_OWNER"); _burn(id); } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.17; interface IDriversPayments { function releaseAllETH() external; function releaseAllToken(address tokenAddress) external; }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.17; interface IMetadata { function tokenURI(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.17; interface IWETH { function deposit() external payable; function withdraw(uint256 wad) external; function transfer(address to, uint256 value) external returns (bool); }
{ "remappings": [ "closedsea/=packages/contracts/lib/closedsea/src/", "ds-test/=packages/contracts/lib/ds-test/src/", "erc4626-tests/=packages/contracts/lib/closedsea/lib/openzeppelin-contracts/lib/erc4626-tests/", "erc721a-upgradeable/=packages/contracts/lib/closedsea/lib/erc721a-upgradeable/contracts/", "erc721a/=packages/contracts/lib/closedsea/lib/erc721a/contracts/", "ethier/=packages/contracts/lib/fount-contracts/lib/ethier/", "forge-std/=packages/contracts/lib/forge-std/src/", "fount-contracts/=packages/contracts/lib/fount-contracts/src/", "fount-drivers/=packages/contracts/src/", "openzeppelin-contracts-upgradeable/=packages/contracts/lib/closedsea/lib/openzeppelin-contracts-upgradeable/contracts/", "openzeppelin-contracts/=packages/contracts/lib/openzeppelin-contracts/", "openzeppelin/=packages/contracts/lib/openzeppelin-contracts/contracts/", "operator-filter-registry/=packages/contracts/lib/closedsea/lib/operator-filter-registry/src/", "solmate/=packages/contracts/lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"address","name":"payments_","type":"address"},{"internalType":"uint256","name":"royaltiesAmount_","type":"uint256"},{"internalType":"address","name":"metadata_","type":"address"},{"internalType":"address","name":"fountCard_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadySold","type":"error"},{"inputs":[],"name":"AuctionAlreadyExists","type":"error"},{"inputs":[],"name":"AuctionAlreadySettled","type":"error"},{"inputs":[],"name":"AuctionAlreadyStarted","type":"error"},{"inputs":[],"name":"AuctionDoesNotExist","type":"error"},{"inputs":[],"name":"AuctionEnded","type":"error"},{"inputs":[{"internalType":"uint256","name":"minBid","type":"uint256"},{"internalType":"uint256","name":"sent","type":"uint256"}],"name":"AuctionMinimumBidNotMet","type":"error"},{"inputs":[],"name":"AuctionNotEnded","type":"error"},{"inputs":[],"name":"AuctionNotStarted","type":"error"},{"inputs":[{"internalType":"uint256","name":"reserve","type":"uint256"},{"internalType":"uint256","name":"sent","type":"uint256"}],"name":"AuctionReserveNotMet","type":"error"},{"inputs":[],"name":"BalanceTooLow","type":"error"},{"inputs":[],"name":"CannotSetAuctionDurationToZero","type":"error"},{"inputs":[],"name":"CannotSetAuctionReservePriceToZero","type":"error"},{"inputs":[],"name":"CannotSetAuctionStartTimeToZero","type":"error"},{"inputs":[],"name":"CannotSetEditionSizeToZero","type":"error"},{"inputs":[],"name":"CannotSetPaymentAddressToZero","type":"error"},{"inputs":[],"name":"CannotWithdrawToZeroAddress","type":"error"},{"inputs":[],"name":"CannotWithdrawWithActiveAuctions","type":"error"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"},{"internalType":"uint256","name":"owned","type":"uint256"}],"name":"DoesNotHoldEnoughFountCards","type":"error"},{"inputs":[],"name":"EditionSizeExceedsMaxValue","type":"error"},{"inputs":[],"name":"EditionSizeLessThanCurrentlySold","type":"error"},{"inputs":[],"name":"EditionSoldOut","type":"error"},{"inputs":[],"name":"IncorrectPaymentAmount","type":"error"},{"inputs":[],"name":"InvalidBaseId","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"MetadataLocked","type":"error"},{"inputs":[],"name":"MoreThanOneHundredPercentRoyalty","type":"error"},{"inputs":[],"name":"NotEdition","type":"error"},{"inputs":[],"name":"NotForSale","type":"error"},{"inputs":[],"name":"NotFountCardHolder","type":"error"},{"inputs":[],"name":"NotOneOfOne","type":"error"},{"inputs":[],"name":"RequiresFountCard","type":"error"},{"inputs":[],"name":"RequiresSignature","type":"error"},{"inputs":[],"name":"SaleNotLive","type":"error"},{"inputs":[],"name":"TokenDataAlreadyExists","type":"error"},{"inputs":[],"name":"TokenDataDoesNotExist","type":"error"},{"inputs":[],"name":"WithdrawFailed","type":"error"},{"inputs":[],"name":"ZeroBalance","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"prevAdmin","type":"address"}],"name":"AdminRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"duration","type":"uint32"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"firstBidTime","type":"uint32"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint128","name":"highestBid","type":"uint128"},{"internalType":"uint128","name":"reservePrice","type":"uint128"}],"indexed":false,"internalType":"struct DriversLimitedEditions.AuctionData","name":"auction","type":"tuple"}],"name":"AuctionBid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"AuctionCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"duration","type":"uint32"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"firstBidTime","type":"uint32"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint128","name":"highestBid","type":"uint128"},{"internalType":"uint128","name":"reservePrice","type":"uint128"}],"indexed":false,"internalType":"struct DriversLimitedEditions.AuctionData","name":"auction","type":"tuple"}],"name":"AuctionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"duration","type":"uint256"}],"name":"AuctionDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"reservePrice","type":"uint256"}],"name":"AuctionReservePriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"duration","type":"uint32"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"firstBidTime","type":"uint32"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint128","name":"highestBid","type":"uint128"},{"internalType":"uint128","name":"reservePrice","type":"uint128"}],"indexed":false,"internalType":"struct DriversLimitedEditions.AuctionData","name":"auction","type":"tuple"}],"name":"AuctionSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"duration","type":"uint32"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"firstBidTime","type":"uint32"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint128","name":"highestBid","type":"uint128"},{"internalType":"uint128","name":"reservePrice","type":"uint128"}],"indexed":false,"internalType":"struct DriversLimitedEditions.AuctionData","name":"auction","type":"tuple"}],"name":"AuctionSoldEarly","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"startTime","type":"uint256"}],"name":"AuctionStartTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"baseId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"editionNumber","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"CollectedEdition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"CollectedOneOfOne","type":"event"},{"anonymous":false,"inputs":[],"name":"Init","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"metadataContract","type":"address"}],"name":"MetadataContractLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"metadataContract","type":"address"}],"name":"MetadataContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RoyaltyInfoSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RoyaltyInfoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint16","name":"editionSize","type":"uint16"},{"internalType":"uint16","name":"collected","type":"uint16"},{"internalType":"bool","name":"fountExclusive","type":"bool"},{"internalType":"bool","name":"requiresSig","type":"bool"},{"internalType":"bool","name":"freeToCollect","type":"bool"}],"indexed":false,"internalType":"struct DriversLimitedEditions.TokenData","name":"tokenData","type":"tuple"}],"name":"TokenDataAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint16","name":"editionSize","type":"uint16"},{"internalType":"uint16","name":"collected","type":"uint16"},{"internalType":"bool","name":"fountExclusive","type":"bool"},{"internalType":"bool","name":"requiresSig","type":"bool"},{"internalType":"bool","name":"freeToCollect","type":"bool"}],"indexed":false,"internalType":"struct DriversLimitedEditions.TokenData","name":"tokenData","type":"tuple"}],"name":"TokenDataSaleConditionsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint16","name":"editionSize","type":"uint16"},{"internalType":"uint16","name":"collected","type":"uint16"},{"internalType":"bool","name":"fountExclusive","type":"bool"},{"internalType":"bool","name":"requiresSig","type":"bool"},{"internalType":"bool","name":"freeToCollect","type":"bool"}],"indexed":false,"internalType":"struct DriversLimitedEditions.TokenData","name":"tokenData","type":"tuple"}],"name":"TokenDataSalePriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MINT_SIGNATURE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SIGNATURE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SIGNING_DOMAIN","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeAuctions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint16","name":"editionSize","type":"uint16"},{"internalType":"bool","name":"fountExclusive","type":"bool"},{"internalType":"bool","name":"requiresSig","type":"bool"},{"internalType":"bool","name":"freeMint","type":"bool"}],"name":"addTokenForSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"admins","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedSigners","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"auctionDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"auctionEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"auctionFirstBidTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"auctionHasEnded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"auctionHasStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"auctionHighestBid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"auctionHighestBidder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionIncPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"auctionReservePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"auctionStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionTimeBuffer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctions","outputs":[{"internalType":"uint32","name":"duration","type":"uint32"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"firstBidTime","type":"uint32"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint128","name":"highestBid","type":"uint128"},{"internalType":"uint128","name":"reservePrice","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"cancelAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"collectEdition","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"collectEdition","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"collectOneOfOne","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"collectOneOfOne","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"uint32","name":"duration","type":"uint32"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint128","name":"reservePrice","type":"uint128"}],"name":"createAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"everfresh","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getEditionBaseIdFromTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getEditionNumberFromTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"uint256","name":"editionNumber","type":"uint256"}],"name":"getEditionTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMetadataLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadata","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorFilteringEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payments","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"placeBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"placeBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"subscriptionOrRegistrantToCopy","type":"address"},{"internalType":"bool","name":"subscribe","type":"bool"}],"name":"registerForOperatorFiltering","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"prevAdmin","type":"address"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"repeatRegistration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"uint32","name":"duration","type":"uint32"}],"name":"setAuctionDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"uint128","name":"reservePrice","type":"uint128"}],"name":"setAuctionReservePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"uint32","name":"startTime","type":"uint32"}],"name":"setAuctionStartTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"contractURI_","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"metadata","type":"address"}],"name":"setMetadataAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setOperatorFilteringEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"paymentAddress","type":"address"}],"name":"setPaymentAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setRoyaltyInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isLive","type":"bool"}],"name":"setSaleLiveState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"bool","name":"fountExclusive","type":"bool"},{"internalType":"bool","name":"requiresSig","type":"bool"}],"name":"setTokenSaleConditions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"},{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"bool","name":"freeMint","type":"bool"}],"name":"setTokenSalePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"settleAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"tokenCollectedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"tokenEditionSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"tokenIsEdition","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"tokenIsFountExclusive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"tokenIsFreeToCollect","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"tokenIsOneOfOne","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"tokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseId","type":"uint256"}],"name":"tokenRequiresOffChainSignatureToCollect","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawAndReleaseAllETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
610140604052600b80546001600160a01b03191673bb3444a06e9928dda9a739cdab3e0c5cf6890099179055600f805474c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200610100600160a81b031990911617905561012c601155600a6012553480156200006d57600080fd5b506040516200624f3803806200624f833981016040819052620000909162000451565b8585858585856040518060400160405280601681526020017f447269766572734c696d6974656445646974696f6e7300000000000000000000815250604051806040016040528060018152602001603160f81b815250858585858b8b6040518060600160405280602581526020016200622a602591396040805180820190915260078152664452495645525360c81b602082015260006200013283826200056e565b5060016200014182826200056e565b5050600680546001600160a01b0319166001600160a01b0385169081179091556040519091506000907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d76908290a36001600160a01b038116600081815260076020526040808220805460ff19166001179055517fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b908290a35050600880546001600160a01b039283166001600160a01b0319918216179091556009805492841692909116821790556040517f0713c9f4b0c5db294e61505e6819f6ad0cccf782df1a544939dc55d13fe7fc1c90600090a2506040805180820182526001600160a01b0384168082526001600160601b0384166020909201829052600160a01b9091028117600a5590518291907f984cbbb47b413608120ad6b444ea0004fe19b6f88a5c0992e612b97fd3cb631e90600090a35050815160209283012081519183019190912060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818801819052818301969096526060810194909452608080850193909352308483018190528151808603909301835260c094850190915281519190950120905291909152610120526200032e62000397565b600f805460ff191660011790556040517f57a86f7d14ccde89e22870afe839e3011216827daa9b24e18629f0a1e9d6cc1490600090a15050601580546001600160a01b0319166001600160a01b039990991698909817909755506200063a975050505050505050565b620003b8733cc6cdda760b79bafa08df41ecfa224f810dceb66001620003ba565b565b6001600160a01b0390911690637d3e3dbe81620003ea5782620003e35750634420e486620003ea565b5063a0af29035b8060e01b60005230600452826024526004600060446000806daaeb6d7670e522a718067333cd4e5af16200042a578060005160e01c036200042a57600080fd5b5060006024525050565b80516001600160a01b03811681146200044c57600080fd5b919050565b60008060008060008060c087890312156200046b57600080fd5b620004768762000434565b9550620004866020880162000434565b9450620004966040880162000434565b935060608701519250620004ad6080880162000434565b9150620004bd60a0880162000434565b90509295509295509295565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620004f457607f821691505b6020821081036200051557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200056957600081815260208120601f850160051c81016020861015620005445750805b601f850160051c820191505b81811015620005655782815560010162000550565b5050505b505050565b81516001600160401b038111156200058a576200058a620004c9565b620005a2816200059b8454620004df565b846200051b565b602080601f831160018114620005da5760008415620005c15750858301515b600019600386901b1c1916600185901b17855562000565565b600085815260208120601f198616915b828110156200060b57888601518255948401946001909101908401620005ea565b50858210156200062a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516101005161012051615ba06200068a6000396000614d2101526000614d7001526000614d4b01526000614ca401526000614cce01526000614cf80152615ba06000f3fe60806040526004361061049f5760003560e01c8063864bc0a011610260578063b9c2443d11610144578063d7e45cd7116100c1578063e3faad9411610085578063e3faad9414611067578063e8a3d485146110a9578063e985e9c5146110be578063ef6ea27a146110f9578063f9e3c46f14611131578063fb796e6c1461117157600080fd5b8063d7e45cd714610fd1578063e07b1afb14610ff2578063e086e5ec14611012578063e17b25af14611027578063e2e784d51461104757600080fd5b8063c87b56dd11610108578063c87b56dd14610f0e578063cb93752814610f2e578063d2e4b90514610f4e578063d46e7ae114610f88578063d4ddce8a14610f9b57600080fd5b8063b9c2443d14610e28578063bdaaf19414610e48578063bf40defb14610e81578063bfe29d5714610ebd578063c0fd735b14610ef957600080fd5b8063a2df15e2116101dd578063a6d23e10116101a1578063a6d23e1014610d61578063aa05234114610d81578063abadb36514610da1578063af4fddfa14610db4578063b7c0b8e814610de8578063b88d4fde14610e0857600080fd5b8063a2df15e214610ca1578063a415729614610cb7578063a43b87a214610ce4578063a522ad2514610d21578063a5aef37d14610d4157600080fd5b806395d89b411161022457806395d89b4114610c0657806396b5a75514610c1b5780639886973114610c3b5780639979ef4514610c6e578063a22cb46514610c8157600080fd5b8063864bc0a014610b6d5780638a87551214610b805780638da5cb5b14610bb0578063923d8dfa14610bd0578063938e3d7b14610be657600080fd5b8063392f37e9116103875780635e1c074611610304578063695747c2116102c8578063695747c214610a88578063702f9bbe14610aa85780637048027514610ae057806370a0823114610b00578063777de70414610b205780637ecebe0014610b4057600080fd5b80635e1c0746146109e95780635e1e1004146109fe578063633511bb14610a1e5780636352211e14610a5557806365a1e83314610a7557600080fd5b80634588d1c71161034b5780634588d1c7146108ac57806346d8efad146108cc57806349df728c146108ec5780635090d0c61461090c578063571a26a01461092257600080fd5b8063392f37e9146107f75780633fc8cef31461081757806342842e0e1461083c57806342966c681461085c578063429b62e51461087c57600080fd5b80631551b7c11161042057806326645a2c116103e457806326645a2c146106cc5780632a55205a146107035780632e9936111461074257806331cb61051461076257806331ccd4bc1461078257806333465c5f146107bd57600080fd5b80631551b7c1146106395780631785f53c1461065957806319ffb5831461067957806320f3f8451461069957806323b872dd146106ac57600080fd5b80630a87c3cf116104675780630a87c3cf146105995780630e9e835c146105b957806311a774fd146105d957806313af4035146105f957806314dfc68e1461061957600080fd5b806301ffc9a7146104a457806306d715fa146104d957806306fdde0314610507578063081812fc14610529578063095ea7b314610577575b600080fd5b3480156104b057600080fd5b506104c46104bf366004615112565b61118b565b60405190151581526020015b60405180910390f35b3480156104e557600080fd5b506104f96104f436600461512f565b6111b6565b6040519081526020016104d0565b34801561051357600080fd5b5061051c6111d1565b6040516104d0919061516c565b34801561053557600080fd5b5061055f61054436600461512f565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016104d0565b34801561058357600080fd5b506105976105923660046151b6565b61125f565b005b3480156105a557600080fd5b506105976105b4366004615205565b611283565b3480156105c557600080fd5b506104c46105d436600461512f565b611467565b3480156105e557600080fd5b506105976105f4366004615245565b611515565b34801561060557600080fd5b5061059761061436600461526c565b6116df565b34801561062557600080fd5b506104f961063436600461512f565b61176f565b34801561064557600080fd5b50610597610654366004615287565b61178e565b34801561066557600080fd5b5061059761067436600461526c565b6117f0565b34801561068557600080fd5b506105976106943660046152a4565b61187e565b6105976106a7366004615308565b611a8a565b3480156106b857600080fd5b506105976106c7366004615361565b611b7a565b3480156106d857600080fd5b506104c46106e736600461512f565b600090815260106020526040902054600160a01b900460ff1690565b34801561070f57600080fd5b5061072361071e36600461539d565b611bb0565b604080516001600160a01b0390931683526020830191909152016104d0565b34801561074e57600080fd5b5061059761075d36600461512f565b611bf2565b34801561076e57600080fd5b5061059761077d3660046153bf565b611d84565b34801561078e57600080fd5b506104c461079d36600461512f565b600090815260106020526040902054600160801b900461ffff1660011490565b3480156107c957600080fd5b506104f96107d836600461512f565b600090815260136020526040902054600160201b900463ffffffff1690565b34801561080357600080fd5b5060095461055f906001600160a01b031681565b34801561082357600080fd5b50600f5461055f9061010090046001600160a01b031681565b34801561084857600080fd5b50610597610857366004615361565b611df3565b34801561086857600080fd5b5061059761087736600461512f565b611e23565b34801561088857600080fd5b506104c461089736600461526c565b60076020526000908152604090205460ff1681565b3480156108b857600080fd5b506105976108c73660046153f6565b611e7b565b3480156108d857600080fd5b506105976108e73660046153bf565b61216a565b3480156108f857600080fd5b5061059761090736600461526c565b6121bc565b34801561091857600080fd5b506104f960145481565b34801561092e57600080fd5b5061099a61093d36600461512f565b6013602052600090815260409020805460019091015463ffffffff80831692600160201b8104821692600160401b820490921691600160601b9091046001600160a01b0316906001600160801b0380821691600160801b90041686565b6040805163ffffffff9788168152958716602087015293909516928401929092526001600160a01b031660608301526001600160801b03908116608083015290911660a082015260c0016104d0565b3480156109f557600080fd5b50610597612217565b348015610a0a57600080fd5b50610597610a1936600461526c565b612221565b348015610a2a57600080fd5b506104c4610a3936600461512f565b600090815260106020526040902054600160a81b900460ff1690565b348015610a6157600080fd5b5061055f610a7036600461512f565b6122ae565b610597610a83366004615474565b612305565b348015610a9457600080fd5b506104f9610aa336600461539d565b6123d6565b348015610ab457600080fd5b506104f9610ac336600461512f565b600090815260106020526040902054600160801b900461ffff1690565b348015610aec57600080fd5b50610597610afb36600461526c565b6123e9565b348015610b0c57600080fd5b506104f9610b1b36600461526c565b61247a565b348015610b2c57600080fd5b506104f9610b3b36600461512f565b6124dd565b348015610b4c57600080fd5b506104f9610b5b36600461526c565b600e6020526000908152604090205481565b610597610b7b366004615497565b61258a565b348015610b8c57600080fd5b506104c4610b9b36600461526c565b600d6020526000908152604090205460ff1681565b348015610bbc57600080fd5b5060065461055f906001600160a01b031681565b348015610bdc57600080fd5b506104f960125481565b348015610bf257600080fd5b50610597610c0136600461554f565b612672565b348015610c1257600080fd5b5061051c6126c2565b348015610c2757600080fd5b50610597610c3636600461512f565b6126cf565b348015610c4757600080fd5b506104f9610c5636600461512f565b60009081526013602052604090205463ffffffff1690565b610597610c7c36600461512f565b61279c565b348015610c8d57600080fd5b50610597610c9c3660046153bf565b61286c565b348015610cad57600080fd5b506104f960115481565b348015610cc357600080fd5b5061051c604051806040016040528060018152602001603160f81b81525081565b348015610cf057600080fd5b5061055f610cff36600461512f565b600090815260136020526040902054600160601b90046001600160a01b031690565b348015610d2d57600080fd5b50610597610d3c3660046155ce565b61288b565b348015610d4d57600080fd5b50610597610d5c36600461560c565b6128d9565b348015610d6d57600080fd5b5060155461055f906001600160a01b031681565b348015610d8d57600080fd5b506104c4610d9c36600461512f565b612ba8565b610597610daf366004615308565b612c3b565b348015610dc057600080fd5b506104f97f9a1ad8626c8e414784b966be6c93b2550ea90ccdf34423b1e4aca0c3b942ada581565b348015610df457600080fd5b50610597610e03366004615287565b612d24565b348015610e1457600080fd5b50610597610e23366004615659565b612d7b565b348015610e3457600080fd5b50610597610e433660046156c7565b612db5565b348015610e5457600080fd5b506104f9610e6336600461512f565b6000908152601360205260409020600101546001600160801b031690565b348015610e8d57600080fd5b506104c4610e9c36600461512f565b6000908152601060205260409020546001600160801b90910461ffff161190565b348015610ec957600080fd5b506104c4610ed836600461512f565b600090815260136020526040902054600160401b900463ffffffff16151590565b348015610f0557600080fd5b50610597612fc3565b348015610f1a57600080fd5b5061051c610f2936600461512f565b6130a1565b348015610f3a57600080fd5b50610597610f493660046156c7565b613113565b348015610f5a57600080fd5b506104f9610f6936600461512f565b600090815260136020526040902054600160401b900463ffffffff1690565b610597610f96366004615474565b613320565b348015610fa757600080fd5b506104f9610fb636600461512f565b6000908152601060205260409020546001600160801b031690565b348015610fdd57600080fd5b506009546104c490600160a01b900460ff1681565b348015610ffe57600080fd5b50600b5461055f906001600160a01b031681565b34801561101e57600080fd5b506105976133f1565b34801561103357600080fd5b5061059761104236600461526c565b61346b565b34801561105357600080fd5b506105976110623660046151b6565b6134b8565b34801561107357600080fd5b5061051c60405180604001604052806016815260200175447269766572734c696d6974656445646974696f6e7360501b81525081565b3480156110b557600080fd5b5061051c613506565b3480156110ca57600080fd5b506104c46110d93660046155ce565b600560209081526000928352604080842090915290825290205460ff1681565b34801561110557600080fd5b506104f961111436600461512f565b600090815260106020526040902054600160901b900461ffff1690565b34801561113d57600080fd5b506104f961114c36600461512f565b600090815260136020526040902060010154600160801b90046001600160801b031690565b34801561117d57600080fd5b50600f546104c49060ff1681565b60006001600160e01b0319821663152a902d60e11b14806111b057506111b082613513565b92915050565b60006103e882106111c5575090565b6111b06103e883615716565b600080546111de9061572a565b80601f016020809104026020016040519081016040528092919081815260200182805461120a9061572a565b80156112575780601f1061122c57610100808354040283529160200191611257565b820191906000526020600020905b81548152906001019060200180831161123a57829003601f168201915b505050505081565b81600f5460ff16156112745761127481613561565b61127e83836135a5565b505050565b6006546001600160a01b03163314806112ab57503360009081526007602052604090205460ff165b6112d05760405162461bcd60e51b81526004016112c790615764565b60405180910390fd5b6000838152601060209081526040808320815160c08101835290546001600160801b038116825261ffff600160801b82048116948301859052600160901b8204169282019290925260ff600160a01b8304811615156060830152600160a81b8304811615156080830152600160b01b909204909116151560a0820152910361136b576040516347c0cce560e01b815260040160405180910390fd5b6001600160801b03808416825282151560a08301908152600086815260106020908152604091829020855181549287015184880151606089015160808a015197511515600160b01b0260ff60b01b19981515600160a81b029890981661ffff60a81b19911515600160a01b0260ff60a01b1961ffff948516600160901b021662ffffff60901b1994909516600160801b026001600160901b031990981695909a1694909417959095171617959095179190911693909317919091179091555184907fc190e68218b7249bd1d46cf62b59253a4b51eed2bfb8924a7a56661fb9a473489061145990849061578a565b60405180910390a250505050565b6000818152601360208181526040808420815160c081018352815463ffffffff8082168352600160201b8204811683870152600160401b820416938201849052600160601b90046001600160a01b031660608201526001909101546001600160801b038082166080840152600160801b9091041660a08201528585529290915215801590819061150d57508151604083015161150391906157e7565b63ffffffff164210155b949350505050565b6006546001600160a01b031633148061153d57503360009081526007602052604090205460ff165b6115595760405162461bcd60e51b81526004016112c790615764565b6000838152601060209081526040808320815160c08101835290546001600160801b038116825261ffff600160801b82048116948301859052600160901b8204169282019290925260ff600160a01b8304811615156060830152600160a81b8304811615156080830152600160b01b909204909116151560a082015291036115f4576040516347c0cce560e01b815260040160405180910390fd5b82151560608201908152821515608083019081526000868152601060209081526040918290208551815492870151848801519651955160a08901511515600160b01b0260ff60b01b19911515600160a81b029190911661ffff60a81b19971515600160a01b0260ff60a01b1961ffff9a8b16600160901b021662ffffff60901b199a909416600160801b026001600160901b03199097166001600160801b03909516949094179590951797909716171793909316179290921790555184907fea454d1e05d501c547b57c90d87e01eaef34d99308681d143ec564111cf7763a9061145990849061578a565b6006546001600160a01b031633148061170757503360009081526007602052604090205460ff165b6117235760405162461bcd60e51b81526004016112c790615764565b600680546001600160a01b0319166001600160a01b03831690811790915560405133907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a350565b60006103e8821061178257506000919050565b6111b06103e88361580b565b6006546001600160a01b03163314806117b657503360009081526007602052604090205460ff165b6117d25760405162461bcd60e51b81526004016112c790615764565b60158054911515600160a01b0260ff60a01b19909216919091179055565b6006546001600160a01b031633148061181857503360009081526007602052604090205460ff165b6118345760405162461bcd60e51b81526004016112c790615764565b6001600160a01b038116600081815260076020526040808220805460ff19169055517fdb9d5d31320daf5bc7181d565b6da4d12e30f0f4d5aa324a992426c14a1d19ce908290a350565b6006546001600160a01b03163314806118a657503360009081526007602052604090205460ff165b6118c25760405162461bcd60e51b81526004016112c790615764565b806001600160801b03166000036118ec57604051633646340760e21b815260040160405180910390fd5b6000828152601360209081526040808320815160c081018352815463ffffffff8082168352600160201b82048116958301869052600160401b82041693820193909352600160601b9092046001600160a01b03166060830152600101546001600160801b038082166080840152600160801b9091041660a082015291036119865760405163e6759c6760e01b815260040160405180910390fd5b604081015163ffffffff16156119af5760405163628e388360e01b815260040160405180910390fd5b6001600160801b0380831660a0830181815260008681526013602090815260408083208751815493890151838a015160608b01516001600160a01b0316600160601b026001600160601b0363ffffffff928316600160401b02166001600160401b03938316600160201b0267ffffffffffffffff199098169290941691909117959095171617929092178255608087015193518616600160801b0293909516929092176001909201919091559151909185917fd44c1f367e4b7835166bd3805433cc6133391fa6e0099d7303ec10205c9efcb89190a3505050565b601554600160a01b900460ff16611ab457604051637e19eeed60e11b815260040160405180910390fd5b600084815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b8204811615801560808501819052600160b01b909304909116151560a0840152611b4a5750611b4885858585613687565b155b15611b6857604051638baa579f60e01b815260040160405180910390fd5b611b738585836137e0565b5050505050565b826001600160a01b0381163314611b9f57600f5460ff1615611b9f57611b9f33613561565b611baa848484613b33565b50505050565b600a546001600160a01b0381169060009061271090611bdf90600160a01b90046001600160601b03168561581f565b611be99190615716565b90509250929050565b6000818152601360209081526040808320815160c081018352815463ffffffff8082168352600160201b8204811695830195909552600160401b8104909416928101839052600160601b9093046001600160a01b03166060840152600101546001600160801b038082166080850152600160801b9091041660a0830152909103611c8f576040516301dff5d560e71b815260040160405180910390fd5b805160408201514291611ca1916157e7565b63ffffffff161115611cc657604051636463738960e01b815260040160405180910390fd5b600b546000838152600260205260409020546001600160a01b03908116911614611d0357604051631b42fb7f60e31b815260040160405180910390fd5b611d11816060015183613cc4565b60405182907f7bb9aafce2f4a89681d211146eaa6c59ec03a137171363e78aa243d7d0bf36d890600090a26014805460001901905560405182907f2be75b1f4f563cd2d2d28f28e51ddcb63c202fa685d6202078fa5376c8269d3490611d78908490615836565b60405180910390a25050565b6006546001600160a01b0316331480611dac57503360009081526007602052604090205460ff165b611dc85760405162461bcd60e51b81526004016112c790615764565b6001600160a01b03919091166000908152600d60205260409020805460ff1916911515919091179055565b826001600160a01b0381163314611e1857600f5460ff1615611e1857611e1833613561565b611baa848484613dca565b33611e2d826122ae565b6001600160a01b031614611e6f5760405162461bcd60e51b81526020600482015260096024820152682727aa2fa7aba722a960b91b60448201526064016112c7565b611e7881613ebd565b50565b6006546001600160a01b0316331480611ea357503360009081526007602052604090205460ff165b611ebf5760405162461bcd60e51b81526004016112c790615764565b611ecd6103e8600019615716565b861115611eed57604051630a779b1560e21b815260040160405180910390fd5b8361ffff16600003611f1257604051634d74210f60e11b815260040160405180910390fd5b611f1f60016103e861589a565b8461ffff161115611f43576040516317ee9bc760e21b815260040160405180910390fd5b600086815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b82048116938301849052600160901b8204169382019390935260ff600160a01b8404811615156060830152600160a81b8404811615156080830152600160b01b909304909216151560a083015215611fde576040516320705a1b60e11b815260040160405180910390fd5b6001600160801b03808716825261ffff8087166020808501918252871515606086019081528715156080870190815287151560a0880190815260008e81526010909452604093849020885181549651868b01519551945193511515600160b01b0260ff60b01b19941515600160a81b029490941661ffff60a81b19951515600160a01b0260ff60a01b19978b16600160901b029790971662ffffff60901b1992909a16600160801b026001600160901b031990991692909a16919091179690961795909516959095179190911716939093179190911790555187907f2f4457ef75a9f3a9d9845f891558d05d38ead4a1df33f2d5a3c14bfe653fba8c906120e690849061578a565b60405180910390a28461ffff1660010361211557600b54612110906001600160a01b031688613f78565b612161565b60005b8561ffff1681101561215f57600b5461214d906001600160a01b03166121488a6121438560016158ad565b61404d565b613f78565b80612157816158c0565b915050612118565b505b50505050505050565b6006546001600160a01b031633148061219257503360009081526007602052604090205460ff165b6121ae5760405162461bcd60e51b81526004016112c790615764565b6121b88282614066565b5050565b6006546001600160a01b03163314806121e457503360009081526007602052604090205460ff165b6122005760405162461bcd60e51b81526004016112c790615764565b601554611e789082906001600160a01b03166140db565b61221f614227565b565b6006546001600160a01b031633148061224957503360009081526007602052604090205460ff165b6122655760405162461bcd60e51b81526004016112c790615764565b6001600160a01b03811661228c57604051631f4c499760e01b815260040160405180910390fd5b601580546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600260205260409020546001600160a01b0316806123005760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b60448201526064016112c7565b919050565b601554600160a01b900460ff1661232f57604051637e19eeed60e11b815260040160405180910390fd5b600082815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b820481161580156080850152600160b01b90920416151560a08301526123cb57604051630426ff7760e01b815260040160405180910390fd5b61127e8383836137e0565b60006123e2838361404d565b9392505050565b6006546001600160a01b031633148061241157503360009081526007602052604090205460ff165b61242d5760405162461bcd60e51b81526004016112c790615764565b6001600160a01b038116600081815260076020526040808220805460ff19166001179055517fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b908290a350565b60006001600160a01b0382166124c15760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b60448201526064016112c7565b506001600160a01b031660009081526003602052604090205490565b6000818152601360208181526040808420815160c081018352815463ffffffff8082168352600160201b8204811683870152600160401b820416938201849052600160601b90046001600160a01b031660608201526001909101546001600160801b038082166080840152600160801b9091041660a08201528585529290915215158061256b57600061257c565b8151602083015161257c91906157e7565b63ffffffff16949350505050565b601554600160a01b900460ff166125b457604051637e19eeed60e11b815260040160405180910390fd5b600083815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b8204811615801560808501819052600160b01b909304909116151560a084015261264a575061264884338585613687565b155b1561266857604051638baa579f60e01b815260040160405180910390fd5b611baa8482614246565b6006546001600160a01b031633148061269a57503360009081526007602052604090205460ff165b6126b65760405162461bcd60e51b81526004016112c790615764565b600c6121b8828261591f565b600180546111de9061572a565b6006546001600160a01b03163314806126f757503360009081526007602052604090205460ff165b6127135760405162461bcd60e51b81526004016112c790615764565b600081815260136020908152604091829020825160c081018452815463ffffffff8082168352600160201b8204811694830194909452600160401b810490931693810193909352600160601b9091046001600160a01b03166060830152600101546001600160801b038082166080840152600160801b9091041660a08201526121b88282614546565b601554600160a01b900460ff166127c657604051637e19eeed60e11b815260040160405180910390fd5b600081815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b820481161580156080850152600160b01b90920416151560a083015261286257604051630426ff7760e01b815260040160405180910390fd5b6121b88282614246565b81600f5460ff16156128815761288181613561565b61127e83836145f4565b6006546001600160a01b03163314806128b357503360009081526007602052604090205460ff165b6128cf5760405162461bcd60e51b81526004016112c790615764565b6121b882826140db565b6006546001600160a01b031633148061290157503360009081526007602052604090205460ff165b61291d5760405162461bcd60e51b81526004016112c790615764565b8263ffffffff16600003612944576040516335f7aa5b60e11b815260040160405180910390fd5b8163ffffffff1660000361296b57604051634b6e1bd360e01b815260040160405180910390fd5b600084815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b82048116938301849052600160901b8204169382019390935260ff600160a01b8404811615156060830152600160a81b8404811615156080830152600160b01b909304909216151560a0830152600114612a0857604051630eea117d60e31b815260040160405180910390fd5b600085815260136020908152604091829020825160c081018452815463ffffffff8082168352600160201b82048116948301859052600160401b82041694820194909452600160601b9093046001600160a01b03166060840152600101546001600160801b038082166080850152600160801b9091041660a083015215612aa157604051628b039960e31b815260040160405180910390fd5b63ffffffff808616825284811660208084019182526001600160801b0380871660a0860190815260008b815260139093526040928390208651815495518589015160608a01516001600160a01b0316600160601b026001600160601b03918a16600160401b02919091166001600160401b03928a16600160201b0267ffffffffffffffff199099169390991692909217969096179590951695909517939093178455608085015192518116600160801b02921691909117600192830155601480549092019091555186907f67e0934daec5a59c2ce373b1d94d8160057ae0a6cfa7a01ccdfc12d63f5ae7fb90612b98908490615836565b60405180910390a2505050505050565b6000818152601060209081526040808320815160c08101835290546001600160801b03811680835261ffff600160801b8304811695840195909552600160901b82049094169282019290925260ff600160a01b8304811615156060830152600160a81b8304811615156080830152600160b01b909204909116151560a0820152901580156123e2575060a0015192915050565b601554600160a01b900460ff16612c6557604051637e19eeed60e11b815260040160405180910390fd5b600084815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b8204811615801560808501819052600160b01b909304909116151560a0840152612cfb5750612cf985858585613687565b155b15612d1957604051638baa579f60e01b815260040160405180910390fd5b611b73858583614660565b6006546001600160a01b0316331480612d4c57503360009081526007602052604090205460ff165b612d685760405162461bcd60e51b81526004016112c790615764565b600f805460ff1916911515919091179055565b846001600160a01b0381163314612da057600f5460ff1615612da057612da033613561565b612dad8686868686614886565b505050505050565b6006546001600160a01b0316331480612ddd57503360009081526007602052604090205460ff165b612df95760405162461bcd60e51b81526004016112c790615764565b8063ffffffff16600003612e2057604051634b6e1bd360e01b815260040160405180910390fd5b6000828152601360209081526040808320815160c081018352815463ffffffff8082168352600160201b82048116958301869052600160401b82041693820193909352600160601b9092046001600160a01b03166060830152600101546001600160801b038082166080840152600160801b9091041660a08201529103612eba5760405163e6759c6760e01b815260040160405180910390fd5b604081015163ffffffff1615612ee35760405163628e388360e01b815260040160405180910390fd5b63ffffffff80831660208084018281526000878152601390925260408083208651815493518389015160608a01516001600160a01b0316600160601b026001600160601b03918a16600160401b02919091166001600160401b03928a16600160201b0267ffffffffffffffff199097169390991692909217949094179390931695909517919091178455608085015160a08601516001600160801b03908116600160801b029116176001909401939093559151909185917f7076391b57145201e1b1e818500795c44fda2ae9af4dc5f2ea3d36a5539eb7779190a3505050565b6006546001600160a01b0316331480612feb57503360009081526007602052604090205460ff165b6130075760405162461bcd60e51b81526004016112c790615764565b6014541561302857604051630745ab4760e51b815260040160405180910390fd5b60155461303d906001600160a01b0316614967565b601560009054906101000a90046001600160a01b03166001600160a01b031663465105f06040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561308d57600080fd5b505af1158015611baa573d6000803e3d6000fd5b60095460405163c87b56dd60e01b8152600481018390526060916001600160a01b03169063c87b56dd90602401600060405180830381865afa1580156130eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111b091908101906159de565b6006546001600160a01b031633148061313b57503360009081526007602052604090205460ff165b6131575760405162461bcd60e51b81526004016112c790615764565b8063ffffffff1660000361317e576040516335f7aa5b60e11b815260040160405180910390fd5b6000828152601360209081526040808320815160c081018352815463ffffffff8082168352600160201b82048116958301869052600160401b82041693820193909352600160601b9092046001600160a01b03166060830152600101546001600160801b038082166080840152600160801b9091041660a082015291036132185760405163e6759c6760e01b815260040160405180910390fd5b604081015163ffffffff16156132415760405163628e388360e01b815260040160405180910390fd5b63ffffffff808316808352600085815260136020908152604080832086518154938801518389015160608a01516001600160a01b0316600160601b026001600160601b03918a16600160401b02919091166001600160401b03928a16600160201b0267ffffffffffffffff199097169390991692909217949094179390931695909517919091178455608085015160a08601516001600160801b03908116600160801b029116176001909401939093559151909185917f9702db1e67fa6b64b8288101859f3b327a978f15d66e12ad769e5bbf30814d289190a3505050565b601554600160a01b900460ff1661334a57604051637e19eeed60e11b815260040160405180910390fd5b600082815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b820481161580156080850152600160b01b90920416151560a08301526133e657604051630426ff7760e01b815260040160405180910390fd5b61127e838383614660565b6006546001600160a01b031633148061341957503360009081526007602052604090205460ff165b6134355760405162461bcd60e51b81526004016112c790615764565b6014541561345657604051630745ab4760e51b815260040160405180910390fd5b60155461221f906001600160a01b0316614967565b6006546001600160a01b031633148061349357503360009081526007602052604090205460ff165b6134af5760405162461bcd60e51b81526004016112c790615764565b611e7881614a25565b6006546001600160a01b03163314806134e057503360009081526007602052604090205460ff165b6134fc5760405162461bcd60e51b81526004016112c790615764565b6121b88282614a9a565b600c80546111de9061572a565b60006301ffc9a760e01b6001600160e01b03198316148061354457506380ac58cd60e01b6001600160e01b03198316145b806111b05750506001600160e01b031916635b5e139f60e01b1490565b69c617113400112233445560005230601a5280603a52600080604460166daaeb6d7670e522a718067333cd4e5afa61359d573d6000803e3d6000fd5b6000603a5250565b6000818152600260205260409020546001600160a01b0316338114806135ee57506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b61362b5760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016112c7565b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b604080516080810182528581526001600160a01b03851660208083018290526000918252600e815283822054838501528351601f860182900482028101820190945284845290928392916060830191908790879081908401838280828437600092018290525093909452505082516020808501516001600160a01b0381168452600e909152604083208054959650929461378f94507f9a1ad8626c8e414784b966be6c93b2550ea90ccdf34423b1e4aca0c3b942ada59386613748836158c0565b909155506040805160208101959095528401929092526001600160a01b03166060830152608082015260a00160405160208183030381529060405280519060200120614b1d565b905060006137a1828460600151614b6b565b6001600160a01b0381166000908152600d602052604090205490915060ff1680156137d457506001600160a01b03811615155b98975050505050505050565b806020015161ffff1660011461380957604051630eea117d60e31b815260040160405180910390fd5b8060a00151158015613823575080516001600160801b0316155b1561384157604051631d99ddbf60e01b815260040160405180910390fd5b80516001600160801b0316341461386b57604051636992e1ff60e01b815260040160405180910390fd5b80606001518015613882575061388082614b8f565b155b156138a057604051633664886760e11b815260040160405180910390fd5b600083815260136020908152604091829020825160c081018452815463ffffffff8082168352600160201b8204811694830194909452600160401b8104909316938101849052600160601b9092046001600160a01b03166060830152600101546001600160801b038082166080840152600160801b9091041660a08201529015613a375760408101516139399063ffffffff164261589a565b63ffffffff908116825260008581526013602090815260409182902084518154928601519386015160608701516001600160a01b038116600160601b026001600160601b03928816600160401b02929092166001600160401b03968816600160201b0267ffffffffffffffff199096169390971692909217939093179390931693909317178255608083015160a08401516001600160801b03908116600160801b0291169081176001909301929092556139f291614ba2565b6014805460001901905560405184907f4215ff61a9831416ed985d067257b9f8802a061f560876a779ebc5f3c6189fe890613a2e908490615836565b60405180910390a25b6040808301805161ffff600190910181168252600087815260106020908152939020855181549487015193516060880151608089015160a08a01511515600160b01b0260ff60b01b19911515600160a81b029190911661ffff60a81b19921515600160a01b0260ff60a01b19948816600160901b029490941662ffffff60901b1998909716600160801b026001600160901b03199099166001600160801b0390951694909417979097179590951693909317929092179290921617919091179055613b028385613cc4565b60405184907f7bb9aafce2f4a89681d211146eaa6c59ec03a137171363e78aa243d7d0bf36d890600090a250505050565b6000818152600260205260409020546001600160a01b03848116911614613b895760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016112c7565b6001600160a01b038216613baf5760405162461bcd60e51b81526004016112c790615a54565b336001600160a01b0384161480613be957506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b80613c0a57506000818152600460205260409020546001600160a01b031633145b613c475760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016112c7565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b0319908116831790915560049092528483208054909216909155925184939291600080516020615b7483398151915291a4505050565b600081815260026020526040902054600b546001600160a01b03908116911614613d1d5760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016112c7565b6001600160a01b038216613d435760405162461bcd60e51b81526004016112c790615a54565b600b80546001600160a01b0390811660009081526003602090815260408083208054600019019055868416808452818420805460010190558684526002835281842080546001600160a01b031990811683179091556004909352818420805490931690925593549351859491939190911691600080516020615b7483398151915291a45050565b613dd5838383611b7a565b6001600160a01b0382163b1580613e7e5750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015613e4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e729190615a7f565b6001600160e01b031916145b61127e5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016112c7565b6000818152600260205260409020546001600160a01b031680613f0f5760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b60448201526064016112c7565b6001600160a01b038116600081815260036020908152604080832080546000190190558583526002825280832080546001600160a01b03199081169091556004909252808320805490921690915551849290600080516020615b74833981519152908390a45050565b6001600160a01b038216613f9e5760405162461bcd60e51b81526004016112c790615a54565b6000818152600260205260409020546001600160a01b031615613ff45760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b60448201526064016112c7565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b031916841790555183929190600080516020615b74833981519152908290a45050565b60008161405c6103e88561581f565b6123e291906158ad565b6001600160a01b0390911690637d3e3dbe81614093578261408c5750634420e486614093565b5063a0af29035b8060e01b60005230600452826024526004600060446000806daaeb6d7670e522a718067333cd4e5af16140d1578060005160e01c036140d157600080fd5b5060006024525050565b6001600160a01b0381166141025760405163172fe2d160e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015614149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061416d9190615a9c565b9050806000036141905760405163334ab3f560e11b815260040160405180910390fd5b60405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390526000919085169063a9059cbb906044016020604051808303816000875af11580156141e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142079190615ab5565b905080611baa57604051631d42c86760e21b815260040160405180910390fd5b61221f733cc6cdda760b79bafa08df41ecfa224f810dceb66001614066565b8060600151801561425d575061425b33614b8f565b155b1561427b57604051633664886760e11b815260040160405180910390fd5b600082815260136020908152604091829020825160c081018452815463ffffffff8082168352600160201b82048116948301859052600160401b82041694820194909452600160601b9093046001600160a01b03166060840152600101546001600160801b038082166080850152600160801b9091041660a0830152158061430c575042816020015163ffffffff16115b1561432a576040516301dff5d560e71b815260040160405180910390fd5b806040015163ffffffff1660000361439257348160a001516001600160801b031611156143815760a0810151604051635cf8b88960e11b81526001600160801b0390911660048201523460248201526044016112c7565b63ffffffff42166040820152614431565b805160408201516143a391906157e7565b63ffffffff164211156143c95760405163283a4a6160e21b815260040160405180910390fd5b600081608001516001600160801b03169050600060646012548302816143f1576143f16156ea565b0482019050348111156144205760405163bc1510d560e01b8152600481018290523460248201526044016112c7565b61442e836060015183614ba2565b50505b346001600160601b0316608082015233606082015280516040820151601154429190920163ffffffff16039081101561447757601154825163ffffffff91839003011682525b60008481526013602090815260409182902084518154928601518487015160608801516001600160a01b0316600160601b026001600160601b0363ffffffff928316600160401b02166001600160401b03938316600160201b0267ffffffffffffffff199097169290941691909117949094171617919091178155608084015160a08501516001600160801b03908116600160801b029116176001909101555184907f90e14ed1433e5f6856e46c6068401974e908b3ef4a8ecd5401cbd68d8b4c2a1f90611459908590615836565b604081015163ffffffff16156145a8578051604082015161456791906157e7565b63ffffffff1642111561458d5760405163283a4a6160e21b815260040160405180910390fd5b6145a8816060015182608001516001600160801b0316614ba2565b600082815260136020526040808220828155600101829055601480546000190190555183917f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df91a25050565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6002816020015161ffff16101561468a57604051630556890560e01b815260040160405180910390fd5b806020015161ffff16816040015160016146a49190615ad2565b61ffff1611156146c75760405163a8fda6c160e01b815260040160405180910390fd5b8060a001511580156146e1575080516001600160801b0316155b156146ff57604051631d99ddbf60e01b815260040160405180910390fd5b80516001600160801b0316341461472957604051636992e1ff60e01b815260040160405180910390fd5b80606001518015614740575061473e82614b8f565b155b1561475e57604051633664886760e11b815260040160405180910390fd5b6000816040015160016147719190615ad2565b61ffff1690506000614783858361404d565b6040808501805161ffff6001909101811682526000898152601060209081529390208751815494890151935160608a015160808b015160a08c01511515600160b01b0260ff60b01b19911515600160a81b029190911661ffff60a81b19921515600160a01b0260ff60a01b19948816600160901b029490941662ffffff60901b1998909716600160801b026001600160901b03199099166001600160801b039095169490941797909717959095169390931792909217929092161791909117905590506148508482613cc4565b8082867fdf5fda6ef84c661a9a8c7217395c3d91bc7e519453e81fcbfa1f0f2d19a8d5be60405160405180910390a45050505050565b614891858585611b7a565b6001600160a01b0384163b15806149285750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a02906148d99033908a90899089908990600401615aed565b6020604051808303816000875af11580156148f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061491c9190615a7f565b6001600160e01b031916145b611b735760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016112c7565b6001600160a01b03811661498e5760405163172fe2d160e01b815260040160405180910390fd5b4760008190036149b15760405163334ab3f560e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146149fe576040519150601f19603f3d011682016040523d82523d6000602084013e614a03565b606091505b505090508061127e57604051631d42c86760e21b815260040160405180910390fd5b600954600160a01b900460ff1615614a50576040516313ef243160e11b815260040160405180910390fd5b600980546001600160a01b0319166001600160a01b0383169081179091556040517f0713c9f4b0c5db294e61505e6819f6ad0cccf782df1a544939dc55d13fe7fc1c90600090a250565b612710811115614abd576040516303c799a760e61b815260040160405180910390fd5b6040805180820182526001600160a01b03841680825262ffffff84166020909201829052600160a01b9091028117600a5590518291907ff21fccf4d64d86d532c4e4eb86c007b6ad57a460c27d724188625e755ec6cf6d90600090a35050565b60006111b0614b2a614c97565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000614b7a8585614dbe565b91509150614b8781614e03565b509392505050565b600080614b9b83614f4d565b1192915050565b614bac8282614fc1565b6121b857600f60019054906101000a90046001600160a01b03166001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015614c0057600080fd5b505af1158015614c14573d6000803e3d6000fd5b5050600f5460405163a9059cbb60e01b81526001600160a01b03878116600483015260248201879052610100909204909116935063a9059cbb925060440190506020604051808303816000875af1158015614c73573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127e9190615ab5565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015614cf057507f000000000000000000000000000000000000000000000000000000000000000046145b15614d1a57507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000808251604103614df45760208301516040840151606085015160001a614de887828585615038565b94509450505050614dfc565b506000905060025b9250929050565b6000816004811115614e1757614e17615b41565b03614e1f5750565b6001816004811115614e3357614e33615b41565b03614e805760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016112c7565b6002816004811115614e9457614e94615b41565b03614ee15760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016112c7565b6003816004811115614ef557614ef5615b41565b03611e785760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016112c7565b600854604051627eeac760e11b81526001600160a01b03838116600483015260016024830152600092169062fdd58e90604401602060405180830381865afa158015614f9d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b09190615a9c565b60408051600080825260208201928390529182916001600160a01b038616918591614feb91615b57565b60006040518083038185875af1925050503d8060008114615028576040519150601f19603f3d011682016040523d82523d6000602084013e61502d565b606091505b509095945050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561506f57506000905060036150f3565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156150c3573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166150ec576000600192509250506150f3565b9150600090505b94509492505050565b6001600160e01b031981168114611e7857600080fd5b60006020828403121561512457600080fd5b81356123e2816150fc565b60006020828403121561514157600080fd5b5035919050565b60005b8381101561516357818101518382015260200161514b565b50506000910152565b602081526000825180602084015261518b816040850160208701615148565b601f01601f19169190910160400192915050565b80356001600160a01b038116811461230057600080fd5b600080604083850312156151c957600080fd5b6151d28361519f565b946020939093013593505050565b80356001600160801b038116811461230057600080fd5b8015158114611e7857600080fd5b60008060006060848603121561521a57600080fd5b8335925061522a602085016151e0565b9150604084013561523a816151f7565b809150509250925092565b60008060006060848603121561525a57600080fd5b83359250602084013561522a816151f7565b60006020828403121561527e57600080fd5b6123e28261519f565b60006020828403121561529957600080fd5b81356123e2816151f7565b600080604083850312156152b757600080fd5b82359150611be9602084016151e0565b60008083601f8401126152d957600080fd5b5081356001600160401b038111156152f057600080fd5b602083019150836020828501011115614dfc57600080fd5b6000806000806060858703121561531e57600080fd5b8435935061532e6020860161519f565b925060408501356001600160401b0381111561534957600080fd5b615355878288016152c7565b95989497509550505050565b60008060006060848603121561537657600080fd5b61537f8461519f565b925061538d6020850161519f565b9150604084013590509250925092565b600080604083850312156153b057600080fd5b50508035926020909101359150565b600080604083850312156153d257600080fd5b6153db8361519f565b915060208301356153eb816151f7565b809150509250929050565b60008060008060008060c0878903121561540f57600080fd5b8635955061541f602088016151e0565b9450604087013561ffff8116811461543657600080fd5b93506060870135615446816151f7565b92506080870135615456816151f7565b915060a0870135615466816151f7565b809150509295509295509295565b6000806040838503121561548757600080fd5b82359150611be96020840161519f565b6000806000604084860312156154ac57600080fd5b8335925060208401356001600160401b038111156154c957600080fd5b6154d5868287016152c7565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715615520576155206154e2565b604052919050565b60006001600160401b03821115615541576155416154e2565b50601f01601f191660200190565b60006020828403121561556157600080fd5b81356001600160401b0381111561557757600080fd5b8201601f8101841361558857600080fd5b803561559b61559682615528565b6154f8565b8181528560208385010111156155b057600080fd5b81602084016020830137600091810160200191909152949350505050565b600080604083850312156155e157600080fd5b6155ea8361519f565b9150611be96020840161519f565b803563ffffffff8116811461230057600080fd5b6000806000806080858703121561562257600080fd5b84359350615632602086016155f8565b9250615640604086016155f8565b915061564e606086016151e0565b905092959194509250565b60008060008060006080868803121561567157600080fd5b61567a8661519f565b94506156886020870161519f565b93506040860135925060608601356001600160401b038111156156aa57600080fd5b6156b6888289016152c7565b969995985093965092949392505050565b600080604083850312156156da57600080fd5b82359150611be9602084016155f8565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082615725576157256156ea565b500490565b600181811c9082168061573e57607f821691505b60208210810361575e57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b600060c0820190506001600160801b038351168252602083015161ffff8082166020850152806040860151166040850152505060608301511515606083015260808301511515608083015260a0830151151560a083015292915050565b63ffffffff81811683821601908082111561580457615804615700565b5092915050565b60008261581a5761581a6156ea565b500690565b80820281158282048414176111b0576111b0615700565b815163ffffffff9081168252602080840151821690830152604080840151909116908201526060808301516001600160a01b0316908201526080808301516001600160801b039081169183019190915260a092830151169181019190915260c00190565b818103818111156111b0576111b0615700565b808201808211156111b0576111b0615700565b6000600182016158d2576158d2615700565b5060010190565b601f82111561127e57600081815260208120601f850160051c810160208610156159005750805b601f850160051c820191505b81811015612dad5782815560010161590c565b81516001600160401b03811115615938576159386154e2565b61594c81615946845461572a565b846158d9565b602080601f83116001811461598157600084156159695750858301515b600019600386901b1c1916600185901b178555612dad565b600085815260208120601f198616915b828110156159b057888601518255948401946001909101908401615991565b50858210156159ce5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156159f057600080fd5b81516001600160401b03811115615a0657600080fd5b8201601f81018413615a1757600080fd5b8051615a2561559682615528565b818152856020838501011115615a3a57600080fd5b615a4b826020830160208601615148565b95945050505050565b6020808252601190820152701253959053125117d49150d25412515395607a1b604082015260600190565b600060208284031215615a9157600080fd5b81516123e2816150fc565b600060208284031215615aae57600080fd5b5051919050565b600060208284031215615ac757600080fd5b81516123e2816151f7565b61ffff81811683821601908082111561580457615804615700565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b634e487b7160e01b600052602160045260246000fd5b60008251615b69818460208701615148565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa164736f6c6343000811000a44726976657273204c696d697465642045646974696f6e73206279204576657266726573680000000000000000000000003b1bd4c99c059ed58155240fd01d6fc86a430d4d0000000000000000000000006306d0cdfadd6095a313e8484275b6cc7036166c00000000000000000000000085991f5f68b0f3678baae5848dea092c582df0cf00000000000000000000000000000000000000000000000000000000000002ee0000000000000000000000008d12974b9003112ecb9f58d60095cc03bef8f0e300000000000000000000000016f444f2d9e696834c1c9b536dc3896e1b545213
Deployed Bytecode
0x60806040526004361061049f5760003560e01c8063864bc0a011610260578063b9c2443d11610144578063d7e45cd7116100c1578063e3faad9411610085578063e3faad9414611067578063e8a3d485146110a9578063e985e9c5146110be578063ef6ea27a146110f9578063f9e3c46f14611131578063fb796e6c1461117157600080fd5b8063d7e45cd714610fd1578063e07b1afb14610ff2578063e086e5ec14611012578063e17b25af14611027578063e2e784d51461104757600080fd5b8063c87b56dd11610108578063c87b56dd14610f0e578063cb93752814610f2e578063d2e4b90514610f4e578063d46e7ae114610f88578063d4ddce8a14610f9b57600080fd5b8063b9c2443d14610e28578063bdaaf19414610e48578063bf40defb14610e81578063bfe29d5714610ebd578063c0fd735b14610ef957600080fd5b8063a2df15e2116101dd578063a6d23e10116101a1578063a6d23e1014610d61578063aa05234114610d81578063abadb36514610da1578063af4fddfa14610db4578063b7c0b8e814610de8578063b88d4fde14610e0857600080fd5b8063a2df15e214610ca1578063a415729614610cb7578063a43b87a214610ce4578063a522ad2514610d21578063a5aef37d14610d4157600080fd5b806395d89b411161022457806395d89b4114610c0657806396b5a75514610c1b5780639886973114610c3b5780639979ef4514610c6e578063a22cb46514610c8157600080fd5b8063864bc0a014610b6d5780638a87551214610b805780638da5cb5b14610bb0578063923d8dfa14610bd0578063938e3d7b14610be657600080fd5b8063392f37e9116103875780635e1c074611610304578063695747c2116102c8578063695747c214610a88578063702f9bbe14610aa85780637048027514610ae057806370a0823114610b00578063777de70414610b205780637ecebe0014610b4057600080fd5b80635e1c0746146109e95780635e1e1004146109fe578063633511bb14610a1e5780636352211e14610a5557806365a1e83314610a7557600080fd5b80634588d1c71161034b5780634588d1c7146108ac57806346d8efad146108cc57806349df728c146108ec5780635090d0c61461090c578063571a26a01461092257600080fd5b8063392f37e9146107f75780633fc8cef31461081757806342842e0e1461083c57806342966c681461085c578063429b62e51461087c57600080fd5b80631551b7c11161042057806326645a2c116103e457806326645a2c146106cc5780632a55205a146107035780632e9936111461074257806331cb61051461076257806331ccd4bc1461078257806333465c5f146107bd57600080fd5b80631551b7c1146106395780631785f53c1461065957806319ffb5831461067957806320f3f8451461069957806323b872dd146106ac57600080fd5b80630a87c3cf116104675780630a87c3cf146105995780630e9e835c146105b957806311a774fd146105d957806313af4035146105f957806314dfc68e1461061957600080fd5b806301ffc9a7146104a457806306d715fa146104d957806306fdde0314610507578063081812fc14610529578063095ea7b314610577575b600080fd5b3480156104b057600080fd5b506104c46104bf366004615112565b61118b565b60405190151581526020015b60405180910390f35b3480156104e557600080fd5b506104f96104f436600461512f565b6111b6565b6040519081526020016104d0565b34801561051357600080fd5b5061051c6111d1565b6040516104d0919061516c565b34801561053557600080fd5b5061055f61054436600461512f565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016104d0565b34801561058357600080fd5b506105976105923660046151b6565b61125f565b005b3480156105a557600080fd5b506105976105b4366004615205565b611283565b3480156105c557600080fd5b506104c46105d436600461512f565b611467565b3480156105e557600080fd5b506105976105f4366004615245565b611515565b34801561060557600080fd5b5061059761061436600461526c565b6116df565b34801561062557600080fd5b506104f961063436600461512f565b61176f565b34801561064557600080fd5b50610597610654366004615287565b61178e565b34801561066557600080fd5b5061059761067436600461526c565b6117f0565b34801561068557600080fd5b506105976106943660046152a4565b61187e565b6105976106a7366004615308565b611a8a565b3480156106b857600080fd5b506105976106c7366004615361565b611b7a565b3480156106d857600080fd5b506104c46106e736600461512f565b600090815260106020526040902054600160a01b900460ff1690565b34801561070f57600080fd5b5061072361071e36600461539d565b611bb0565b604080516001600160a01b0390931683526020830191909152016104d0565b34801561074e57600080fd5b5061059761075d36600461512f565b611bf2565b34801561076e57600080fd5b5061059761077d3660046153bf565b611d84565b34801561078e57600080fd5b506104c461079d36600461512f565b600090815260106020526040902054600160801b900461ffff1660011490565b3480156107c957600080fd5b506104f96107d836600461512f565b600090815260136020526040902054600160201b900463ffffffff1690565b34801561080357600080fd5b5060095461055f906001600160a01b031681565b34801561082357600080fd5b50600f5461055f9061010090046001600160a01b031681565b34801561084857600080fd5b50610597610857366004615361565b611df3565b34801561086857600080fd5b5061059761087736600461512f565b611e23565b34801561088857600080fd5b506104c461089736600461526c565b60076020526000908152604090205460ff1681565b3480156108b857600080fd5b506105976108c73660046153f6565b611e7b565b3480156108d857600080fd5b506105976108e73660046153bf565b61216a565b3480156108f857600080fd5b5061059761090736600461526c565b6121bc565b34801561091857600080fd5b506104f960145481565b34801561092e57600080fd5b5061099a61093d36600461512f565b6013602052600090815260409020805460019091015463ffffffff80831692600160201b8104821692600160401b820490921691600160601b9091046001600160a01b0316906001600160801b0380821691600160801b90041686565b6040805163ffffffff9788168152958716602087015293909516928401929092526001600160a01b031660608301526001600160801b03908116608083015290911660a082015260c0016104d0565b3480156109f557600080fd5b50610597612217565b348015610a0a57600080fd5b50610597610a1936600461526c565b612221565b348015610a2a57600080fd5b506104c4610a3936600461512f565b600090815260106020526040902054600160a81b900460ff1690565b348015610a6157600080fd5b5061055f610a7036600461512f565b6122ae565b610597610a83366004615474565b612305565b348015610a9457600080fd5b506104f9610aa336600461539d565b6123d6565b348015610ab457600080fd5b506104f9610ac336600461512f565b600090815260106020526040902054600160801b900461ffff1690565b348015610aec57600080fd5b50610597610afb36600461526c565b6123e9565b348015610b0c57600080fd5b506104f9610b1b36600461526c565b61247a565b348015610b2c57600080fd5b506104f9610b3b36600461512f565b6124dd565b348015610b4c57600080fd5b506104f9610b5b36600461526c565b600e6020526000908152604090205481565b610597610b7b366004615497565b61258a565b348015610b8c57600080fd5b506104c4610b9b36600461526c565b600d6020526000908152604090205460ff1681565b348015610bbc57600080fd5b5060065461055f906001600160a01b031681565b348015610bdc57600080fd5b506104f960125481565b348015610bf257600080fd5b50610597610c0136600461554f565b612672565b348015610c1257600080fd5b5061051c6126c2565b348015610c2757600080fd5b50610597610c3636600461512f565b6126cf565b348015610c4757600080fd5b506104f9610c5636600461512f565b60009081526013602052604090205463ffffffff1690565b610597610c7c36600461512f565b61279c565b348015610c8d57600080fd5b50610597610c9c3660046153bf565b61286c565b348015610cad57600080fd5b506104f960115481565b348015610cc357600080fd5b5061051c604051806040016040528060018152602001603160f81b81525081565b348015610cf057600080fd5b5061055f610cff36600461512f565b600090815260136020526040902054600160601b90046001600160a01b031690565b348015610d2d57600080fd5b50610597610d3c3660046155ce565b61288b565b348015610d4d57600080fd5b50610597610d5c36600461560c565b6128d9565b348015610d6d57600080fd5b5060155461055f906001600160a01b031681565b348015610d8d57600080fd5b506104c4610d9c36600461512f565b612ba8565b610597610daf366004615308565b612c3b565b348015610dc057600080fd5b506104f97f9a1ad8626c8e414784b966be6c93b2550ea90ccdf34423b1e4aca0c3b942ada581565b348015610df457600080fd5b50610597610e03366004615287565b612d24565b348015610e1457600080fd5b50610597610e23366004615659565b612d7b565b348015610e3457600080fd5b50610597610e433660046156c7565b612db5565b348015610e5457600080fd5b506104f9610e6336600461512f565b6000908152601360205260409020600101546001600160801b031690565b348015610e8d57600080fd5b506104c4610e9c36600461512f565b6000908152601060205260409020546001600160801b90910461ffff161190565b348015610ec957600080fd5b506104c4610ed836600461512f565b600090815260136020526040902054600160401b900463ffffffff16151590565b348015610f0557600080fd5b50610597612fc3565b348015610f1a57600080fd5b5061051c610f2936600461512f565b6130a1565b348015610f3a57600080fd5b50610597610f493660046156c7565b613113565b348015610f5a57600080fd5b506104f9610f6936600461512f565b600090815260136020526040902054600160401b900463ffffffff1690565b610597610f96366004615474565b613320565b348015610fa757600080fd5b506104f9610fb636600461512f565b6000908152601060205260409020546001600160801b031690565b348015610fdd57600080fd5b506009546104c490600160a01b900460ff1681565b348015610ffe57600080fd5b50600b5461055f906001600160a01b031681565b34801561101e57600080fd5b506105976133f1565b34801561103357600080fd5b5061059761104236600461526c565b61346b565b34801561105357600080fd5b506105976110623660046151b6565b6134b8565b34801561107357600080fd5b5061051c60405180604001604052806016815260200175447269766572734c696d6974656445646974696f6e7360501b81525081565b3480156110b557600080fd5b5061051c613506565b3480156110ca57600080fd5b506104c46110d93660046155ce565b600560209081526000928352604080842090915290825290205460ff1681565b34801561110557600080fd5b506104f961111436600461512f565b600090815260106020526040902054600160901b900461ffff1690565b34801561113d57600080fd5b506104f961114c36600461512f565b600090815260136020526040902060010154600160801b90046001600160801b031690565b34801561117d57600080fd5b50600f546104c49060ff1681565b60006001600160e01b0319821663152a902d60e11b14806111b057506111b082613513565b92915050565b60006103e882106111c5575090565b6111b06103e883615716565b600080546111de9061572a565b80601f016020809104026020016040519081016040528092919081815260200182805461120a9061572a565b80156112575780601f1061122c57610100808354040283529160200191611257565b820191906000526020600020905b81548152906001019060200180831161123a57829003601f168201915b505050505081565b81600f5460ff16156112745761127481613561565b61127e83836135a5565b505050565b6006546001600160a01b03163314806112ab57503360009081526007602052604090205460ff165b6112d05760405162461bcd60e51b81526004016112c790615764565b60405180910390fd5b6000838152601060209081526040808320815160c08101835290546001600160801b038116825261ffff600160801b82048116948301859052600160901b8204169282019290925260ff600160a01b8304811615156060830152600160a81b8304811615156080830152600160b01b909204909116151560a0820152910361136b576040516347c0cce560e01b815260040160405180910390fd5b6001600160801b03808416825282151560a08301908152600086815260106020908152604091829020855181549287015184880151606089015160808a015197511515600160b01b0260ff60b01b19981515600160a81b029890981661ffff60a81b19911515600160a01b0260ff60a01b1961ffff948516600160901b021662ffffff60901b1994909516600160801b026001600160901b031990981695909a1694909417959095171617959095179190911693909317919091179091555184907fc190e68218b7249bd1d46cf62b59253a4b51eed2bfb8924a7a56661fb9a473489061145990849061578a565b60405180910390a250505050565b6000818152601360208181526040808420815160c081018352815463ffffffff8082168352600160201b8204811683870152600160401b820416938201849052600160601b90046001600160a01b031660608201526001909101546001600160801b038082166080840152600160801b9091041660a08201528585529290915215801590819061150d57508151604083015161150391906157e7565b63ffffffff164210155b949350505050565b6006546001600160a01b031633148061153d57503360009081526007602052604090205460ff165b6115595760405162461bcd60e51b81526004016112c790615764565b6000838152601060209081526040808320815160c08101835290546001600160801b038116825261ffff600160801b82048116948301859052600160901b8204169282019290925260ff600160a01b8304811615156060830152600160a81b8304811615156080830152600160b01b909204909116151560a082015291036115f4576040516347c0cce560e01b815260040160405180910390fd5b82151560608201908152821515608083019081526000868152601060209081526040918290208551815492870151848801519651955160a08901511515600160b01b0260ff60b01b19911515600160a81b029190911661ffff60a81b19971515600160a01b0260ff60a01b1961ffff9a8b16600160901b021662ffffff60901b199a909416600160801b026001600160901b03199097166001600160801b03909516949094179590951797909716171793909316179290921790555184907fea454d1e05d501c547b57c90d87e01eaef34d99308681d143ec564111cf7763a9061145990849061578a565b6006546001600160a01b031633148061170757503360009081526007602052604090205460ff165b6117235760405162461bcd60e51b81526004016112c790615764565b600680546001600160a01b0319166001600160a01b03831690811790915560405133907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a350565b60006103e8821061178257506000919050565b6111b06103e88361580b565b6006546001600160a01b03163314806117b657503360009081526007602052604090205460ff165b6117d25760405162461bcd60e51b81526004016112c790615764565b60158054911515600160a01b0260ff60a01b19909216919091179055565b6006546001600160a01b031633148061181857503360009081526007602052604090205460ff165b6118345760405162461bcd60e51b81526004016112c790615764565b6001600160a01b038116600081815260076020526040808220805460ff19169055517fdb9d5d31320daf5bc7181d565b6da4d12e30f0f4d5aa324a992426c14a1d19ce908290a350565b6006546001600160a01b03163314806118a657503360009081526007602052604090205460ff165b6118c25760405162461bcd60e51b81526004016112c790615764565b806001600160801b03166000036118ec57604051633646340760e21b815260040160405180910390fd5b6000828152601360209081526040808320815160c081018352815463ffffffff8082168352600160201b82048116958301869052600160401b82041693820193909352600160601b9092046001600160a01b03166060830152600101546001600160801b038082166080840152600160801b9091041660a082015291036119865760405163e6759c6760e01b815260040160405180910390fd5b604081015163ffffffff16156119af5760405163628e388360e01b815260040160405180910390fd5b6001600160801b0380831660a0830181815260008681526013602090815260408083208751815493890151838a015160608b01516001600160a01b0316600160601b026001600160601b0363ffffffff928316600160401b02166001600160401b03938316600160201b0267ffffffffffffffff199098169290941691909117959095171617929092178255608087015193518616600160801b0293909516929092176001909201919091559151909185917fd44c1f367e4b7835166bd3805433cc6133391fa6e0099d7303ec10205c9efcb89190a3505050565b601554600160a01b900460ff16611ab457604051637e19eeed60e11b815260040160405180910390fd5b600084815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b8204811615801560808501819052600160b01b909304909116151560a0840152611b4a5750611b4885858585613687565b155b15611b6857604051638baa579f60e01b815260040160405180910390fd5b611b738585836137e0565b5050505050565b826001600160a01b0381163314611b9f57600f5460ff1615611b9f57611b9f33613561565b611baa848484613b33565b50505050565b600a546001600160a01b0381169060009061271090611bdf90600160a01b90046001600160601b03168561581f565b611be99190615716565b90509250929050565b6000818152601360209081526040808320815160c081018352815463ffffffff8082168352600160201b8204811695830195909552600160401b8104909416928101839052600160601b9093046001600160a01b03166060840152600101546001600160801b038082166080850152600160801b9091041660a0830152909103611c8f576040516301dff5d560e71b815260040160405180910390fd5b805160408201514291611ca1916157e7565b63ffffffff161115611cc657604051636463738960e01b815260040160405180910390fd5b600b546000838152600260205260409020546001600160a01b03908116911614611d0357604051631b42fb7f60e31b815260040160405180910390fd5b611d11816060015183613cc4565b60405182907f7bb9aafce2f4a89681d211146eaa6c59ec03a137171363e78aa243d7d0bf36d890600090a26014805460001901905560405182907f2be75b1f4f563cd2d2d28f28e51ddcb63c202fa685d6202078fa5376c8269d3490611d78908490615836565b60405180910390a25050565b6006546001600160a01b0316331480611dac57503360009081526007602052604090205460ff165b611dc85760405162461bcd60e51b81526004016112c790615764565b6001600160a01b03919091166000908152600d60205260409020805460ff1916911515919091179055565b826001600160a01b0381163314611e1857600f5460ff1615611e1857611e1833613561565b611baa848484613dca565b33611e2d826122ae565b6001600160a01b031614611e6f5760405162461bcd60e51b81526020600482015260096024820152682727aa2fa7aba722a960b91b60448201526064016112c7565b611e7881613ebd565b50565b6006546001600160a01b0316331480611ea357503360009081526007602052604090205460ff165b611ebf5760405162461bcd60e51b81526004016112c790615764565b611ecd6103e8600019615716565b861115611eed57604051630a779b1560e21b815260040160405180910390fd5b8361ffff16600003611f1257604051634d74210f60e11b815260040160405180910390fd5b611f1f60016103e861589a565b8461ffff161115611f43576040516317ee9bc760e21b815260040160405180910390fd5b600086815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b82048116938301849052600160901b8204169382019390935260ff600160a01b8404811615156060830152600160a81b8404811615156080830152600160b01b909304909216151560a083015215611fde576040516320705a1b60e11b815260040160405180910390fd5b6001600160801b03808716825261ffff8087166020808501918252871515606086019081528715156080870190815287151560a0880190815260008e81526010909452604093849020885181549651868b01519551945193511515600160b01b0260ff60b01b19941515600160a81b029490941661ffff60a81b19951515600160a01b0260ff60a01b19978b16600160901b029790971662ffffff60901b1992909a16600160801b026001600160901b031990991692909a16919091179690961795909516959095179190911716939093179190911790555187907f2f4457ef75a9f3a9d9845f891558d05d38ead4a1df33f2d5a3c14bfe653fba8c906120e690849061578a565b60405180910390a28461ffff1660010361211557600b54612110906001600160a01b031688613f78565b612161565b60005b8561ffff1681101561215f57600b5461214d906001600160a01b03166121488a6121438560016158ad565b61404d565b613f78565b80612157816158c0565b915050612118565b505b50505050505050565b6006546001600160a01b031633148061219257503360009081526007602052604090205460ff165b6121ae5760405162461bcd60e51b81526004016112c790615764565b6121b88282614066565b5050565b6006546001600160a01b03163314806121e457503360009081526007602052604090205460ff165b6122005760405162461bcd60e51b81526004016112c790615764565b601554611e789082906001600160a01b03166140db565b61221f614227565b565b6006546001600160a01b031633148061224957503360009081526007602052604090205460ff165b6122655760405162461bcd60e51b81526004016112c790615764565b6001600160a01b03811661228c57604051631f4c499760e01b815260040160405180910390fd5b601580546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600260205260409020546001600160a01b0316806123005760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b60448201526064016112c7565b919050565b601554600160a01b900460ff1661232f57604051637e19eeed60e11b815260040160405180910390fd5b600082815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b820481161580156080850152600160b01b90920416151560a08301526123cb57604051630426ff7760e01b815260040160405180910390fd5b61127e8383836137e0565b60006123e2838361404d565b9392505050565b6006546001600160a01b031633148061241157503360009081526007602052604090205460ff165b61242d5760405162461bcd60e51b81526004016112c790615764565b6001600160a01b038116600081815260076020526040808220805460ff19166001179055517fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b908290a350565b60006001600160a01b0382166124c15760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b60448201526064016112c7565b506001600160a01b031660009081526003602052604090205490565b6000818152601360208181526040808420815160c081018352815463ffffffff8082168352600160201b8204811683870152600160401b820416938201849052600160601b90046001600160a01b031660608201526001909101546001600160801b038082166080840152600160801b9091041660a08201528585529290915215158061256b57600061257c565b8151602083015161257c91906157e7565b63ffffffff16949350505050565b601554600160a01b900460ff166125b457604051637e19eeed60e11b815260040160405180910390fd5b600083815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b8204811615801560808501819052600160b01b909304909116151560a084015261264a575061264884338585613687565b155b1561266857604051638baa579f60e01b815260040160405180910390fd5b611baa8482614246565b6006546001600160a01b031633148061269a57503360009081526007602052604090205460ff165b6126b65760405162461bcd60e51b81526004016112c790615764565b600c6121b8828261591f565b600180546111de9061572a565b6006546001600160a01b03163314806126f757503360009081526007602052604090205460ff165b6127135760405162461bcd60e51b81526004016112c790615764565b600081815260136020908152604091829020825160c081018452815463ffffffff8082168352600160201b8204811694830194909452600160401b810490931693810193909352600160601b9091046001600160a01b03166060830152600101546001600160801b038082166080840152600160801b9091041660a08201526121b88282614546565b601554600160a01b900460ff166127c657604051637e19eeed60e11b815260040160405180910390fd5b600081815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b820481161580156080850152600160b01b90920416151560a083015261286257604051630426ff7760e01b815260040160405180910390fd5b6121b88282614246565b81600f5460ff16156128815761288181613561565b61127e83836145f4565b6006546001600160a01b03163314806128b357503360009081526007602052604090205460ff165b6128cf5760405162461bcd60e51b81526004016112c790615764565b6121b882826140db565b6006546001600160a01b031633148061290157503360009081526007602052604090205460ff165b61291d5760405162461bcd60e51b81526004016112c790615764565b8263ffffffff16600003612944576040516335f7aa5b60e11b815260040160405180910390fd5b8163ffffffff1660000361296b57604051634b6e1bd360e01b815260040160405180910390fd5b600084815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b82048116938301849052600160901b8204169382019390935260ff600160a01b8404811615156060830152600160a81b8404811615156080830152600160b01b909304909216151560a0830152600114612a0857604051630eea117d60e31b815260040160405180910390fd5b600085815260136020908152604091829020825160c081018452815463ffffffff8082168352600160201b82048116948301859052600160401b82041694820194909452600160601b9093046001600160a01b03166060840152600101546001600160801b038082166080850152600160801b9091041660a083015215612aa157604051628b039960e31b815260040160405180910390fd5b63ffffffff808616825284811660208084019182526001600160801b0380871660a0860190815260008b815260139093526040928390208651815495518589015160608a01516001600160a01b0316600160601b026001600160601b03918a16600160401b02919091166001600160401b03928a16600160201b0267ffffffffffffffff199099169390991692909217969096179590951695909517939093178455608085015192518116600160801b02921691909117600192830155601480549092019091555186907f67e0934daec5a59c2ce373b1d94d8160057ae0a6cfa7a01ccdfc12d63f5ae7fb90612b98908490615836565b60405180910390a2505050505050565b6000818152601060209081526040808320815160c08101835290546001600160801b03811680835261ffff600160801b8304811695840195909552600160901b82049094169282019290925260ff600160a01b8304811615156060830152600160a81b8304811615156080830152600160b01b909204909116151560a0820152901580156123e2575060a0015192915050565b601554600160a01b900460ff16612c6557604051637e19eeed60e11b815260040160405180910390fd5b600084815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b8204811615801560808501819052600160b01b909304909116151560a0840152612cfb5750612cf985858585613687565b155b15612d1957604051638baa579f60e01b815260040160405180910390fd5b611b73858583614660565b6006546001600160a01b0316331480612d4c57503360009081526007602052604090205460ff165b612d685760405162461bcd60e51b81526004016112c790615764565b600f805460ff1916911515919091179055565b846001600160a01b0381163314612da057600f5460ff1615612da057612da033613561565b612dad8686868686614886565b505050505050565b6006546001600160a01b0316331480612ddd57503360009081526007602052604090205460ff165b612df95760405162461bcd60e51b81526004016112c790615764565b8063ffffffff16600003612e2057604051634b6e1bd360e01b815260040160405180910390fd5b6000828152601360209081526040808320815160c081018352815463ffffffff8082168352600160201b82048116958301869052600160401b82041693820193909352600160601b9092046001600160a01b03166060830152600101546001600160801b038082166080840152600160801b9091041660a08201529103612eba5760405163e6759c6760e01b815260040160405180910390fd5b604081015163ffffffff1615612ee35760405163628e388360e01b815260040160405180910390fd5b63ffffffff80831660208084018281526000878152601390925260408083208651815493518389015160608a01516001600160a01b0316600160601b026001600160601b03918a16600160401b02919091166001600160401b03928a16600160201b0267ffffffffffffffff199097169390991692909217949094179390931695909517919091178455608085015160a08601516001600160801b03908116600160801b029116176001909401939093559151909185917f7076391b57145201e1b1e818500795c44fda2ae9af4dc5f2ea3d36a5539eb7779190a3505050565b6006546001600160a01b0316331480612feb57503360009081526007602052604090205460ff165b6130075760405162461bcd60e51b81526004016112c790615764565b6014541561302857604051630745ab4760e51b815260040160405180910390fd5b60155461303d906001600160a01b0316614967565b601560009054906101000a90046001600160a01b03166001600160a01b031663465105f06040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561308d57600080fd5b505af1158015611baa573d6000803e3d6000fd5b60095460405163c87b56dd60e01b8152600481018390526060916001600160a01b03169063c87b56dd90602401600060405180830381865afa1580156130eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111b091908101906159de565b6006546001600160a01b031633148061313b57503360009081526007602052604090205460ff165b6131575760405162461bcd60e51b81526004016112c790615764565b8063ffffffff1660000361317e576040516335f7aa5b60e11b815260040160405180910390fd5b6000828152601360209081526040808320815160c081018352815463ffffffff8082168352600160201b82048116958301869052600160401b82041693820193909352600160601b9092046001600160a01b03166060830152600101546001600160801b038082166080840152600160801b9091041660a082015291036132185760405163e6759c6760e01b815260040160405180910390fd5b604081015163ffffffff16156132415760405163628e388360e01b815260040160405180910390fd5b63ffffffff808316808352600085815260136020908152604080832086518154938801518389015160608a01516001600160a01b0316600160601b026001600160601b03918a16600160401b02919091166001600160401b03928a16600160201b0267ffffffffffffffff199097169390991692909217949094179390931695909517919091178455608085015160a08601516001600160801b03908116600160801b029116176001909401939093559151909185917f9702db1e67fa6b64b8288101859f3b327a978f15d66e12ad769e5bbf30814d289190a3505050565b601554600160a01b900460ff1661334a57604051637e19eeed60e11b815260040160405180910390fd5b600082815260106020908152604091829020825160c08101845290546001600160801b038116825261ffff600160801b8204811693830193909352600160901b81049092169281019290925260ff600160a01b8204811615156060840152600160a81b820481161580156080850152600160b01b90920416151560a08301526133e657604051630426ff7760e01b815260040160405180910390fd5b61127e838383614660565b6006546001600160a01b031633148061341957503360009081526007602052604090205460ff165b6134355760405162461bcd60e51b81526004016112c790615764565b6014541561345657604051630745ab4760e51b815260040160405180910390fd5b60155461221f906001600160a01b0316614967565b6006546001600160a01b031633148061349357503360009081526007602052604090205460ff165b6134af5760405162461bcd60e51b81526004016112c790615764565b611e7881614a25565b6006546001600160a01b03163314806134e057503360009081526007602052604090205460ff165b6134fc5760405162461bcd60e51b81526004016112c790615764565b6121b88282614a9a565b600c80546111de9061572a565b60006301ffc9a760e01b6001600160e01b03198316148061354457506380ac58cd60e01b6001600160e01b03198316145b806111b05750506001600160e01b031916635b5e139f60e01b1490565b69c617113400112233445560005230601a5280603a52600080604460166daaeb6d7670e522a718067333cd4e5afa61359d573d6000803e3d6000fd5b6000603a5250565b6000818152600260205260409020546001600160a01b0316338114806135ee57506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b61362b5760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016112c7565b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b604080516080810182528581526001600160a01b03851660208083018290526000918252600e815283822054838501528351601f860182900482028101820190945284845290928392916060830191908790879081908401838280828437600092018290525093909452505082516020808501516001600160a01b0381168452600e909152604083208054959650929461378f94507f9a1ad8626c8e414784b966be6c93b2550ea90ccdf34423b1e4aca0c3b942ada59386613748836158c0565b909155506040805160208101959095528401929092526001600160a01b03166060830152608082015260a00160405160208183030381529060405280519060200120614b1d565b905060006137a1828460600151614b6b565b6001600160a01b0381166000908152600d602052604090205490915060ff1680156137d457506001600160a01b03811615155b98975050505050505050565b806020015161ffff1660011461380957604051630eea117d60e31b815260040160405180910390fd5b8060a00151158015613823575080516001600160801b0316155b1561384157604051631d99ddbf60e01b815260040160405180910390fd5b80516001600160801b0316341461386b57604051636992e1ff60e01b815260040160405180910390fd5b80606001518015613882575061388082614b8f565b155b156138a057604051633664886760e11b815260040160405180910390fd5b600083815260136020908152604091829020825160c081018452815463ffffffff8082168352600160201b8204811694830194909452600160401b8104909316938101849052600160601b9092046001600160a01b03166060830152600101546001600160801b038082166080840152600160801b9091041660a08201529015613a375760408101516139399063ffffffff164261589a565b63ffffffff908116825260008581526013602090815260409182902084518154928601519386015160608701516001600160a01b038116600160601b026001600160601b03928816600160401b02929092166001600160401b03968816600160201b0267ffffffffffffffff199096169390971692909217939093179390931693909317178255608083015160a08401516001600160801b03908116600160801b0291169081176001909301929092556139f291614ba2565b6014805460001901905560405184907f4215ff61a9831416ed985d067257b9f8802a061f560876a779ebc5f3c6189fe890613a2e908490615836565b60405180910390a25b6040808301805161ffff600190910181168252600087815260106020908152939020855181549487015193516060880151608089015160a08a01511515600160b01b0260ff60b01b19911515600160a81b029190911661ffff60a81b19921515600160a01b0260ff60a01b19948816600160901b029490941662ffffff60901b1998909716600160801b026001600160901b03199099166001600160801b0390951694909417979097179590951693909317929092179290921617919091179055613b028385613cc4565b60405184907f7bb9aafce2f4a89681d211146eaa6c59ec03a137171363e78aa243d7d0bf36d890600090a250505050565b6000818152600260205260409020546001600160a01b03848116911614613b895760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016112c7565b6001600160a01b038216613baf5760405162461bcd60e51b81526004016112c790615a54565b336001600160a01b0384161480613be957506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b80613c0a57506000818152600460205260409020546001600160a01b031633145b613c475760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016112c7565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b0319908116831790915560049092528483208054909216909155925184939291600080516020615b7483398151915291a4505050565b600081815260026020526040902054600b546001600160a01b03908116911614613d1d5760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016112c7565b6001600160a01b038216613d435760405162461bcd60e51b81526004016112c790615a54565b600b80546001600160a01b0390811660009081526003602090815260408083208054600019019055868416808452818420805460010190558684526002835281842080546001600160a01b031990811683179091556004909352818420805490931690925593549351859491939190911691600080516020615b7483398151915291a45050565b613dd5838383611b7a565b6001600160a01b0382163b1580613e7e5750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015613e4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e729190615a7f565b6001600160e01b031916145b61127e5760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016112c7565b6000818152600260205260409020546001600160a01b031680613f0f5760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b60448201526064016112c7565b6001600160a01b038116600081815260036020908152604080832080546000190190558583526002825280832080546001600160a01b03199081169091556004909252808320805490921690915551849290600080516020615b74833981519152908390a45050565b6001600160a01b038216613f9e5760405162461bcd60e51b81526004016112c790615a54565b6000818152600260205260409020546001600160a01b031615613ff45760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b60448201526064016112c7565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b031916841790555183929190600080516020615b74833981519152908290a45050565b60008161405c6103e88561581f565b6123e291906158ad565b6001600160a01b0390911690637d3e3dbe81614093578261408c5750634420e486614093565b5063a0af29035b8060e01b60005230600452826024526004600060446000806daaeb6d7670e522a718067333cd4e5af16140d1578060005160e01c036140d157600080fd5b5060006024525050565b6001600160a01b0381166141025760405163172fe2d160e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015614149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061416d9190615a9c565b9050806000036141905760405163334ab3f560e11b815260040160405180910390fd5b60405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390526000919085169063a9059cbb906044016020604051808303816000875af11580156141e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142079190615ab5565b905080611baa57604051631d42c86760e21b815260040160405180910390fd5b61221f733cc6cdda760b79bafa08df41ecfa224f810dceb66001614066565b8060600151801561425d575061425b33614b8f565b155b1561427b57604051633664886760e11b815260040160405180910390fd5b600082815260136020908152604091829020825160c081018452815463ffffffff8082168352600160201b82048116948301859052600160401b82041694820194909452600160601b9093046001600160a01b03166060840152600101546001600160801b038082166080850152600160801b9091041660a0830152158061430c575042816020015163ffffffff16115b1561432a576040516301dff5d560e71b815260040160405180910390fd5b806040015163ffffffff1660000361439257348160a001516001600160801b031611156143815760a0810151604051635cf8b88960e11b81526001600160801b0390911660048201523460248201526044016112c7565b63ffffffff42166040820152614431565b805160408201516143a391906157e7565b63ffffffff164211156143c95760405163283a4a6160e21b815260040160405180910390fd5b600081608001516001600160801b03169050600060646012548302816143f1576143f16156ea565b0482019050348111156144205760405163bc1510d560e01b8152600481018290523460248201526044016112c7565b61442e836060015183614ba2565b50505b346001600160601b0316608082015233606082015280516040820151601154429190920163ffffffff16039081101561447757601154825163ffffffff91839003011682525b60008481526013602090815260409182902084518154928601518487015160608801516001600160a01b0316600160601b026001600160601b0363ffffffff928316600160401b02166001600160401b03938316600160201b0267ffffffffffffffff199097169290941691909117949094171617919091178155608084015160a08501516001600160801b03908116600160801b029116176001909101555184907f90e14ed1433e5f6856e46c6068401974e908b3ef4a8ecd5401cbd68d8b4c2a1f90611459908590615836565b604081015163ffffffff16156145a8578051604082015161456791906157e7565b63ffffffff1642111561458d5760405163283a4a6160e21b815260040160405180910390fd5b6145a8816060015182608001516001600160801b0316614ba2565b600082815260136020526040808220828155600101829055601480546000190190555183917f2809c7e17bf978fbc7194c0a694b638c4215e9140cacc6c38ca36010b45697df91a25050565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6002816020015161ffff16101561468a57604051630556890560e01b815260040160405180910390fd5b806020015161ffff16816040015160016146a49190615ad2565b61ffff1611156146c75760405163a8fda6c160e01b815260040160405180910390fd5b8060a001511580156146e1575080516001600160801b0316155b156146ff57604051631d99ddbf60e01b815260040160405180910390fd5b80516001600160801b0316341461472957604051636992e1ff60e01b815260040160405180910390fd5b80606001518015614740575061473e82614b8f565b155b1561475e57604051633664886760e11b815260040160405180910390fd5b6000816040015160016147719190615ad2565b61ffff1690506000614783858361404d565b6040808501805161ffff6001909101811682526000898152601060209081529390208751815494890151935160608a015160808b015160a08c01511515600160b01b0260ff60b01b19911515600160a81b029190911661ffff60a81b19921515600160a01b0260ff60a01b19948816600160901b029490941662ffffff60901b1998909716600160801b026001600160901b03199099166001600160801b039095169490941797909717959095169390931792909217929092161791909117905590506148508482613cc4565b8082867fdf5fda6ef84c661a9a8c7217395c3d91bc7e519453e81fcbfa1f0f2d19a8d5be60405160405180910390a45050505050565b614891858585611b7a565b6001600160a01b0384163b15806149285750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a02906148d99033908a90899089908990600401615aed565b6020604051808303816000875af11580156148f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061491c9190615a7f565b6001600160e01b031916145b611b735760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016112c7565b6001600160a01b03811661498e5760405163172fe2d160e01b815260040160405180910390fd5b4760008190036149b15760405163334ab3f560e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146149fe576040519150601f19603f3d011682016040523d82523d6000602084013e614a03565b606091505b505090508061127e57604051631d42c86760e21b815260040160405180910390fd5b600954600160a01b900460ff1615614a50576040516313ef243160e11b815260040160405180910390fd5b600980546001600160a01b0319166001600160a01b0383169081179091556040517f0713c9f4b0c5db294e61505e6819f6ad0cccf782df1a544939dc55d13fe7fc1c90600090a250565b612710811115614abd576040516303c799a760e61b815260040160405180910390fd5b6040805180820182526001600160a01b03841680825262ffffff84166020909201829052600160a01b9091028117600a5590518291907ff21fccf4d64d86d532c4e4eb86c007b6ad57a460c27d724188625e755ec6cf6d90600090a35050565b60006111b0614b2a614c97565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000806000614b7a8585614dbe565b91509150614b8781614e03565b509392505050565b600080614b9b83614f4d565b1192915050565b614bac8282614fc1565b6121b857600f60019054906101000a90046001600160a01b03166001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015614c0057600080fd5b505af1158015614c14573d6000803e3d6000fd5b5050600f5460405163a9059cbb60e01b81526001600160a01b03878116600483015260248201879052610100909204909116935063a9059cbb925060440190506020604051808303816000875af1158015614c73573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127e9190615ab5565b6000306001600160a01b037f0000000000000000000000002a13ca75851eb518375d6e9cf7d1441bcf4a825816148015614cf057507f000000000000000000000000000000000000000000000000000000000000000146145b15614d1a57507fbb9355a78ff71cb72ba2edbfa1ca21c88d4f8c731533c97c4a677ac5d39ba21b90565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527fb30aa96379938f3d26fa51ee56f3b18dc754d9a68044dec5e47c2a85e3cb898d828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000808251604103614df45760208301516040840151606085015160001a614de887828585615038565b94509450505050614dfc565b506000905060025b9250929050565b6000816004811115614e1757614e17615b41565b03614e1f5750565b6001816004811115614e3357614e33615b41565b03614e805760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016112c7565b6002816004811115614e9457614e94615b41565b03614ee15760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016112c7565b6003816004811115614ef557614ef5615b41565b03611e785760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016112c7565b600854604051627eeac760e11b81526001600160a01b03838116600483015260016024830152600092169062fdd58e90604401602060405180830381865afa158015614f9d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b09190615a9c565b60408051600080825260208201928390529182916001600160a01b038616918591614feb91615b57565b60006040518083038185875af1925050503d8060008114615028576040519150601f19603f3d011682016040523d82523d6000602084013e61502d565b606091505b509095945050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561506f57506000905060036150f3565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156150c3573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166150ec576000600192509250506150f3565b9150600090505b94509492505050565b6001600160e01b031981168114611e7857600080fd5b60006020828403121561512457600080fd5b81356123e2816150fc565b60006020828403121561514157600080fd5b5035919050565b60005b8381101561516357818101518382015260200161514b565b50506000910152565b602081526000825180602084015261518b816040850160208701615148565b601f01601f19169190910160400192915050565b80356001600160a01b038116811461230057600080fd5b600080604083850312156151c957600080fd5b6151d28361519f565b946020939093013593505050565b80356001600160801b038116811461230057600080fd5b8015158114611e7857600080fd5b60008060006060848603121561521a57600080fd5b8335925061522a602085016151e0565b9150604084013561523a816151f7565b809150509250925092565b60008060006060848603121561525a57600080fd5b83359250602084013561522a816151f7565b60006020828403121561527e57600080fd5b6123e28261519f565b60006020828403121561529957600080fd5b81356123e2816151f7565b600080604083850312156152b757600080fd5b82359150611be9602084016151e0565b60008083601f8401126152d957600080fd5b5081356001600160401b038111156152f057600080fd5b602083019150836020828501011115614dfc57600080fd5b6000806000806060858703121561531e57600080fd5b8435935061532e6020860161519f565b925060408501356001600160401b0381111561534957600080fd5b615355878288016152c7565b95989497509550505050565b60008060006060848603121561537657600080fd5b61537f8461519f565b925061538d6020850161519f565b9150604084013590509250925092565b600080604083850312156153b057600080fd5b50508035926020909101359150565b600080604083850312156153d257600080fd5b6153db8361519f565b915060208301356153eb816151f7565b809150509250929050565b60008060008060008060c0878903121561540f57600080fd5b8635955061541f602088016151e0565b9450604087013561ffff8116811461543657600080fd5b93506060870135615446816151f7565b92506080870135615456816151f7565b915060a0870135615466816151f7565b809150509295509295509295565b6000806040838503121561548757600080fd5b82359150611be96020840161519f565b6000806000604084860312156154ac57600080fd5b8335925060208401356001600160401b038111156154c957600080fd5b6154d5868287016152c7565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715615520576155206154e2565b604052919050565b60006001600160401b03821115615541576155416154e2565b50601f01601f191660200190565b60006020828403121561556157600080fd5b81356001600160401b0381111561557757600080fd5b8201601f8101841361558857600080fd5b803561559b61559682615528565b6154f8565b8181528560208385010111156155b057600080fd5b81602084016020830137600091810160200191909152949350505050565b600080604083850312156155e157600080fd5b6155ea8361519f565b9150611be96020840161519f565b803563ffffffff8116811461230057600080fd5b6000806000806080858703121561562257600080fd5b84359350615632602086016155f8565b9250615640604086016155f8565b915061564e606086016151e0565b905092959194509250565b60008060008060006080868803121561567157600080fd5b61567a8661519f565b94506156886020870161519f565b93506040860135925060608601356001600160401b038111156156aa57600080fd5b6156b6888289016152c7565b969995985093965092949392505050565b600080604083850312156156da57600080fd5b82359150611be9602084016155f8565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082615725576157256156ea565b500490565b600181811c9082168061573e57607f821691505b60208210810361575e57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b600060c0820190506001600160801b038351168252602083015161ffff8082166020850152806040860151166040850152505060608301511515606083015260808301511515608083015260a0830151151560a083015292915050565b63ffffffff81811683821601908082111561580457615804615700565b5092915050565b60008261581a5761581a6156ea565b500690565b80820281158282048414176111b0576111b0615700565b815163ffffffff9081168252602080840151821690830152604080840151909116908201526060808301516001600160a01b0316908201526080808301516001600160801b039081169183019190915260a092830151169181019190915260c00190565b818103818111156111b0576111b0615700565b808201808211156111b0576111b0615700565b6000600182016158d2576158d2615700565b5060010190565b601f82111561127e57600081815260208120601f850160051c810160208610156159005750805b601f850160051c820191505b81811015612dad5782815560010161590c565b81516001600160401b03811115615938576159386154e2565b61594c81615946845461572a565b846158d9565b602080601f83116001811461598157600084156159695750858301515b600019600386901b1c1916600185901b178555612dad565b600085815260208120601f198616915b828110156159b057888601518255948401946001909101908401615991565b50858210156159ce5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602082840312156159f057600080fd5b81516001600160401b03811115615a0657600080fd5b8201601f81018413615a1757600080fd5b8051615a2561559682615528565b818152856020838501011115615a3a57600080fd5b615a4b826020830160208601615148565b95945050505050565b6020808252601190820152701253959053125117d49150d25412515395607a1b604082015260600190565b600060208284031215615a9157600080fd5b81516123e2816150fc565b600060208284031215615aae57600080fd5b5051919050565b600060208284031215615ac757600080fd5b81516123e2816151f7565b61ffff81811683821601908082111561580457615804615700565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b634e487b7160e01b600052602160045260246000fd5b60008251615b69818460208701615148565b919091019291505056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa164736f6c6343000811000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003b1bd4c99c059ed58155240fd01d6fc86a430d4d0000000000000000000000006306d0cdfadd6095a313e8484275b6cc7036166c00000000000000000000000085991f5f68b0f3678baae5848dea092c582df0cf00000000000000000000000000000000000000000000000000000000000002ee0000000000000000000000008d12974b9003112ecb9f58d60095cc03bef8f0e300000000000000000000000016f444f2d9e696834c1c9b536dc3896e1b545213
-----Decoded View---------------
Arg [0] : owner_ (address): 0x3B1Bd4C99c059ED58155240FD01D6fC86A430D4D
Arg [1] : admin_ (address): 0x6306D0cDFADD6095A313e8484275b6cC7036166C
Arg [2] : payments_ (address): 0x85991F5F68b0F3678bAAE5848DEa092c582Df0Cf
Arg [3] : royaltiesAmount_ (uint256): 750
Arg [4] : metadata_ (address): 0x8d12974B9003112ecB9F58D60095Cc03BeF8f0e3
Arg [5] : fountCard_ (address): 0x16F444F2d9E696834C1c9b536Dc3896E1B545213
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000003b1bd4c99c059ed58155240fd01d6fc86a430d4d
Arg [1] : 0000000000000000000000006306d0cdfadd6095a313e8484275b6cc7036166c
Arg [2] : 00000000000000000000000085991f5f68b0f3678baae5848dea092c582df0cf
Arg [3] : 00000000000000000000000000000000000000000000000000000000000002ee
Arg [4] : 0000000000000000000000008d12974b9003112ecb9f58d60095cc03bef8f0e3
Arg [5] : 00000000000000000000000016f444f2d9e696834c1c9b536dc3896e1b545213
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.