Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Latest 25 from a total of 227 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Transfer Ownersh... | 17076990 | 1052 days ago | IN | 0 ETH | 0.00163252 | ||||
| Withdraw Bid | 14637451 | 1413 days ago | IN | 0 ETH | 0.0019404 | ||||
| Make Bid | 14637448 | 1413 days ago | IN | 0.3233717 ETH | 0.00430285 | ||||
| Withdraw Bid | 14637447 | 1413 days ago | IN | 0 ETH | 0.0019404 | ||||
| Make Bid | 14637443 | 1413 days ago | IN | 0.2525 ETH | 0.00430285 | ||||
| Withdraw Bid | 14637442 | 1413 days ago | IN | 0 ETH | 0.0019404 | ||||
| Make Bid | 14637441 | 1413 days ago | IN | 0.2222 ETH | 0.00430285 | ||||
| Withdraw Bid | 14637440 | 1413 days ago | IN | 0 ETH | 0.0019404 | ||||
| Make Bid | 14637439 | 1413 days ago | IN | 0.16665 ETH | 0.00430285 | ||||
| Withdraw Bid | 14637438 | 1413 days ago | IN | 0 ETH | 0.0019404 | ||||
| Make Bid | 14637437 | 1413 days ago | IN | 0.1919 ETH | 0.00430285 | ||||
| Withdraw Bid | 14637436 | 1413 days ago | IN | 0 ETH | 0.0019404 | ||||
| Make Bid | 14637430 | 1413 days ago | IN | 0.3535 ETH | 0.00430285 | ||||
| Withdraw Bid | 14637397 | 1413 days ago | IN | 0 ETH | 0.0019404 | ||||
| Make Bid | 14637373 | 1413 days ago | IN | 0.255025 ETH | 0.00430285 | ||||
| Withdraw Bid | 14637371 | 1413 days ago | IN | 0 ETH | 0.0019404 | ||||
| Make Bid | 14637368 | 1413 days ago | IN | 0.2828 ETH | 0.00430285 | ||||
| Withdraw Bid | 14637330 | 1413 days ago | IN | 0 ETH | 0.00213444 | ||||
| Make Bid | 14637327 | 1413 days ago | IN | 0.2525 ETH | 0.00473313 | ||||
| Withdraw Bid | 14637320 | 1413 days ago | IN | 0 ETH | 0.00232848 | ||||
| Make Bid | 14637291 | 1413 days ago | IN | 0.2626 ETH | 0.00516342 | ||||
| Withdraw Bid | 14637262 | 1413 days ago | IN | 0 ETH | 0.00232848 | ||||
| Make Bid | 14637255 | 1413 days ago | IN | 1.313 ETH | 0.00516342 | ||||
| Withdraw Bid | 14637159 | 1413 days ago | IN | 0 ETH | 0.0029106 | ||||
| Make Bid | 14637153 | 1413 days ago | IN | 0.214221 ETH | 0.00645427 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| - | 14637451 | 1413 days ago | 0.3233717 ETH | ||||
| - | 14637448 | 1413 days ago | 0.32017 ETH | ||||
| - | 14637447 | 1413 days ago | 0.2525 ETH | ||||
| - | 14637443 | 1413 days ago | 0.25 ETH | ||||
| - | 14637442 | 1413 days ago | 0.2222 ETH | ||||
| - | 14637441 | 1413 days ago | 0.22 ETH | ||||
| - | 14637440 | 1413 days ago | 0.16665 ETH | ||||
| - | 14637439 | 1413 days ago | 0.165 ETH | ||||
| - | 14637438 | 1413 days ago | 0.1919 ETH | ||||
| - | 14637437 | 1413 days ago | 0.19 ETH | ||||
| - | 14637436 | 1413 days ago | 0.3535 ETH | ||||
| - | 14637430 | 1413 days ago | 0.35 ETH | ||||
| - | 14637397 | 1413 days ago | 0.255025 ETH | ||||
| - | 14637373 | 1413 days ago | 0.2525 ETH | ||||
| - | 14637371 | 1413 days ago | 0.2828 ETH | ||||
| - | 14637368 | 1413 days ago | 0.28 ETH | ||||
| - | 14637330 | 1413 days ago | 0.2525 ETH | ||||
| - | 14637327 | 1413 days ago | 0.25 ETH | ||||
| - | 14637320 | 1413 days ago | 0.2626 ETH | ||||
| - | 14637291 | 1413 days ago | 0.26 ETH | ||||
| - | 14637262 | 1413 days ago | 1.313 ETH | ||||
| - | 14637255 | 1413 days ago | 1.3 ETH | ||||
| - | 14637159 | 1413 days ago | 0.214221 ETH | ||||
| - | 14637153 | 1413 days ago | 0.2121 ETH | ||||
| - | 14636687 | 1413 days ago | 1.2 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
NFTAuction
Compiler Version
v0.8.13+commit.abaa5c0e
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
// moved from https://github.com/museum-of-war/auction
pragma solidity 0.8.13;
import "IERC721.sol";
import "IERC721Receiver.sol";
import "IERC20.sol";
import "Ownable.sol";
import "IWithBalance.sol";
/// @title An Auction Contract for bidding and selling single and batched NFTs
/// @author Avo Labs GmbH
/// @notice This contract can be used for auctioning any NFTs, and accepts any ERC20 token as payment
contract NFTAuction is Ownable {
address[] public whitelistedPassCollections; //Only owners of tokens from any of these collections can make bids
mapping(address => mapping(uint256 => Auction)) public nftContractAuctions;
mapping(address => uint256) failedTransferCredits;
//Each Auction is unique to each NFT (contract + id pairing).
struct Auction {
//map token ID to
uint32 bidIncreasePercentage;
uint32 auctionBidPeriod; //Increments the length of time the auction is open in which a new bid can be made after each bid.
uint64 auctionEnd;
uint128 minPrice;
uint128 buyNowPrice;
uint128 nftHighestBid;
address nftHighestBidder;
address nftSeller;
address whitelistedBuyer; //The seller can specify a whitelisted address for a sale (this is effectively a direct sale).
address nftRecipient; //The bidder can specify a recipient for the NFT if their bid is successful.
address ERC20Token; // The seller can specify an ERC20 token that can be used to bid or purchase the NFT.
address[] feeRecipients;
uint32[] feePercentages;
}
/*
* Default values that are used if not specified by the NFT seller.
*/
uint32 public defaultBidIncreasePercentage;
uint32 public minimumSettableIncreasePercentage;
uint32 public maximumMinPricePercentage;
uint32 public defaultAuctionBidPeriod;
/*╔═════════════════════════════╗
║ EVENTS ║
╚═════════════════════════════╝*/
event NftAuctionCreated(
address nftContractAddress,
uint256 tokenId,
address nftSeller,
address erc20Token,
uint128 minPrice,
uint128 buyNowPrice,
uint32 auctionBidPeriod,
uint32 bidIncreasePercentage,
address[] feeRecipients,
uint32[] feePercentages
);
event SaleCreated(
address nftContractAddress,
uint256 tokenId,
address nftSeller,
address erc20Token,
uint128 buyNowPrice,
address whitelistedBuyer,
address[] feeRecipients,
uint32[] feePercentages
);
event BidMade(
address nftContractAddress,
uint256 tokenId,
address bidder,
uint256 ethAmount,
address erc20Token,
uint256 tokenAmount
);
event AuctionPeriodUpdated(
address nftContractAddress,
uint256 tokenId,
uint64 auctionEndPeriod
);
event NFTTransferredAndSellerPaid(
address nftContractAddress,
uint256 tokenId,
address nftSeller,
uint128 nftHighestBid,
address nftHighestBidder,
address nftRecipient
);
event AuctionSettled(
address nftContractAddress,
uint256 tokenId,
address auctionSettler
);
event AuctionWithdrawn(
address nftContractAddress,
uint256 tokenId,
address nftOwner
);
event BidWithdrawn(
address nftContractAddress,
uint256 tokenId,
address highestBidder
);
event WhitelistedBuyerUpdated(
address nftContractAddress,
uint256 tokenId,
address newWhitelistedBuyer
);
event MinimumPriceUpdated(
address nftContractAddress,
uint256 tokenId,
uint256 newMinPrice
);
event BuyNowPriceUpdated(
address nftContractAddress,
uint256 tokenId,
uint128 newBuyNowPrice
);
event HighestBidTaken(address nftContractAddress, uint256 tokenId);
/**********************************/
/*╔═════════════════════════════╗
║ END ║
║ EVENTS ║
╚═════════════════════════════╝*/
/**********************************/
/*╔═════════════════════════════╗
║ MODIFIERS ║
╚═════════════════════════════╝*/
modifier hasWhitelistedToken() {
{ //Block scoping to prevent "Stack too deep"
bool isWhitelisted;
for (uint256 i = 0; i < whitelistedPassCollections.length; i++) {
if(IWithBalance(whitelistedPassCollections[i]).balanceOf(msg.sender) > 0) {
isWhitelisted = true;
break;
}
}
require(isWhitelisted, "Sender has no whitelisted NFTs");
}
_;
}
modifier isAuctionNotStartedByOwner(
address _nftContractAddress,
uint256 _tokenId
) {
require(
nftContractAuctions[_nftContractAddress][_tokenId].nftSeller !=
msg.sender,
"Auction already started by owner"
);
if (
nftContractAuctions[_nftContractAddress][_tokenId].nftSeller !=
address(0)
) {
require(
msg.sender == IERC721(_nftContractAddress).ownerOf(_tokenId),
"Sender doesn't own NFT"
);
_resetAuction(_nftContractAddress, _tokenId);
}
_;
}
modifier auctionOngoing(address _nftContractAddress, uint256 _tokenId) {
require(
_isAuctionOngoing(_nftContractAddress, _tokenId),
"Auction has ended"
);
_;
}
modifier priceGreaterThanZero(uint256 _price) {
require(_price > 0, "Price cannot be 0");
_;
}
/*
* The minimum price must be 80% of the buyNowPrice(if set).
*/
modifier minPriceDoesNotExceedLimit(
uint128 _buyNowPrice,
uint128 _minPrice
) {
require(
_buyNowPrice == 0 ||
_getPortionOfBid(_buyNowPrice, maximumMinPricePercentage) >=
_minPrice,
"MinPrice > 80% of buyNowPrice"
);
_;
}
modifier notNftSeller(address _nftContractAddress, uint256 _tokenId) {
require(
msg.sender !=
nftContractAuctions[_nftContractAddress][_tokenId].nftSeller,
"Owner cannot bid on own NFT"
);
_;
}
modifier onlyNftSeller(address _nftContractAddress, uint256 _tokenId) {
require(
msg.sender ==
nftContractAuctions[_nftContractAddress][_tokenId].nftSeller,
"Only nft seller"
);
_;
}
/*
* The bid amount was either equal the buyNowPrice or it must be higher than the previous
* bid by the specified bid increase percentage.
*/
modifier bidAmountMeetsBidRequirements(
address _nftContractAddress,
uint256 _tokenId,
uint128 _tokenAmount
) {
require(
_doesBidMeetBidRequirements(
_nftContractAddress,
_tokenId,
_tokenAmount
),
"Not enough funds to bid on NFT"
);
_;
}
// check if the highest bidder can purchase this NFT.
modifier onlyApplicableBuyer(
address _nftContractAddress,
uint256 _tokenId
) {
require(
!_isWhitelistedSale(_nftContractAddress, _tokenId) ||
nftContractAuctions[_nftContractAddress][_tokenId]
.whitelistedBuyer ==
msg.sender,
"Only the whitelisted buyer"
);
_;
}
modifier minimumBidNotMade(address _nftContractAddress, uint256 _tokenId) {
require(
!_isMinimumBidMade(_nftContractAddress, _tokenId),
"The auction has a valid bid made"
);
_;
}
/*
* Payment is accepted if the payment is made in the ERC20 token or ETH specified by the seller.
* Early bids on NFTs not yet up for auction must be made in ETH.
*/
modifier paymentAccepted(
address _nftContractAddress,
uint256 _tokenId,
address _erc20Token,
uint128 _tokenAmount
) {
require(
_isPaymentAccepted(
_nftContractAddress,
_tokenId,
_erc20Token,
_tokenAmount
),
"Bid to be in specified ERC20/Eth"
);
_;
}
modifier isAuctionOver(address _nftContractAddress, uint256 _tokenId) {
require(
!_isAuctionOngoing(_nftContractAddress, _tokenId),
"Auction is not yet over"
);
_;
}
modifier notZeroAddress(address _address) {
require(_address != address(0), "Cannot specify 0 address");
_;
}
modifier increasePercentageAboveMinimum(uint32 _bidIncreasePercentage) {
require(
_bidIncreasePercentage >= minimumSettableIncreasePercentage,
"Bid increase percentage too low"
);
_;
}
modifier isFeePercentagesLessThanMaximum(uint32[] memory _feePercentages) {
uint32 totalPercent;
for (uint256 i = 0; i < _feePercentages.length; i++) {
totalPercent = totalPercent + _feePercentages[i];
}
require(totalPercent <= 10000, "Fee percentages exceed maximum");
_;
}
modifier correctFeeRecipientsAndPercentages(
uint256 _recipientsLength,
uint256 _percentagesLength
) {
require(
_recipientsLength == _percentagesLength,
"Recipients != percentages"
);
_;
}
modifier isNotASale(address _nftContractAddress, uint256 _tokenId) {
require(
!_isASale(_nftContractAddress, _tokenId),
"Not applicable for a sale"
);
_;
}
/**********************************/
/*╔═════════════════════════════╗
║ END ║
║ MODIFIERS ║
╚═════════════════════════════╝*/
/**********************************/
// constructor
constructor(address[] memory _whitelistedPassCollectionsAddresses) {
defaultBidIncreasePercentage = 100;
defaultAuctionBidPeriod = 86400; //1 day
minimumSettableIncreasePercentage = 100;
maximumMinPricePercentage = 8000;
uint256 collectionsCount = _whitelistedPassCollectionsAddresses.length;
for (uint256 i = 0; i < collectionsCount; i++) {
whitelistedPassCollections.push(_whitelistedPassCollectionsAddresses[i]);
}
}
/**********************************/
/*╔══════════════════════════════╗
║ WHITELIST FUNCTIONS ║
╚══════════════════════════════╝*/
/*
* Add whitelisted pass collection.
*/
function addWhitelistedCollection(address _collectionContractAddress)
external
onlyOwner
{
whitelistedPassCollections.push(_collectionContractAddress);
}
/*
* Remove whitelisted pass collection by index.
*/
function removeWhitelistedCollection(uint256 index)
external
onlyOwner
{
whitelistedPassCollections[index] = whitelistedPassCollections[whitelistedPassCollections.length - 1];
whitelistedPassCollections.pop();
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ WHITELIST FUNCTIONS ║
╚══════════════════════════════╝*/
/**********************************/
/*╔══════════════════════════════╗
║ AUCTION CHECK FUNCTIONS ║
╚══════════════════════════════╝*/
function _isAuctionOngoing(address _nftContractAddress, uint256 _tokenId)
internal
view
returns (bool)
{
uint64 auctionEndTimestamp = nftContractAuctions[_nftContractAddress][
_tokenId
].auctionEnd;
//if the auctionEnd is set to 0, the auction is technically on-going, however
//the minimum bid price (minPrice) has not yet been met.
return (auctionEndTimestamp == 0 ||
block.timestamp < auctionEndTimestamp);
}
/*
* Check if a bid has been made. This is applicable in the early bid scenario
* to ensure that if an auction is created after an early bid, the auction
* begins appropriately or is settled if the buy now price is met.
*/
function _isABidMade(address _nftContractAddress, uint256 _tokenId)
internal
view
returns (bool)
{
return (nftContractAuctions[_nftContractAddress][_tokenId]
.nftHighestBid > 0);
}
/*
*if the minPrice is set by the seller, check that the highest bid meets or exceeds that price.
*/
function _isMinimumBidMade(address _nftContractAddress, uint256 _tokenId)
internal
view
returns (bool)
{
uint128 minPrice = nftContractAuctions[_nftContractAddress][_tokenId]
.minPrice;
return
minPrice > 0 &&
(nftContractAuctions[_nftContractAddress][_tokenId].nftHighestBid >=
minPrice);
}
/*
* If the buy now price is set by the seller, check that the highest bid meets that price.
*/
function _isBuyNowPriceMet(address _nftContractAddress, uint256 _tokenId)
internal
view
returns (bool)
{
uint128 buyNowPrice = nftContractAuctions[_nftContractAddress][_tokenId]
.buyNowPrice;
return
buyNowPrice > 0 &&
nftContractAuctions[_nftContractAddress][_tokenId].nftHighestBid >=
buyNowPrice;
}
/*
* Check that a bid is applicable for the purchase of the NFT.
* In the case of a sale: the bid needs to meet the buyNowPrice.
* In the case of an auction: the bid needs to be a % higher than the previous bid.
*/
function _doesBidMeetBidRequirements(
address _nftContractAddress,
uint256 _tokenId,
uint128 _tokenAmount
) internal view returns (bool) {
uint128 buyNowPrice = nftContractAuctions[_nftContractAddress][_tokenId]
.buyNowPrice;
//if buyNowPrice is met, ignore increase percentage
if (
buyNowPrice > 0 &&
(msg.value >= buyNowPrice || _tokenAmount >= buyNowPrice)
) {
return true;
}
//if the NFT is up for auction, the bid needs to be a % higher than the previous bid
uint256 bidIncreaseAmount = (nftContractAuctions[_nftContractAddress][
_tokenId
].nftHighestBid *
(10000 +
_getBidIncreasePercentage(_nftContractAddress, _tokenId))) /
10000;
return (msg.value >= bidIncreaseAmount ||
_tokenAmount >= bidIncreaseAmount);
}
/*
* An NFT is up for sale if the buyNowPrice is set, but the minPrice is not set.
* Therefore the only way to conclude the NFT sale is to meet the buyNowPrice.
*/
function _isASale(address _nftContractAddress, uint256 _tokenId)
internal
view
returns (bool)
{
return (nftContractAuctions[_nftContractAddress][_tokenId].buyNowPrice >
0 &&
nftContractAuctions[_nftContractAddress][_tokenId].minPrice == 0);
}
function _isWhitelistedSale(address _nftContractAddress, uint256 _tokenId)
internal
view
returns (bool)
{
return (nftContractAuctions[_nftContractAddress][_tokenId]
.whitelistedBuyer != address(0));
}
/*
* The highest bidder is allowed to purchase the NFT if
* no whitelisted buyer is set by the NFT seller.
* Otherwise, the highest bidder must equal the whitelisted buyer.
*/
function _isHighestBidderAllowedToPurchaseNFT(
address _nftContractAddress,
uint256 _tokenId
) internal view returns (bool) {
return
(!_isWhitelistedSale(_nftContractAddress, _tokenId)) ||
_isHighestBidderWhitelisted(_nftContractAddress, _tokenId);
}
function _isHighestBidderWhitelisted(
address _nftContractAddress,
uint256 _tokenId
) internal view returns (bool) {
return (nftContractAuctions[_nftContractAddress][_tokenId]
.nftHighestBidder ==
nftContractAuctions[_nftContractAddress][_tokenId]
.whitelistedBuyer);
}
/**
* Payment is accepted in the following scenarios:
* (1) Auction already created - can accept ETH or Specified Token
* --------> Cannot bid with ETH & an ERC20 Token together in any circumstance<------
* (2) Auction not created - only ETH accepted (cannot early bid with an ERC20 Token
* (3) Cannot make a zero bid (no ETH or Token amount)
*/
function _isPaymentAccepted(
address _nftContractAddress,
uint256 _tokenId,
address _bidERC20Token,
uint128 _tokenAmount
) internal view returns (bool) {
address auctionERC20Token = nftContractAuctions[_nftContractAddress][
_tokenId
].ERC20Token;
if (_isERC20Auction(auctionERC20Token)) {
return
msg.value == 0 &&
auctionERC20Token == _bidERC20Token &&
_tokenAmount > 0;
} else {
return
msg.value != 0 &&
_bidERC20Token == address(0) &&
_tokenAmount == 0;
}
}
function _isERC20Auction(address _auctionERC20Token)
internal
pure
returns (bool)
{
return _auctionERC20Token != address(0);
}
/*
* Returns the percentage of the total bid (used to calculate fee payments)
*/
function _getPortionOfBid(uint256 _totalBid, uint256 _percentage)
internal
pure
returns (uint256)
{
return (_totalBid * (_percentage)) / 10000;
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ AUCTION CHECK FUNCTIONS ║
╚══════════════════════════════╝*/
/**********************************/
/*╔══════════════════════════════╗
║ DEFAULT GETTER FUNCTIONS ║
╚══════════════════════════════╝*/
/*****************************************************************
* These functions check if the applicable auction parameter has *
* been set by the NFT seller. If not, return the default value. *
*****************************************************************/
function _getBidIncreasePercentage(
address _nftContractAddress,
uint256 _tokenId
) internal view returns (uint32) {
uint32 bidIncreasePercentage = nftContractAuctions[_nftContractAddress][
_tokenId
].bidIncreasePercentage;
if (bidIncreasePercentage == 0) {
return defaultBidIncreasePercentage;
} else {
return bidIncreasePercentage;
}
}
function _getAuctionBidPeriod(address _nftContractAddress, uint256 _tokenId)
internal
view
returns (uint32)
{
uint32 auctionBidPeriod = nftContractAuctions[_nftContractAddress][
_tokenId
].auctionBidPeriod;
if (auctionBidPeriod == 0) {
return defaultAuctionBidPeriod;
} else {
return auctionBidPeriod;
}
}
/*
* The default value for the NFT recipient is the highest bidder
*/
function _getNftRecipient(address _nftContractAddress, uint256 _tokenId)
internal
view
returns (address)
{
address nftRecipient = nftContractAuctions[_nftContractAddress][
_tokenId
].nftRecipient;
if (nftRecipient == address(0)) {
return
nftContractAuctions[_nftContractAddress][_tokenId]
.nftHighestBidder;
} else {
return nftRecipient;
}
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ DEFAULT GETTER FUNCTIONS ║
╚══════════════════════════════╝*/
/**********************************/
/*╔══════════════════════════════╗
║ TRANSFER NFTS TO CONTRACT ║
╚══════════════════════════════╝*/
function _transferNftToAuctionContract(
address _nftContractAddress,
uint256 _tokenId
) internal {
address _nftSeller = nftContractAuctions[_nftContractAddress][_tokenId]
.nftSeller;
if (IERC721(_nftContractAddress).ownerOf(_tokenId) == _nftSeller) {
IERC721(_nftContractAddress).transferFrom(
_nftSeller,
address(this),
_tokenId
);
require(
IERC721(_nftContractAddress).ownerOf(_tokenId) == address(this),
"nft transfer failed"
);
} else {
require(
IERC721(_nftContractAddress).ownerOf(_tokenId) == address(this),
"Seller doesn't own NFT"
);
}
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ TRANSFER NFTS TO CONTRACT ║
╚══════════════════════════════╝*/
/**********************************/
/*╔══════════════════════════════╗
║ AUCTION CREATION ║
╚══════════════════════════════╝*/
/**
* Setup parameters applicable to all auctions and whitelised sales:
* -> ERC20 Token for payment (if specified by the seller) : _erc20Token
* -> minimum price : _minPrice
* -> buy now price : _buyNowPrice
* -> the nft seller: msg.sender
* -> The fee recipients & their respective percentages for a sucessful auction/sale
*/
function _setupAuction(
address _nftContractAddress,
uint256 _tokenId,
address _erc20Token,
uint128 _minPrice,
uint128 _buyNowPrice,
address[] memory _feeRecipients,
uint32[] memory _feePercentages
)
internal
minPriceDoesNotExceedLimit(_buyNowPrice, _minPrice)
correctFeeRecipientsAndPercentages(
_feeRecipients.length,
_feePercentages.length
)
isFeePercentagesLessThanMaximum(_feePercentages)
{
if (_erc20Token != address(0)) {
nftContractAuctions[_nftContractAddress][_tokenId]
.ERC20Token = _erc20Token;
}
nftContractAuctions[_nftContractAddress][_tokenId]
.feeRecipients = _feeRecipients;
nftContractAuctions[_nftContractAddress][_tokenId]
.feePercentages = _feePercentages;
nftContractAuctions[_nftContractAddress][_tokenId]
.buyNowPrice = _buyNowPrice;
nftContractAuctions[_nftContractAddress][_tokenId].minPrice = _minPrice;
nftContractAuctions[_nftContractAddress][_tokenId].nftSeller = msg
.sender;
}
function _createNewNftAuction(
address _nftContractAddress,
uint256 _tokenId,
address _erc20Token,
uint128 _minPrice,
uint128 _buyNowPrice,
address[] memory _feeRecipients,
uint32[] memory _feePercentages
) internal {
// Sending the NFT to this contract
_setupAuction(
_nftContractAddress,
_tokenId,
_erc20Token,
_minPrice,
_buyNowPrice,
_feeRecipients,
_feePercentages
);
emit NftAuctionCreated(
_nftContractAddress,
_tokenId,
msg.sender,
_erc20Token,
_minPrice,
_buyNowPrice,
_getAuctionBidPeriod(_nftContractAddress, _tokenId),
_getBidIncreasePercentage(_nftContractAddress, _tokenId),
_feeRecipients,
_feePercentages
);
_updateOngoingAuction(_nftContractAddress, _tokenId);
}
/**
* Create an auction that uses the default bid increase percentage
* & the default auction bid period.
*/
function createDefaultNftAuction(
address _nftContractAddress,
uint256 _tokenId,
address _erc20Token,
uint128 _minPrice,
uint128 _buyNowPrice,
address[] memory _feeRecipients,
uint32[] memory _feePercentages
)
external
isAuctionNotStartedByOwner(_nftContractAddress, _tokenId)
priceGreaterThanZero(_minPrice)
{
_createNewNftAuction(
_nftContractAddress,
_tokenId,
_erc20Token,
_minPrice,
_buyNowPrice,
_feeRecipients,
_feePercentages
);
}
function createNewNftAuction(
address _nftContractAddress,
uint256 _tokenId,
address _erc20Token,
uint128 _minPrice,
uint128 _buyNowPrice,
uint32 _auctionBidPeriod, //this is the time that the auction lasts until another bid occurs
uint32 _bidIncreasePercentage,
address[] memory _feeRecipients,
uint32[] memory _feePercentages
)
external
isAuctionNotStartedByOwner(_nftContractAddress, _tokenId)
priceGreaterThanZero(_minPrice)
increasePercentageAboveMinimum(_bidIncreasePercentage)
{
nftContractAuctions[_nftContractAddress][_tokenId]
.auctionBidPeriod = _auctionBidPeriod;
nftContractAuctions[_nftContractAddress][_tokenId]
.bidIncreasePercentage = _bidIncreasePercentage;
_createNewNftAuction(
_nftContractAddress,
_tokenId,
_erc20Token,
_minPrice,
_buyNowPrice,
_feeRecipients,
_feePercentages
);
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ AUCTION CREATION ║
╚══════════════════════════════╝*/
/**********************************/
/*╔══════════════════════════════╗
║ SALES ║
╚══════════════════════════════╝*/
/********************************************************************
* Allows for a standard sale mechanism where the NFT seller can *
* can select an address to be whitelisted. This address is then *
* allowed to make a bid on the NFT. No other address can bid on *
* the NFT. *
********************************************************************/
function _setupSale(
address _nftContractAddress,
uint256 _tokenId,
address _erc20Token,
uint128 _buyNowPrice,
address _whitelistedBuyer,
address[] memory _feeRecipients,
uint32[] memory _feePercentages
)
internal
correctFeeRecipientsAndPercentages(
_feeRecipients.length,
_feePercentages.length
)
isFeePercentagesLessThanMaximum(_feePercentages)
{
if (_erc20Token != address(0)) {
nftContractAuctions[_nftContractAddress][_tokenId]
.ERC20Token = _erc20Token;
}
nftContractAuctions[_nftContractAddress][_tokenId]
.feeRecipients = _feeRecipients;
nftContractAuctions[_nftContractAddress][_tokenId]
.feePercentages = _feePercentages;
nftContractAuctions[_nftContractAddress][_tokenId]
.buyNowPrice = _buyNowPrice;
nftContractAuctions[_nftContractAddress][_tokenId]
.whitelistedBuyer = _whitelistedBuyer;
nftContractAuctions[_nftContractAddress][_tokenId].nftSeller = msg
.sender;
}
function createSale(
address _nftContractAddress,
uint256 _tokenId,
address _erc20Token,
uint128 _buyNowPrice,
address _whitelistedBuyer,
address[] memory _feeRecipients,
uint32[] memory _feePercentages
)
external
isAuctionNotStartedByOwner(_nftContractAddress, _tokenId)
priceGreaterThanZero(_buyNowPrice)
{
//min price = 0
_setupSale(
_nftContractAddress,
_tokenId,
_erc20Token,
_buyNowPrice,
_whitelistedBuyer,
_feeRecipients,
_feePercentages
);
emit SaleCreated(
_nftContractAddress,
_tokenId,
msg.sender,
_erc20Token,
_buyNowPrice,
_whitelistedBuyer,
_feeRecipients,
_feePercentages
);
//check if buyNowPrice is meet and conclude sale, otherwise reverse the early bid
if (_isABidMade(_nftContractAddress, _tokenId)) {
if (
//we only revert the underbid if the seller specifies a different
//whitelisted buyer to the highest bidder
_isHighestBidderAllowedToPurchaseNFT(
_nftContractAddress,
_tokenId
)
) {
if (_isBuyNowPriceMet(_nftContractAddress, _tokenId)) {
_transferNftToAuctionContract(
_nftContractAddress,
_tokenId
);
_transferNftAndPaySeller(_nftContractAddress, _tokenId);
}
} else {
_reverseAndResetPreviousBid(_nftContractAddress, _tokenId);
}
}
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ SALES ║
╚══════════════════════════════╝*/
/**********************************/
/*╔═════════════════════════════╗
║ BID FUNCTIONS ║
╚═════════════════════════════╝*/
/********************************************************************
* Make bids with ETH or an ERC20 Token specified by the NFT seller.*
* Additionally, a buyer can pay the asking price to conclude a sale*
* of an NFT. *
********************************************************************/
function _makeBid(
address _nftContractAddress,
uint256 _tokenId,
address _erc20Token,
uint128 _tokenAmount
)
internal
hasWhitelistedToken
notNftSeller(_nftContractAddress, _tokenId)
paymentAccepted(
_nftContractAddress,
_tokenId,
_erc20Token,
_tokenAmount
)
bidAmountMeetsBidRequirements(
_nftContractAddress,
_tokenId,
_tokenAmount
)
{
_reversePreviousBidAndUpdateHighestBid(
_nftContractAddress,
_tokenId,
_tokenAmount
);
emit BidMade(
_nftContractAddress,
_tokenId,
msg.sender,
msg.value,
_erc20Token,
_tokenAmount
);
_updateOngoingAuction(_nftContractAddress, _tokenId);
}
function makeBid(
address _nftContractAddress,
uint256 _tokenId,
address _erc20Token,
uint128 _tokenAmount
)
external
payable
auctionOngoing(_nftContractAddress, _tokenId)
onlyApplicableBuyer(_nftContractAddress, _tokenId)
{
_makeBid(_nftContractAddress, _tokenId, _erc20Token, _tokenAmount);
}
function makeCustomBid(
address _nftContractAddress,
uint256 _tokenId,
address _erc20Token,
uint128 _tokenAmount,
address _nftRecipient
)
external
payable
auctionOngoing(_nftContractAddress, _tokenId)
notZeroAddress(_nftRecipient)
onlyApplicableBuyer(_nftContractAddress, _tokenId)
{
nftContractAuctions[_nftContractAddress][_tokenId]
.nftRecipient = _nftRecipient;
_makeBid(_nftContractAddress, _tokenId, _erc20Token, _tokenAmount);
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ BID FUNCTIONS ║
╚══════════════════════════════╝*/
/**********************************/
/*╔══════════════════════════════╗
║ UPDATE AUCTION ║
╚══════════════════════════════╝*/
/***************************************************************
* Settle an auction or sale if the buyNowPrice is met or set *
* auction period to begin if the minimum price has been met. *
***************************************************************/
function _updateOngoingAuction(
address _nftContractAddress,
uint256 _tokenId
) internal {
if (_isBuyNowPriceMet(_nftContractAddress, _tokenId)) {
_transferNftToAuctionContract(_nftContractAddress, _tokenId);
_transferNftAndPaySeller(_nftContractAddress, _tokenId);
return;
}
//min price not set, nft not up for auction yet
if (_isMinimumBidMade(_nftContractAddress, _tokenId)) {
_transferNftToAuctionContract(_nftContractAddress, _tokenId);
_updateAuctionEnd(_nftContractAddress, _tokenId);
}
}
function _updateAuctionEnd(address _nftContractAddress, uint256 _tokenId)
internal
{
//the auction end is always set to now + the bid period
nftContractAuctions[_nftContractAddress][_tokenId].auctionEnd =
_getAuctionBidPeriod(_nftContractAddress, _tokenId) +
uint64(block.timestamp);
emit AuctionPeriodUpdated(
_nftContractAddress,
_tokenId,
nftContractAuctions[_nftContractAddress][_tokenId].auctionEnd
);
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ UPDATE AUCTION ║
╚══════════════════════════════╝*/
/**********************************/
/*╔══════════════════════════════╗
║ RESET FUNCTIONS ║
╚══════════════════════════════╝*/
/*
* Reset all auction related parameters for an NFT.
* This effectively removes an EFT as an item up for auction
*/
function _resetAuction(address _nftContractAddress, uint256 _tokenId)
internal
{
nftContractAuctions[_nftContractAddress][_tokenId].minPrice = 0;
nftContractAuctions[_nftContractAddress][_tokenId].buyNowPrice = 0;
nftContractAuctions[_nftContractAddress][_tokenId].auctionEnd = 0;
nftContractAuctions[_nftContractAddress][_tokenId].auctionBidPeriod = 0;
nftContractAuctions[_nftContractAddress][_tokenId]
.bidIncreasePercentage = 0;
nftContractAuctions[_nftContractAddress][_tokenId].nftSeller = address(
0
);
nftContractAuctions[_nftContractAddress][_tokenId]
.whitelistedBuyer = address(0);
nftContractAuctions[_nftContractAddress][_tokenId].ERC20Token = address(
0
);
}
/*
* Reset all bid related parameters for an NFT.
* This effectively sets an NFT as having no active bids
*/
function _resetBids(address _nftContractAddress, uint256 _tokenId)
internal
{
nftContractAuctions[_nftContractAddress][_tokenId]
.nftHighestBidder = address(0);
nftContractAuctions[_nftContractAddress][_tokenId].nftHighestBid = 0;
nftContractAuctions[_nftContractAddress][_tokenId]
.nftRecipient = address(0);
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ RESET FUNCTIONS ║
╚══════════════════════════════╝*/
/**********************************/
/*╔══════════════════════════════╗
║ UPDATE BIDS ║
╚══════════════════════════════╝*/
/******************************************************************
* Internal functions that update bid parameters and reverse bids *
* to ensure contract only holds the highest bid. *
******************************************************************/
function _updateHighestBid(
address _nftContractAddress,
uint256 _tokenId,
uint128 _tokenAmount
) internal {
address auctionERC20Token = nftContractAuctions[_nftContractAddress][
_tokenId
].ERC20Token;
if (_isERC20Auction(auctionERC20Token)) {
IERC20(auctionERC20Token).transferFrom(
msg.sender,
address(this),
_tokenAmount
);
nftContractAuctions[_nftContractAddress][_tokenId]
.nftHighestBid = _tokenAmount;
} else {
nftContractAuctions[_nftContractAddress][_tokenId]
.nftHighestBid = uint128(msg.value);
}
nftContractAuctions[_nftContractAddress][_tokenId]
.nftHighestBidder = msg.sender;
}
function _reverseAndResetPreviousBid(
address _nftContractAddress,
uint256 _tokenId
) internal {
address nftHighestBidder = nftContractAuctions[_nftContractAddress][
_tokenId
].nftHighestBidder;
uint128 nftHighestBid = nftContractAuctions[_nftContractAddress][
_tokenId
].nftHighestBid;
_resetBids(_nftContractAddress, _tokenId);
_payout(_nftContractAddress, _tokenId, nftHighestBidder, nftHighestBid);
}
function _reversePreviousBidAndUpdateHighestBid(
address _nftContractAddress,
uint256 _tokenId,
uint128 _tokenAmount
) internal {
address prevNftHighestBidder = nftContractAuctions[_nftContractAddress][
_tokenId
].nftHighestBidder;
uint256 prevNftHighestBid = nftContractAuctions[_nftContractAddress][
_tokenId
].nftHighestBid;
_updateHighestBid(_nftContractAddress, _tokenId, _tokenAmount);
if (prevNftHighestBidder != address(0)) {
_payout(
_nftContractAddress,
_tokenId,
prevNftHighestBidder,
prevNftHighestBid
);
}
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ UPDATE BIDS ║
╚══════════════════════════════╝*/
/**********************************/
/*╔══════════════════════════════╗
║ TRANSFER NFT & PAY SELLER ║
╚══════════════════════════════╝*/
function _transferNftAndPaySeller(
address _nftContractAddress,
uint256 _tokenId
) internal {
address _nftSeller = nftContractAuctions[_nftContractAddress][_tokenId]
.nftSeller;
address _nftHighestBidder = nftContractAuctions[_nftContractAddress][
_tokenId
].nftHighestBidder;
address _nftRecipient = _getNftRecipient(_nftContractAddress, _tokenId);
uint128 _nftHighestBid = nftContractAuctions[_nftContractAddress][
_tokenId
].nftHighestBid;
_resetBids(_nftContractAddress, _tokenId);
_payFeesAndSeller(
_nftContractAddress,
_tokenId,
_nftSeller,
_nftHighestBid
);
IERC721(_nftContractAddress).transferFrom(
address(this),
_nftRecipient,
_tokenId
);
_resetAuction(_nftContractAddress, _tokenId);
emit NFTTransferredAndSellerPaid(
_nftContractAddress,
_tokenId,
_nftSeller,
_nftHighestBid,
_nftHighestBidder,
_nftRecipient
);
}
function _payFeesAndSeller(
address _nftContractAddress,
uint256 _tokenId,
address _nftSeller,
uint256 _highestBid
) internal {
uint256 feesPaid;
for (
uint256 i = 0;
i <
nftContractAuctions[_nftContractAddress][_tokenId]
.feeRecipients
.length;
i++
) {
uint256 fee = _getPortionOfBid(
_highestBid,
nftContractAuctions[_nftContractAddress][_tokenId]
.feePercentages[i]
);
feesPaid = feesPaid + fee;
_payout(
_nftContractAddress,
_tokenId,
nftContractAuctions[_nftContractAddress][_tokenId]
.feeRecipients[i],
fee
);
}
_payout(
_nftContractAddress,
_tokenId,
_nftSeller,
(_highestBid - feesPaid)
);
}
function _payout(
address _nftContractAddress,
uint256 _tokenId,
address _recipient,
uint256 _amount
) internal {
address auctionERC20Token = nftContractAuctions[_nftContractAddress][
_tokenId
].ERC20Token;
if (_isERC20Auction(auctionERC20Token)) {
IERC20(auctionERC20Token).transfer(_recipient, _amount);
} else {
// attempt to send the funds to the recipient
(bool success, ) = payable(_recipient).call{
value: _amount,
gas: 20000
}("");
// if it failed, update their credit balance so they can pull it later
if (!success) {
failedTransferCredits[_recipient] =
failedTransferCredits[_recipient] +
_amount;
}
}
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ TRANSFER NFT & PAY SELLER ║
╚══════════════════════════════╝*/
/**********************************/
/*╔══════════════════════════════╗
║ SETTLE & WITHDRAW ║
╚══════════════════════════════╝*/
function settleAuction(address _nftContractAddress, uint256 _tokenId)
external
isAuctionOver(_nftContractAddress, _tokenId)
{
_transferNftAndPaySeller(_nftContractAddress, _tokenId);
emit AuctionSettled(_nftContractAddress, _tokenId, msg.sender);
}
function withdrawAuction(address _nftContractAddress, uint256 _tokenId)
external
{
//only the NFT owner can prematurely close and auction
require(
IERC721(_nftContractAddress).ownerOf(_tokenId) == msg.sender,
"Not NFT owner"
);
_resetAuction(_nftContractAddress, _tokenId);
emit AuctionWithdrawn(_nftContractAddress, _tokenId, msg.sender);
}
function withdrawBid(address _nftContractAddress, uint256 _tokenId)
external
minimumBidNotMade(_nftContractAddress, _tokenId)
{
address nftHighestBidder = nftContractAuctions[_nftContractAddress][
_tokenId
].nftHighestBidder;
require(msg.sender == nftHighestBidder, "Cannot withdraw funds");
uint128 nftHighestBid = nftContractAuctions[_nftContractAddress][
_tokenId
].nftHighestBid;
_resetBids(_nftContractAddress, _tokenId);
_payout(_nftContractAddress, _tokenId, nftHighestBidder, nftHighestBid);
emit BidWithdrawn(_nftContractAddress, _tokenId, msg.sender);
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ SETTLE & WITHDRAW ║
╚══════════════════════════════╝*/
/**********************************/
/*╔══════════════════════════════╗
║ UPDATE AUCTION ║
╚══════════════════════════════╝*/
function updateWhitelistedBuyer(
address _nftContractAddress,
uint256 _tokenId,
address _newWhitelistedBuyer
) external onlyNftSeller(_nftContractAddress, _tokenId) {
require(_isASale(_nftContractAddress, _tokenId), "Not a sale");
nftContractAuctions[_nftContractAddress][_tokenId]
.whitelistedBuyer = _newWhitelistedBuyer;
//if an underbid is by a non whitelisted buyer,reverse that bid
address nftHighestBidder = nftContractAuctions[_nftContractAddress][
_tokenId
].nftHighestBidder;
uint128 nftHighestBid = nftContractAuctions[_nftContractAddress][
_tokenId
].nftHighestBid;
if (nftHighestBid > 0 && !(nftHighestBidder == _newWhitelistedBuyer)) {
//we only revert the underbid if the seller specifies a different
//whitelisted buyer to the highest bider
_resetBids(_nftContractAddress, _tokenId);
_payout(
_nftContractAddress,
_tokenId,
nftHighestBidder,
nftHighestBid
);
}
emit WhitelistedBuyerUpdated(
_nftContractAddress,
_tokenId,
_newWhitelistedBuyer
);
}
function updateMinimumPrice(
address _nftContractAddress,
uint256 _tokenId,
uint128 _newMinPrice
)
external
onlyNftSeller(_nftContractAddress, _tokenId)
minimumBidNotMade(_nftContractAddress, _tokenId)
isNotASale(_nftContractAddress, _tokenId)
priceGreaterThanZero(_newMinPrice)
minPriceDoesNotExceedLimit(
nftContractAuctions[_nftContractAddress][_tokenId].buyNowPrice,
_newMinPrice
)
{
nftContractAuctions[_nftContractAddress][_tokenId]
.minPrice = _newMinPrice;
emit MinimumPriceUpdated(_nftContractAddress, _tokenId, _newMinPrice);
if (_isMinimumBidMade(_nftContractAddress, _tokenId)) {
_transferNftToAuctionContract(_nftContractAddress, _tokenId);
_updateAuctionEnd(_nftContractAddress, _tokenId);
}
}
function updateBuyNowPrice(
address _nftContractAddress,
uint256 _tokenId,
uint128 _newBuyNowPrice
)
external
onlyNftSeller(_nftContractAddress, _tokenId)
priceGreaterThanZero(_newBuyNowPrice)
minPriceDoesNotExceedLimit(
_newBuyNowPrice,
nftContractAuctions[_nftContractAddress][_tokenId].minPrice
)
{
nftContractAuctions[_nftContractAddress][_tokenId]
.buyNowPrice = _newBuyNowPrice;
emit BuyNowPriceUpdated(_nftContractAddress, _tokenId, _newBuyNowPrice);
if (_isBuyNowPriceMet(_nftContractAddress, _tokenId)) {
_transferNftToAuctionContract(_nftContractAddress, _tokenId);
_transferNftAndPaySeller(_nftContractAddress, _tokenId);
}
}
/*
* The NFT seller can opt to end an auction by taking the current highest bid.
*/
function takeHighestBid(address _nftContractAddress, uint256 _tokenId)
external
onlyNftSeller(_nftContractAddress, _tokenId)
{
require(
_isABidMade(_nftContractAddress, _tokenId),
"cannot payout 0 bid"
);
_transferNftToAuctionContract(_nftContractAddress, _tokenId);
_transferNftAndPaySeller(_nftContractAddress, _tokenId);
emit HighestBidTaken(_nftContractAddress, _tokenId);
}
/*
* Query the owner of an NFT deposited for auction
*/
function ownerOfNFT(address _nftContractAddress, uint256 _tokenId)
external
view
returns (address)
{
address nftSeller = nftContractAuctions[_nftContractAddress][_tokenId]
.nftSeller;
require(nftSeller != address(0), "NFT not deposited");
return nftSeller;
}
/*
* If the transfer of a bid has failed, allow the recipient to reclaim their amount later.
*/
function withdrawAllFailedCredits() external {
uint256 amount = failedTransferCredits[msg.sender];
require(amount != 0, "no credits to withdraw");
failedTransferCredits[msg.sender] = 0;
(bool successfulWithdraw, ) = msg.sender.call{
value: amount,
gas: 20000
}("");
require(successfulWithdraw, "withdraw failed");
}
/**********************************/
/*╔══════════════════════════════╗
║ END ║
║ UPDATE AUCTION ║
╚══════════════════════════════╝*/
/**********************************/
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "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`, 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 be 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 Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @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 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);
/**
* @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;
}// SPDX-License-Identifier: MIT
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: MIT
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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 `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool);
/**
* @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);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IWithBalance {
function balanceOf(address owner) external view returns (uint256);
}{
"evmVersion": "istanbul",
"optimizer": {
"enabled": true,
"runs": 200
},
"libraries": {
"NFTAuction.sol": {}
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address[]","name":"_whitelistedPassCollectionsAddresses","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"auctionEndPeriod","type":"uint64"}],"name":"AuctionPeriodUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"auctionSettler","type":"address"}],"name":"AuctionSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"nftOwner","type":"address"}],"name":"AuctionWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"bidder","type":"address"},{"indexed":false,"internalType":"uint256","name":"ethAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"erc20Token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"BidMade","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"highestBidder","type":"address"}],"name":"BidWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"newBuyNowPrice","type":"uint128"}],"name":"BuyNowPriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"HighestBidTaken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinPrice","type":"uint256"}],"name":"MinimumPriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"nftSeller","type":"address"},{"indexed":false,"internalType":"uint128","name":"nftHighestBid","type":"uint128"},{"indexed":false,"internalType":"address","name":"nftHighestBidder","type":"address"},{"indexed":false,"internalType":"address","name":"nftRecipient","type":"address"}],"name":"NFTTransferredAndSellerPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"nftSeller","type":"address"},{"indexed":false,"internalType":"address","name":"erc20Token","type":"address"},{"indexed":false,"internalType":"uint128","name":"minPrice","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"buyNowPrice","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"auctionBidPeriod","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"bidIncreasePercentage","type":"uint32"},{"indexed":false,"internalType":"address[]","name":"feeRecipients","type":"address[]"},{"indexed":false,"internalType":"uint32[]","name":"feePercentages","type":"uint32[]"}],"name":"NftAuctionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"nftSeller","type":"address"},{"indexed":false,"internalType":"address","name":"erc20Token","type":"address"},{"indexed":false,"internalType":"uint128","name":"buyNowPrice","type":"uint128"},{"indexed":false,"internalType":"address","name":"whitelistedBuyer","type":"address"},{"indexed":false,"internalType":"address[]","name":"feeRecipients","type":"address[]"},{"indexed":false,"internalType":"uint32[]","name":"feePercentages","type":"uint32[]"}],"name":"SaleCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nftContractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"newWhitelistedBuyer","type":"address"}],"name":"WhitelistedBuyerUpdated","type":"event"},{"inputs":[{"internalType":"address","name":"_collectionContractAddress","type":"address"}],"name":"addWhitelistedCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_erc20Token","type":"address"},{"internalType":"uint128","name":"_minPrice","type":"uint128"},{"internalType":"uint128","name":"_buyNowPrice","type":"uint128"},{"internalType":"address[]","name":"_feeRecipients","type":"address[]"},{"internalType":"uint32[]","name":"_feePercentages","type":"uint32[]"}],"name":"createDefaultNftAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_erc20Token","type":"address"},{"internalType":"uint128","name":"_minPrice","type":"uint128"},{"internalType":"uint128","name":"_buyNowPrice","type":"uint128"},{"internalType":"uint32","name":"_auctionBidPeriod","type":"uint32"},{"internalType":"uint32","name":"_bidIncreasePercentage","type":"uint32"},{"internalType":"address[]","name":"_feeRecipients","type":"address[]"},{"internalType":"uint32[]","name":"_feePercentages","type":"uint32[]"}],"name":"createNewNftAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_erc20Token","type":"address"},{"internalType":"uint128","name":"_buyNowPrice","type":"uint128"},{"internalType":"address","name":"_whitelistedBuyer","type":"address"},{"internalType":"address[]","name":"_feeRecipients","type":"address[]"},{"internalType":"uint32[]","name":"_feePercentages","type":"uint32[]"}],"name":"createSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultAuctionBidPeriod","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultBidIncreasePercentage","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_erc20Token","type":"address"},{"internalType":"uint128","name":"_tokenAmount","type":"uint128"}],"name":"makeBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_erc20Token","type":"address"},{"internalType":"uint128","name":"_tokenAmount","type":"uint128"},{"internalType":"address","name":"_nftRecipient","type":"address"}],"name":"makeCustomBid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"maximumMinPricePercentage","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumSettableIncreasePercentage","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"nftContractAuctions","outputs":[{"internalType":"uint32","name":"bidIncreasePercentage","type":"uint32"},{"internalType":"uint32","name":"auctionBidPeriod","type":"uint32"},{"internalType":"uint64","name":"auctionEnd","type":"uint64"},{"internalType":"uint128","name":"minPrice","type":"uint128"},{"internalType":"uint128","name":"buyNowPrice","type":"uint128"},{"internalType":"uint128","name":"nftHighestBid","type":"uint128"},{"internalType":"address","name":"nftHighestBidder","type":"address"},{"internalType":"address","name":"nftSeller","type":"address"},{"internalType":"address","name":"whitelistedBuyer","type":"address"},{"internalType":"address","name":"nftRecipient","type":"address"},{"internalType":"address","name":"ERC20Token","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOfNFT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"removeWhitelistedCollection","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"settleAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"takeHighestBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint128","name":"_newBuyNowPrice","type":"uint128"}],"name":"updateBuyNowPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint128","name":"_newMinPrice","type":"uint128"}],"name":"updateMinimumPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_newWhitelistedBuyer","type":"address"}],"name":"updateWhitelistedBuyer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"whitelistedPassCollections","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawAllFailedCredits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"withdrawAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftContractAddress","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"withdrawBid","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b506040516200408e3803806200408e833981016040819052620000349162000147565b600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600480546001600160801b0319166e01518000001f400000006400000064179055805160005b818110156200010b576001838281518110620000bb57620000bb62000219565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b039092169190911790558062000102816200022f565b9150506200009b565b50505062000257565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200014257600080fd5b919050565b600060208083850312156200015b57600080fd5b82516001600160401b03808211156200017357600080fd5b818501915085601f8301126200018857600080fd5b8151818111156200019d576200019d62000114565b8060051b604051601f19603f83011681018181108582111715620001c557620001c562000114565b604052918252848201925083810185019188831115620001e457600080fd5b938501935b828510156200020d57620001fd856200012a565b84529385019392850192620001e9565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200025057634e487b7160e01b600052601160045260246000fd5b5060010190565b613e2780620002676000396000f3fe6080604052600436106101665760003560e01c80639041e273116100d1578063d18e629c1161008a578063f2fde38b11610064578063f2fde38b1461052f578063f45671f11461054f578063f583bac71461056f578063f7f829a41461058f57600080fd5b8063d18e629c146104cf578063db227338146104ef578063ebea60251461050f57600080fd5b80639041e2731461042657806399157d70146104465780639c0b996614610466578063b6ad691414610483578063c24d5a5c14610498578063cd4eda1c146104ab57600080fd5b80634cb8ef5b116101235780634cb8ef5b146103805780635138b08c146103a0578063565c5172146103c0578063715018a6146103d3578063848e5c77146103e85780638da5cb5b1461040857600080fd5b8063041fa0b81461016b578063076b73ac146102a8578063186779d5146102ca57806320950fc6146103035780632f9c95761461033b5780633d87d5fb1461035b575b600080fd5b34801561017757600080fd5b5061021f610186366004613471565b60026020818152600093845260408085209091529183529120805460018201549282015460038301546004840154600585015460069095015463ffffffff8086169764010000000087049091169667ffffffffffffffff600160401b880416966001600160801b03600160801b91829004811697848216979290940416946001600160a01b03938416949184169390811692811691168b565b6040805163ffffffff9c8d1681529b909a1660208c015267ffffffffffffffff909816988a01989098526001600160801b0395861660608a015293851660808901529390911660a08701526001600160a01b0390811660c087015291821660e0860152811661010085015291821661012084015216610140820152610160015b60405180910390f35b3480156102b457600080fd5b506102c86102c336600461349d565b6105af565b005b3480156102d657600080fd5b506004546102ee90600160601b900463ffffffff1681565b60405163ffffffff909116815260200161029f565b34801561030f57600080fd5b5061032361031e366004613471565b610727565b6040516001600160a01b03909116815260200161029f565b34801561034757600080fd5b506102c86103563660046134fb565b61079c565b34801561036757600080fd5b506004546102ee90640100000000900463ffffffff1681565b34801561038c57600080fd5b506102c861039b366004613471565b610a10565b3480156103ac57600080fd5b506102c86103bb366004613471565b610b71565b6102c86103ce366004613539565b610c15565b3480156103df57600080fd5b506102c8610d97565b3480156103f457600080fd5b506102c8610403366004613471565b610e0b565b34801561041457600080fd5b506000546001600160a01b0316610323565b34801561043257600080fd5b506102c86104413660046136f4565b610ef5565b34801561045257600080fd5b506103236104613660046137a8565b61104b565b34801561047257600080fd5b506004546102ee9063ffffffff1681565b34801561048f57600080fd5b506102c8611075565b6102c86104a63660046137c1565b611170565b3480156104b757600080fd5b506004546102ee90600160401b900463ffffffff1681565b3480156104db57600080fd5b506102c86104ea366004613812565b61125d565b3480156104fb57600080fd5b506102c861050a3660046137a8565b6112d8565b34801561051b57600080fd5b506102c861052a366004613471565b6113b1565b34801561053b57600080fd5b506102c861054a366004613812565b6114ab565b34801561055b57600080fd5b506102c861056a36600461382f565b611595565b34801561057b57600080fd5b506102c861058a36600461388a565b611780565b34801561059b57600080fd5b506102c86105aa3660046134fb565b6119fb565b6001600160a01b038381166000908152600260209081526040808320868452909152902060030154849184911633146106035760405162461bcd60e51b81526004016105fa90613960565b60405180910390fd5b61060d8585611b9b565b6106465760405162461bcd60e51b815260206004820152600a6024820152694e6f7420612073616c6560b01b60448201526064016105fa565b6001600160a01b0385811660009081526002602081815260408084208985529091529091206004810180546001600160a01b03191687851617905590810154600190910154911690600160801b90046001600160801b031680158015906106bf5750846001600160a01b0316826001600160a01b031614155b156106e3576106ce8787611c0e565b6106e3878784846001600160801b0316611c67565b7f7502912f483c1fb3f89bf8664bea10db517c2093040d379e78e169e06752364687878760405161071693929190613989565b60405180910390a150505050505050565b6001600160a01b038083166000908152600260209081526040808320858452909152812060030154909116806107935760405162461bcd60e51b8152602060048201526011602482015270139195081b9bdd0819195c1bdcda5d1959607a1b60448201526064016105fa565b90505b92915050565b6001600160a01b038381166000908152600260209081526040808320868452909152902060030154849184911633146107e75760405162461bcd60e51b81526004016105fa90613960565b84846107f38282611db6565b156108405760405162461bcd60e51b815260206004820181905260248201527f5468652061756374696f6e2068617320612076616c696420626964206d61646560448201526064016105fa565b868661084c8282611b9b565b156108995760405162461bcd60e51b815260206004820152601960248201527f4e6f74206170706c696361626c6520666f7220612073616c650000000000000060448201526064016105fa565b866001600160801b0316600081116108c35760405162461bcd60e51b81526004016105fa906139ac565b6001600160a01b038a1660009081526002602090815260408083208c84529091529020600101546001600160801b03168881158061092757506004546001600160801b038281169161092491851690600160401b900463ffffffff16611e3a565b10155b6109435760405162461bcd60e51b81526004016105fa906139d7565b6001600160a01b038c1660009081526002602090815260408083208e84529091529081902080546001600160801b03808e16600160801b029116179055517fdcf27af4c564afa0c536dd1fa48e5fef0d9833378a1bddacc95922b902ebfc32906109d7908e908e908e906001600160a01b0393909316835260208301919091526001600160801b0316604082015260600190565b60405180910390a16109e98c8c611db6565b15610a02576109f88c8c611e53565b610a028c8c6120cc565b505050505050505050505050565b8181610a1c8282611db6565b15610a695760405162461bcd60e51b815260206004820181905260248201527f5468652061756374696f6e2068617320612076616c696420626964206d61646560448201526064016105fa565b6001600160a01b038085166000908152600260208181526040808420888552909152909120015416338114610ad85760405162461bcd60e51b815260206004820152601560248201527443616e6e6f742077697468647261772066756e647360581b60448201526064016105fa565b6001600160a01b0385166000908152600260209081526040808320878452909152902060010154600160801b90046001600160801b0316610b198686611c0e565b610b2e868684846001600160801b0316611c67565b7f10d9bddf66f639dd3c5a6ad2db5ae3102c2b468dfb90a4b0da219435f24a970d868633604051610b6193929190613989565b60405180910390a1505050505050565b8181610b7d828261217b565b15610bca5760405162461bcd60e51b815260206004820152601760248201527f41756374696f6e206973206e6f7420796574206f76657200000000000000000060448201526064016105fa565b610bd484846121cb565b7fe6b94748c5d6e0d188a0fcb9b7f2973b01fc0095627f1ec5accdcd9d2e65ca36848433604051610c0793929190613989565b60405180910390a150505050565b8484610c21828261217b565b610c615760405162461bcd60e51b8152602060048201526011602482015270105d58dd1a5bdb881a185cc8195b991959607a1b60448201526064016105fa565b826001600160a01b038116610cb85760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f74207370656369667920302061646472657373000000000000000060448201526064016105fa565b8787610cc4828261233d565b1580610cf757506001600160a01b0382811660009081526002602090815260408083208584529091529020600401541633145b610d435760405162461bcd60e51b815260206004820152601a60248201527f4f6e6c79207468652077686974656c697374656420627579657200000000000060448201526064016105fa565b6001600160a01b038a811660009081526002602090815260408083208d8452909152902060050180546001600160a01b031916918816919091179055610d8b8a8a8a8a61236a565b50505050505050505050565b6000546001600160a01b03163314610dc15760405162461bcd60e51b81526004016105fa90613a0e565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6001600160a01b03828116600090815260026020908152604080832085845290915290206003015483918391163314610e565760405162461bcd60e51b81526004016105fa90613960565b610e608484612638565b610ea25760405162461bcd60e51b815260206004820152601360248201527218d85b9b9bdd081c185e5bdd5d080c08189a59606a1b60448201526064016105fa565b610eac8484611e53565b610eb684846121cb565b604080516001600160a01b0386168152602081018590527f711f4eae05533b90c24ff0ae762d6e9e1ef1b2c85d4c484a2913c5201bcbb7c99101610c07565b6001600160a01b0380881660009081526002602090815260408083208a84529091529020600301548891889133911603610f415760405162461bcd60e51b81526004016105fa90613a43565b6001600160a01b0382811660009081526002602090815260408083208584529091529020600301541615611012576040516331a9108f60e11b8152600481018290526001600160a01b03831690636352211e90602401602060405180830381865afa158015610fb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd89190613a78565b6001600160a01b0316336001600160a01b0316146110085760405162461bcd60e51b81526004016105fa90613a95565b6110128282612675565b856001600160801b03166000811161103c5760405162461bcd60e51b81526004016105fa906139ac565b610d8b8a8a8a8a8a8a8a6126dd565b6001818154811061105b57600080fd5b6000918252602090912001546001600160a01b0316905081565b33600090815260036020526040812054908190036110ce5760405162461bcd60e51b81526020600482015260166024820152756e6f206372656469747320746f20776974686472617760501b60448201526064016105fa565b3360008181526003602052604080822082905551909190614e2090849084818181858888f193505050503d8060008114611124576040519150601f19603f3d011682016040523d82523d6000602084013e611129565b606091505b505090508061116c5760405162461bcd60e51b815260206004820152600f60248201526e1dda5d1a191c985dc819985a5b1959608a1b60448201526064016105fa565b5050565b838361117c828261217b565b6111bc5760405162461bcd60e51b8152602060048201526011602482015270105d58dd1a5bdb881a185cc8195b991959607a1b60448201526064016105fa565b85856111c8828261233d565b15806111fb57506001600160a01b0382811660009081526002602090815260408083208584529091529020600401541633145b6112475760405162461bcd60e51b815260206004820152601a60248201527f4f6e6c79207468652077686974656c697374656420627579657200000000000060448201526064016105fa565b6112538888888861236a565b5050505050505050565b6000546001600160a01b031633146112875760405162461bcd60e51b81526004016105fa90613a0e565b6001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146113025760405162461bcd60e51b81526004016105fa90613a0e565b60018054611311908290613adb565b8154811061132157611321613af2565b600091825260209091200154600180546001600160a01b03909216918390811061134d5761134d613af2565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600180548061138c5761138c613b08565b600082815260209020810160001990810180546001600160a01b031916905501905550565b6040516331a9108f60e11b81526004810182905233906001600160a01b03841690636352211e90602401602060405180830381865afa1580156113f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141c9190613a78565b6001600160a01b0316146114625760405162461bcd60e51b815260206004820152600d60248201526c2737ba1027232a1037bbb732b960991b60448201526064016105fa565b61146c8282612675565b7fec19f84af4aad6523d37faa19e243c77717842cca9bf492dc5379830cac958d082823360405161149f93929190613989565b60405180910390a15050565b6000546001600160a01b031633146114d55760405162461bcd60e51b81526004016105fa90613a0e565b6001600160a01b03811661153a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105fa565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380881660009081526002602090815260408083208a845290915290206003015488918891339116036115e15760405162461bcd60e51b81526004016105fa90613a43565b6001600160a01b03828116600090815260026020908152604080832085845290915290206003015416156116b2576040516331a9108f60e11b8152600481018290526001600160a01b03831690636352211e90602401602060405180830381865afa158015611654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116789190613a78565b6001600160a01b0316336001600160a01b0316146116a85760405162461bcd60e51b81526004016105fa90613a95565b6116b28282612675565b856001600160801b0316600081116116dc5760405162461bcd60e51b81526004016105fa906139ac565b6116eb8a8a8a8a8a8a8a61275a565b7fb4cb1faa7b4f2b837334e4a12fb94a1cfc320c32b70dd31e113d1795b9d0f0568a8a338b8b8b8b8b604051611728989796959493929190613b98565b60405180910390a161173a8a8a612638565b15610d8b576117498a8a612980565b15611776576117588a8a6129ca565b15611771576117678a8a611e53565b6117718a8a6121cb565b610d8b565b610d8b8a8a612a4a565b6001600160a01b03808a1660009081526002602090815260408083208c84529091529020600301548a918a91339116036117cc5760405162461bcd60e51b81526004016105fa90613a43565b6001600160a01b038281166000908152600260209081526040808320858452909152902060030154161561189d576040516331a9108f60e11b8152600481018290526001600160a01b03831690636352211e90602401602060405180830381865afa15801561183f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118639190613a78565b6001600160a01b0316336001600160a01b0316146118935760405162461bcd60e51b81526004016105fa90613a95565b61189d8282612675565b876001600160801b0316600081116118c75760405162461bcd60e51b81526004016105fa906139ac565b600454869063ffffffff6401000000009091048116908216101561192d5760405162461bcd60e51b815260206004820152601f60248201527f42696420696e6372656173652070657263656e7461676520746f6f206c6f770060448201526064016105fa565b87600260008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e815260200190815260200160002060000160046101000a81548163ffffffff021916908363ffffffff16021790555086600260008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e815260200190815260200160002060000160006101000a81548163ffffffff021916908363ffffffff1602179055506119ec8d8d8d8d8d8b8b6126dd565b50505050505050505050505050565b6001600160a01b03838116600090815260026020908152604080832086845290915290206003015484918491163314611a465760405162461bcd60e51b81526004016105fa90613960565b826001600160801b031660008111611a705760405162461bcd60e51b81526004016105fa906139ac565b6001600160a01b038616600090815260026020908152604080832088845290915290205484906001600160801b03600160801b90910481169082161580611add57506004546001600160801b0382811691611ada91851690600160401b900463ffffffff16611e3a565b10155b611af95760405162461bcd60e51b81526004016105fa906139d7565b6001600160a01b03881660008181526002602090815260408083208b845282529182902060010180546001600160801b0319166001600160801b038b1690811790915582519384529083018a9052908201527fcc66420416a999e685e3938d2c6252ed709db214d0435f13da0b1e5339bcac769060600160405180910390a1611b8288886129ca565b1561125357611b918888611e53565b61125388886121cb565b6001600160a01b03821660009081526002602090815260408083208484529091528120600101546001600160801b0316158015906107935750506001600160a01b039190911660009081526002602090815260408083209383529290522054600160801b90046001600160801b03161590565b6001600160a01b0391909116600090815260026020818152604080842094845293905291902090810180546001600160a01b03199081169091556001820180546001600160801b03169055600590910180549091169055565b6001600160a01b038481166000908152600260209081526040808320878452909152902060060154168015611d0f5760405163a9059cbb60e01b81526001600160a01b0384811660048301526024820184905282169063a9059cbb906044016020604051808303816000875af1158015611ce5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d099190613c0e565b50611daf565b6000836001600160a01b031683614e2090604051600060405180830381858888f193505050503d8060008114611d61576040519150601f19603f3d011682016040523d82523d6000602084013e611d66565b606091505b5050905080611dad576001600160a01b038416600090815260036020526040902054611d93908490613c30565b6001600160a01b0385166000908152600360205260409020555b505b5050505050565b6001600160a01b0382166000908152600260209081526040808320848452909152812054600160801b90046001600160801b03168015801590611e3257506001600160a01b03841660009081526002602090815260408083208684529091529020600101546001600160801b03808316600160801b9092041610155b949350505050565b6000612710611e498385613c48565b6107939190613c7d565b6001600160a01b038281166000818152600260209081526040808320868452909152908190206003015490516331a9108f60e11b815260048101859052921691829190636352211e90602401602060405180830381865afa158015611ebc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee09190613a78565b6001600160a01b031603612012576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018490528416906323b872dd90606401600060405180830381600087803b158015611f3e57600080fd5b505af1158015611f52573d6000803e3d6000fd5b50506040516331a9108f60e11b8152600481018590523092506001600160a01b0386169150636352211e90602401602060405180830381865afa158015611f9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc19190613a78565b6001600160a01b03161461200d5760405162461bcd60e51b81526020600482015260136024820152721b999d081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016105fa565b505050565b6040516331a9108f60e11b81526004810183905230906001600160a01b03851690636352211e90602401602060405180830381865afa158015612059573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207d9190613a78565b6001600160a01b03161461200d5760405162461bcd60e51b815260206004820152601660248201527514d95b1b195c88191bd95cdb89dd081bdddb8813919560521b60448201526064016105fa565b426120d78383612ab1565b63ffffffff166120e79190613c91565b6001600160a01b038316600081815260026020908152604080832086845282529182902080546fffffffffffffffff00000000000000001916600160401b67ffffffffffffffff96871681029190911791829055835194855291840186905204909216918101919091527fc1ce6cc1337b95ed3c849e00bffc0d93e89e5e80cc5d198db838140827ac75949060600161149f565b6001600160a01b0382166000908152600260209081526040808320848452909152812054600160401b900467ffffffffffffffff16801580611e32575067ffffffffffffffff1642109392505050565b6001600160a01b038281166000908152600260208181526040808420868552909152822060038101549101549083169216906122078585612b08565b6001600160a01b0386166000908152600260209081526040808320888452909152902060010154909150600160801b90046001600160801b031661224b8686611c0e565b612260868686846001600160801b0316612b67565b6040516323b872dd60e01b81523060048201526001600160a01b038381166024830152604482018790528716906323b872dd90606401600060405180830381600087803b1580156122b057600080fd5b505af11580156122c4573d6000803e3d6000fd5b505050506122d28686612675565b604080516001600160a01b03808916825260208201889052808716928201929092526001600160801b0383166060820152818516608082015290831660a08201527f8df77c988c9550e96e43a66277f716818a74ed2188cdacb49d790623e6f225719060c001610b61565b6001600160a01b039182166000908152600260209081526040808320938352929052206004015416151590565b6000805b6001548110156124235760006001828154811061238d5761238d613af2565b6000918252602090912001546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156123de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124029190613cbd565b11156124115760019150612423565b8061241b81613cd6565b91505061236e565b50806124715760405162461bcd60e51b815260206004820152601e60248201527f53656e64657220686173206e6f2077686974656c6973746564204e465473000060448201526064016105fa565b506001600160a01b038085166000908152600260209081526040808320878452909152902060030154859185911633036124ed5760405162461bcd60e51b815260206004820152601b60248201527f4f776e65722063616e6e6f7420626964206f6e206f776e204e4654000000000060448201526064016105fa565b858585856124fd84848484612c93565b6125495760405162461bcd60e51b815260206004820181905260248201527f42696420746f20626520696e207370656369666965642045524332302f45746860448201526064016105fa565b898988612557838383612d30565b6125a35760405162461bcd60e51b815260206004820152601e60248201527f4e6f7420656e6f7567682066756e647320746f20626964206f6e204e4654000060448201526064016105fa565b6125ae8d8d8c612e3e565b7fdfd4ac8cb43d5458b7a6f74f2d6461d77d4985704bdbc2fd4c4816444bbfd5e08d8d33348f8f604051612626969594939291906001600160a01b03968716815260208101959095529285166040850152606084019190915290921660808201526001600160801b039190911660a082015260c00190565b60405180910390a16119ec8d8d612ea6565b6001600160a01b039190911660009081526002602090815260408083209383529290522060010154600160801b90046001600160801b0316151590565b6001600160a01b039190911660009081526002602090815260408083209383529290529081206001810180546001600160801b03191690559081556003810180546001600160a01b031990811690915560048201805482169055600690910180549091169055565b6126ec87878787878787612eec565b7f3379e969de5522101a0f0912ffe00daf15361dbcbf9cd5c328e0dd97aa25cdf987873388888861271d8e8e612ab1565b6127278f8f61318d565b8a8a60405161273f9a99989796959493929190613cef565b60405180910390a16127518787612ea6565b50505050505050565b815181518082146127a95760405162461bcd60e51b8152602060048201526019602482015278526563697069656e747320213d2070657263656e746167657360381b60448201526064016105fa565b826000805b82518110156127f0578281815181106127c9576127c9613af2565b6020026020010151826127dc9190613d7d565b9150806127e881613cd6565b9150506127ae565b506127108163ffffffff1611156128495760405162461bcd60e51b815260206004820152601e60248201527f4665652070657263656e746167657320657863656564206d6178696d756d000060448201526064016105fa565b6001600160a01b03891615612895576001600160a01b038b811660009081526002602090815260408083208e8452909152902060060180546001600160a01b031916918b169190911790555b6001600160a01b038b1660009081526002602090815260408083208d8452825290912087516128cc92600790920191890190613339565b506001600160a01b038b1660009081526002602090815260408083208d8452825290912086516129049260089092019188019061339e565b505050506001600160a01b039788166000908152600260209081526040808320998352989052969096206001810180546001600160801b03969096166001600160801b0319909616959095179094555050600482018054919095166001600160a01b031991821617909455600301805490931633179092555050565b600061298c838361233d565b158061079357506001600160a01b03808416600090815260026020818152604080842087855290915290912060048101549101548216911614610793565b6001600160a01b03821660009081526002602090815260408083208484529091528120600101546001600160801b03168015801590611e3257506001600160a01b03841660009081526002602090815260408083208684529091529020600101546001600160801b03808316600160801b90920416101591505092915050565b6001600160a01b03828116600090815260026020818152604080842086855290915290912090810154600190910154911690600160801b90046001600160801b0316612a968484611c0e565b612aab848484846001600160801b0316611c67565b50505050565b6001600160a01b0382166000908152600260209081526040808320848452909152812054640100000000900463ffffffff16808203612b01575050600454600160601b900463ffffffff16610796565b9050610796565b6001600160a01b03808316600090815260026020908152604080832085845290915281206005015490911680612b015750506001600160a01b038083166000908152600260208181526040808420868552909152909120015416610796565b6000805b6001600160a01b0386166000908152600260209081526040808320888452909152902060070154811015612c7d576001600160a01b038616600090815260026020908152604080832088845290915281206008018054612c0091869185908110612bd757612bd7613af2565b6000918252602090912060088204015460079091166004026101000a900463ffffffff16611e3a565b9050612c0c8184613c30565b6001600160a01b03881660009081526002602090815260408083208a845290915290206007018054919450612c6a918991899186908110612c4f57612c4f613af2565b6000918252602090912001546001600160a01b031684611c67565b5080612c7581613cd6565b915050612b6b565b50611daf858585612c8e8587613adb565b611c67565b6001600160a01b0384811660009081526002602090815260408083208784529091528120600601549091168015612d005734158015612ce35750836001600160a01b0316816001600160a01b0316145b8015612cf857506000836001600160801b0316115b915050611e32565b3415801590612d1657506001600160a01b038416155b8015612cf8575050506001600160801b0316159392505050565b6001600160a01b03831660009081526002602090815260408083208584529091528120600101546001600160801b03168015801590612d945750806001600160801b031634101580612d945750806001600160801b0316836001600160801b031610155b15612da3576001915050612e37565b6000612710612db2878761318d565b612dbe90612710613d7d565b6001600160a01b03881660009081526002602090815260408083208a8452909152902060010154612e059163ffffffff1690600160801b90046001600160801b0316613d9c565b612e0f9190613dcb565b6001600160801b031690508034101580612e32575080846001600160801b031610155b925050505b9392505050565b6001600160a01b03838116600090815260026020818152604080842087855290915290912090810154600190910154911690600160801b90046001600160801b0316612e8b8585856131ce565b6001600160a01b03821615611daf57611daf85858484611c67565b612eb082826129ca565b15612ec957612ebf8282611e53565b61116c82826121cb565b612ed38282611db6565b1561116c57612ee28282611e53565b61116c82826120cc565b82846001600160801b0382161580612f2a57506004546001600160801b0382811691612f2791851690600160401b900463ffffffff16611e3a565b10155b612f465760405162461bcd60e51b81526004016105fa906139d7565b83518351808214612f955760405162461bcd60e51b8152602060048201526019602482015278526563697069656e747320213d2070657263656e746167657360381b60448201526064016105fa565b846000805b8251811015612fdc57828181518110612fb557612fb5613af2565b602002602001015182612fc89190613d7d565b915080612fd481613cd6565b915050612f9a565b506127108163ffffffff1611156130355760405162461bcd60e51b815260206004820152601e60248201527f4665652070657263656e746167657320657863656564206d6178696d756d000060448201526064016105fa565b6001600160a01b038b16156130a3578a600260008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e815260200190815260200160002060060160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b6001600160a01b038d1660009081526002602090815260408083208f8452825290912089516130da926007909201918b0190613339565b506001600160a01b038d1660009081526002602090815260408083208f845282529091208851613112926008909201918a019061339e565b505050506001600160a01b039990991660009081526002602090815260408083209a8352999052979097206001810180546001600160801b039687166001600160801b03199091161790558054958516600160801b0295909416949094178355505060030180546001600160a01b0319163317905550505050565b6001600160a01b038216600090815260026020908152604080832084845290915281205463ffffffff16808203612b0157505060045463ffffffff16610796565b6001600160a01b0383811660009081526002602090815260408083208684529091529020600601541680156132c0576040516323b872dd60e01b81523360048201523060248201526001600160801b03831660448201526001600160a01b038216906323b872dd906064016020604051808303816000875af1158015613258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327c9190613c0e565b506001600160a01b0384166000908152600260209081526040808320868452909152902060010180546001600160801b03808516600160801b0291161790556132ff565b6001600160a01b0384166000908152600260209081526040808320868452909152902060010180546001600160801b03348116600160801b0291161790555b50506001600160a01b0390911660009081526002602081815260408084209484529390529190200180546001600160a01b03191633179055565b82805482825590600052602060002090810192821561338e579160200282015b8281111561338e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613359565b5061339a929150613444565b5090565b8280548282559060005260206000209060070160089004810192821561338e5791602002820160005b8382111561340b57835183826101000a81548163ffffffff021916908363ffffffff16021790555092602001926004016020816003010492830192600103026133c7565b801561343b5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261340b565b505061339a9291505b5b8082111561339a5760008155600101613445565b6001600160a01b038116811461346e57600080fd5b50565b6000806040838503121561348457600080fd5b823561348f81613459565b946020939093013593505050565b6000806000606084860312156134b257600080fd5b83356134bd81613459565b92506020840135915060408401356134d481613459565b809150509250925092565b80356001600160801b03811681146134f657600080fd5b919050565b60008060006060848603121561351057600080fd5b833561351b81613459565b925060208401359150613530604085016134df565b90509250925092565b600080600080600060a0868803121561355157600080fd5b853561355c81613459565b945060208601359350604086013561357381613459565b9250613581606087016134df565b9150608086013561359181613459565b809150509295509295909350565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156135de576135de61359f565b604052919050565b600067ffffffffffffffff8211156136005761360061359f565b5060051b60200190565b600082601f83011261361b57600080fd5b8135602061363061362b836135e6565b6135b5565b82815260059290921b8401810191818101908684111561364f57600080fd5b8286015b8481101561367357803561366681613459565b8352918301918301613653565b509695505050505050565b803563ffffffff811681146134f657600080fd5b600082601f8301126136a357600080fd5b813560206136b361362b836135e6565b82815260059290921b840181019181810190868411156136d257600080fd5b8286015b84811015613673576136e78161367e565b83529183019183016136d6565b600080600080600080600060e0888a03121561370f57600080fd5b873561371a81613459565b965060208801359550604088013561373181613459565b945061373f606089016134df565b935061374d608089016134df565b925060a088013567ffffffffffffffff8082111561376a57600080fd5b6137768b838c0161360a565b935060c08a013591508082111561378c57600080fd5b506137998a828b01613692565b91505092959891949750929550565b6000602082840312156137ba57600080fd5b5035919050565b600080600080608085870312156137d757600080fd5b84356137e281613459565b93506020850135925060408501356137f981613459565b9150613807606086016134df565b905092959194509250565b60006020828403121561382457600080fd5b813561079381613459565b600080600080600080600060e0888a03121561384a57600080fd5b873561385581613459565b965060208801359550604088013561386c81613459565b945061387a606089016134df565b9350608088013561374d81613459565b60008060008060008060008060006101208a8c0312156138a957600080fd5b89356138b481613459565b985060208a0135975060408a01356138cb81613459565b96506138d960608b016134df565b95506138e760808b016134df565b94506138f560a08b0161367e565b935061390360c08b0161367e565b925060e08a013567ffffffffffffffff8082111561392057600080fd5b61392c8d838e0161360a565b93506101008c013591508082111561394357600080fd5b506139508c828d01613692565b9150509295985092959850929598565b6020808252600f908201526e27b7363c9037333a1039b2b63632b960891b604082015260600190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b602080825260119082015270050726963652063616e6e6f74206265203607c1b604082015260600190565b6020808252601d908201527f4d696e5072696365203e20383025206f66206275794e6f775072696365000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252818101527f41756374696f6e20616c72656164792073746172746564206279206f776e6572604082015260600190565b600060208284031215613a8a57600080fd5b815161079381613459565b60208082526016908201527514d95b99195c88191bd95cdb89dd081bdddb8813919560521b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b600082821015613aed57613aed613ac5565b500390565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b600081518084526020808501945080840160005b83811015613b575781516001600160a01b031687529582019590820190600101613b32565b509495945050505050565b600081518084526020808501945080840160005b83811015613b5757815163ffffffff1687529582019590820190600101613b76565b6001600160a01b03898116825260208201899052878116604083015286811660608301526001600160801b0386166080830152841660a082015261010060c08201819052600090613beb83820186613b1e565b905082810360e0840152613bff8185613b62565b9b9a5050505050505050505050565b600060208284031215613c2057600080fd5b8151801515811461079357600080fd5b60008219821115613c4357613c43613ac5565b500190565b6000816000190483118215151615613c6257613c62613ac5565b500290565b634e487b7160e01b600052601260045260246000fd5b600082613c8c57613c8c613c67565b500490565b600067ffffffffffffffff808316818516808303821115613cb457613cb4613ac5565b01949350505050565b600060208284031215613ccf57600080fd5b5051919050565b600060018201613ce857613ce8613ac5565b5060010190565b6001600160a01b038b81168252602082018b90528981166040830152881660608201526001600160801b038781166080830152861660a082015263ffffffff85811660c0830152841660e08201526101406101008201819052600090613d5783820186613b1e565b9050828103610120840152613d6c8185613b62565b9d9c50505050505050505050505050565b600063ffffffff808316818516808303821115613cb457613cb4613ac5565b60006001600160801b0380831681851681830481118215151615613dc257613dc2613ac5565b02949350505050565b60006001600160801b0380841680613de557613de5613c67565b9216919091049291505056fea26469706673582212206a536cf573a2864b43e335f913d2731550811ae78d2ef81b8f5eadbaeb12395764736f6c634300080d003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000d3228e099e6596988ae0b73eaa62591c875e56930000000000000000000000005dc23613fd54a87c3b8a7134534110f5180433c8000000000000000000000000932aeac0eebaa1fe8fdb53c4f81312cba5f771a8
Deployed Bytecode
0x6080604052600436106101665760003560e01c80639041e273116100d1578063d18e629c1161008a578063f2fde38b11610064578063f2fde38b1461052f578063f45671f11461054f578063f583bac71461056f578063f7f829a41461058f57600080fd5b8063d18e629c146104cf578063db227338146104ef578063ebea60251461050f57600080fd5b80639041e2731461042657806399157d70146104465780639c0b996614610466578063b6ad691414610483578063c24d5a5c14610498578063cd4eda1c146104ab57600080fd5b80634cb8ef5b116101235780634cb8ef5b146103805780635138b08c146103a0578063565c5172146103c0578063715018a6146103d3578063848e5c77146103e85780638da5cb5b1461040857600080fd5b8063041fa0b81461016b578063076b73ac146102a8578063186779d5146102ca57806320950fc6146103035780632f9c95761461033b5780633d87d5fb1461035b575b600080fd5b34801561017757600080fd5b5061021f610186366004613471565b60026020818152600093845260408085209091529183529120805460018201549282015460038301546004840154600585015460069095015463ffffffff8086169764010000000087049091169667ffffffffffffffff600160401b880416966001600160801b03600160801b91829004811697848216979290940416946001600160a01b03938416949184169390811692811691168b565b6040805163ffffffff9c8d1681529b909a1660208c015267ffffffffffffffff909816988a01989098526001600160801b0395861660608a015293851660808901529390911660a08701526001600160a01b0390811660c087015291821660e0860152811661010085015291821661012084015216610140820152610160015b60405180910390f35b3480156102b457600080fd5b506102c86102c336600461349d565b6105af565b005b3480156102d657600080fd5b506004546102ee90600160601b900463ffffffff1681565b60405163ffffffff909116815260200161029f565b34801561030f57600080fd5b5061032361031e366004613471565b610727565b6040516001600160a01b03909116815260200161029f565b34801561034757600080fd5b506102c86103563660046134fb565b61079c565b34801561036757600080fd5b506004546102ee90640100000000900463ffffffff1681565b34801561038c57600080fd5b506102c861039b366004613471565b610a10565b3480156103ac57600080fd5b506102c86103bb366004613471565b610b71565b6102c86103ce366004613539565b610c15565b3480156103df57600080fd5b506102c8610d97565b3480156103f457600080fd5b506102c8610403366004613471565b610e0b565b34801561041457600080fd5b506000546001600160a01b0316610323565b34801561043257600080fd5b506102c86104413660046136f4565b610ef5565b34801561045257600080fd5b506103236104613660046137a8565b61104b565b34801561047257600080fd5b506004546102ee9063ffffffff1681565b34801561048f57600080fd5b506102c8611075565b6102c86104a63660046137c1565b611170565b3480156104b757600080fd5b506004546102ee90600160401b900463ffffffff1681565b3480156104db57600080fd5b506102c86104ea366004613812565b61125d565b3480156104fb57600080fd5b506102c861050a3660046137a8565b6112d8565b34801561051b57600080fd5b506102c861052a366004613471565b6113b1565b34801561053b57600080fd5b506102c861054a366004613812565b6114ab565b34801561055b57600080fd5b506102c861056a36600461382f565b611595565b34801561057b57600080fd5b506102c861058a36600461388a565b611780565b34801561059b57600080fd5b506102c86105aa3660046134fb565b6119fb565b6001600160a01b038381166000908152600260209081526040808320868452909152902060030154849184911633146106035760405162461bcd60e51b81526004016105fa90613960565b60405180910390fd5b61060d8585611b9b565b6106465760405162461bcd60e51b815260206004820152600a6024820152694e6f7420612073616c6560b01b60448201526064016105fa565b6001600160a01b0385811660009081526002602081815260408084208985529091529091206004810180546001600160a01b03191687851617905590810154600190910154911690600160801b90046001600160801b031680158015906106bf5750846001600160a01b0316826001600160a01b031614155b156106e3576106ce8787611c0e565b6106e3878784846001600160801b0316611c67565b7f7502912f483c1fb3f89bf8664bea10db517c2093040d379e78e169e06752364687878760405161071693929190613989565b60405180910390a150505050505050565b6001600160a01b038083166000908152600260209081526040808320858452909152812060030154909116806107935760405162461bcd60e51b8152602060048201526011602482015270139195081b9bdd0819195c1bdcda5d1959607a1b60448201526064016105fa565b90505b92915050565b6001600160a01b038381166000908152600260209081526040808320868452909152902060030154849184911633146107e75760405162461bcd60e51b81526004016105fa90613960565b84846107f38282611db6565b156108405760405162461bcd60e51b815260206004820181905260248201527f5468652061756374696f6e2068617320612076616c696420626964206d61646560448201526064016105fa565b868661084c8282611b9b565b156108995760405162461bcd60e51b815260206004820152601960248201527f4e6f74206170706c696361626c6520666f7220612073616c650000000000000060448201526064016105fa565b866001600160801b0316600081116108c35760405162461bcd60e51b81526004016105fa906139ac565b6001600160a01b038a1660009081526002602090815260408083208c84529091529020600101546001600160801b03168881158061092757506004546001600160801b038281169161092491851690600160401b900463ffffffff16611e3a565b10155b6109435760405162461bcd60e51b81526004016105fa906139d7565b6001600160a01b038c1660009081526002602090815260408083208e84529091529081902080546001600160801b03808e16600160801b029116179055517fdcf27af4c564afa0c536dd1fa48e5fef0d9833378a1bddacc95922b902ebfc32906109d7908e908e908e906001600160a01b0393909316835260208301919091526001600160801b0316604082015260600190565b60405180910390a16109e98c8c611db6565b15610a02576109f88c8c611e53565b610a028c8c6120cc565b505050505050505050505050565b8181610a1c8282611db6565b15610a695760405162461bcd60e51b815260206004820181905260248201527f5468652061756374696f6e2068617320612076616c696420626964206d61646560448201526064016105fa565b6001600160a01b038085166000908152600260208181526040808420888552909152909120015416338114610ad85760405162461bcd60e51b815260206004820152601560248201527443616e6e6f742077697468647261772066756e647360581b60448201526064016105fa565b6001600160a01b0385166000908152600260209081526040808320878452909152902060010154600160801b90046001600160801b0316610b198686611c0e565b610b2e868684846001600160801b0316611c67565b7f10d9bddf66f639dd3c5a6ad2db5ae3102c2b468dfb90a4b0da219435f24a970d868633604051610b6193929190613989565b60405180910390a1505050505050565b8181610b7d828261217b565b15610bca5760405162461bcd60e51b815260206004820152601760248201527f41756374696f6e206973206e6f7420796574206f76657200000000000000000060448201526064016105fa565b610bd484846121cb565b7fe6b94748c5d6e0d188a0fcb9b7f2973b01fc0095627f1ec5accdcd9d2e65ca36848433604051610c0793929190613989565b60405180910390a150505050565b8484610c21828261217b565b610c615760405162461bcd60e51b8152602060048201526011602482015270105d58dd1a5bdb881a185cc8195b991959607a1b60448201526064016105fa565b826001600160a01b038116610cb85760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f74207370656369667920302061646472657373000000000000000060448201526064016105fa565b8787610cc4828261233d565b1580610cf757506001600160a01b0382811660009081526002602090815260408083208584529091529020600401541633145b610d435760405162461bcd60e51b815260206004820152601a60248201527f4f6e6c79207468652077686974656c697374656420627579657200000000000060448201526064016105fa565b6001600160a01b038a811660009081526002602090815260408083208d8452909152902060050180546001600160a01b031916918816919091179055610d8b8a8a8a8a61236a565b50505050505050505050565b6000546001600160a01b03163314610dc15760405162461bcd60e51b81526004016105fa90613a0e565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6001600160a01b03828116600090815260026020908152604080832085845290915290206003015483918391163314610e565760405162461bcd60e51b81526004016105fa90613960565b610e608484612638565b610ea25760405162461bcd60e51b815260206004820152601360248201527218d85b9b9bdd081c185e5bdd5d080c08189a59606a1b60448201526064016105fa565b610eac8484611e53565b610eb684846121cb565b604080516001600160a01b0386168152602081018590527f711f4eae05533b90c24ff0ae762d6e9e1ef1b2c85d4c484a2913c5201bcbb7c99101610c07565b6001600160a01b0380881660009081526002602090815260408083208a84529091529020600301548891889133911603610f415760405162461bcd60e51b81526004016105fa90613a43565b6001600160a01b0382811660009081526002602090815260408083208584529091529020600301541615611012576040516331a9108f60e11b8152600481018290526001600160a01b03831690636352211e90602401602060405180830381865afa158015610fb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd89190613a78565b6001600160a01b0316336001600160a01b0316146110085760405162461bcd60e51b81526004016105fa90613a95565b6110128282612675565b856001600160801b03166000811161103c5760405162461bcd60e51b81526004016105fa906139ac565b610d8b8a8a8a8a8a8a8a6126dd565b6001818154811061105b57600080fd5b6000918252602090912001546001600160a01b0316905081565b33600090815260036020526040812054908190036110ce5760405162461bcd60e51b81526020600482015260166024820152756e6f206372656469747320746f20776974686472617760501b60448201526064016105fa565b3360008181526003602052604080822082905551909190614e2090849084818181858888f193505050503d8060008114611124576040519150601f19603f3d011682016040523d82523d6000602084013e611129565b606091505b505090508061116c5760405162461bcd60e51b815260206004820152600f60248201526e1dda5d1a191c985dc819985a5b1959608a1b60448201526064016105fa565b5050565b838361117c828261217b565b6111bc5760405162461bcd60e51b8152602060048201526011602482015270105d58dd1a5bdb881a185cc8195b991959607a1b60448201526064016105fa565b85856111c8828261233d565b15806111fb57506001600160a01b0382811660009081526002602090815260408083208584529091529020600401541633145b6112475760405162461bcd60e51b815260206004820152601a60248201527f4f6e6c79207468652077686974656c697374656420627579657200000000000060448201526064016105fa565b6112538888888861236a565b5050505050505050565b6000546001600160a01b031633146112875760405162461bcd60e51b81526004016105fa90613a0e565b6001805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146113025760405162461bcd60e51b81526004016105fa90613a0e565b60018054611311908290613adb565b8154811061132157611321613af2565b600091825260209091200154600180546001600160a01b03909216918390811061134d5761134d613af2565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600180548061138c5761138c613b08565b600082815260209020810160001990810180546001600160a01b031916905501905550565b6040516331a9108f60e11b81526004810182905233906001600160a01b03841690636352211e90602401602060405180830381865afa1580156113f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141c9190613a78565b6001600160a01b0316146114625760405162461bcd60e51b815260206004820152600d60248201526c2737ba1027232a1037bbb732b960991b60448201526064016105fa565b61146c8282612675565b7fec19f84af4aad6523d37faa19e243c77717842cca9bf492dc5379830cac958d082823360405161149f93929190613989565b60405180910390a15050565b6000546001600160a01b031633146114d55760405162461bcd60e51b81526004016105fa90613a0e565b6001600160a01b03811661153a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105fa565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0380881660009081526002602090815260408083208a845290915290206003015488918891339116036115e15760405162461bcd60e51b81526004016105fa90613a43565b6001600160a01b03828116600090815260026020908152604080832085845290915290206003015416156116b2576040516331a9108f60e11b8152600481018290526001600160a01b03831690636352211e90602401602060405180830381865afa158015611654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116789190613a78565b6001600160a01b0316336001600160a01b0316146116a85760405162461bcd60e51b81526004016105fa90613a95565b6116b28282612675565b856001600160801b0316600081116116dc5760405162461bcd60e51b81526004016105fa906139ac565b6116eb8a8a8a8a8a8a8a61275a565b7fb4cb1faa7b4f2b837334e4a12fb94a1cfc320c32b70dd31e113d1795b9d0f0568a8a338b8b8b8b8b604051611728989796959493929190613b98565b60405180910390a161173a8a8a612638565b15610d8b576117498a8a612980565b15611776576117588a8a6129ca565b15611771576117678a8a611e53565b6117718a8a6121cb565b610d8b565b610d8b8a8a612a4a565b6001600160a01b03808a1660009081526002602090815260408083208c84529091529020600301548a918a91339116036117cc5760405162461bcd60e51b81526004016105fa90613a43565b6001600160a01b038281166000908152600260209081526040808320858452909152902060030154161561189d576040516331a9108f60e11b8152600481018290526001600160a01b03831690636352211e90602401602060405180830381865afa15801561183f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118639190613a78565b6001600160a01b0316336001600160a01b0316146118935760405162461bcd60e51b81526004016105fa90613a95565b61189d8282612675565b876001600160801b0316600081116118c75760405162461bcd60e51b81526004016105fa906139ac565b600454869063ffffffff6401000000009091048116908216101561192d5760405162461bcd60e51b815260206004820152601f60248201527f42696420696e6372656173652070657263656e7461676520746f6f206c6f770060448201526064016105fa565b87600260008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e815260200190815260200160002060000160046101000a81548163ffffffff021916908363ffffffff16021790555086600260008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e815260200190815260200160002060000160006101000a81548163ffffffff021916908363ffffffff1602179055506119ec8d8d8d8d8d8b8b6126dd565b50505050505050505050505050565b6001600160a01b03838116600090815260026020908152604080832086845290915290206003015484918491163314611a465760405162461bcd60e51b81526004016105fa90613960565b826001600160801b031660008111611a705760405162461bcd60e51b81526004016105fa906139ac565b6001600160a01b038616600090815260026020908152604080832088845290915290205484906001600160801b03600160801b90910481169082161580611add57506004546001600160801b0382811691611ada91851690600160401b900463ffffffff16611e3a565b10155b611af95760405162461bcd60e51b81526004016105fa906139d7565b6001600160a01b03881660008181526002602090815260408083208b845282529182902060010180546001600160801b0319166001600160801b038b1690811790915582519384529083018a9052908201527fcc66420416a999e685e3938d2c6252ed709db214d0435f13da0b1e5339bcac769060600160405180910390a1611b8288886129ca565b1561125357611b918888611e53565b61125388886121cb565b6001600160a01b03821660009081526002602090815260408083208484529091528120600101546001600160801b0316158015906107935750506001600160a01b039190911660009081526002602090815260408083209383529290522054600160801b90046001600160801b03161590565b6001600160a01b0391909116600090815260026020818152604080842094845293905291902090810180546001600160a01b03199081169091556001820180546001600160801b03169055600590910180549091169055565b6001600160a01b038481166000908152600260209081526040808320878452909152902060060154168015611d0f5760405163a9059cbb60e01b81526001600160a01b0384811660048301526024820184905282169063a9059cbb906044016020604051808303816000875af1158015611ce5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d099190613c0e565b50611daf565b6000836001600160a01b031683614e2090604051600060405180830381858888f193505050503d8060008114611d61576040519150601f19603f3d011682016040523d82523d6000602084013e611d66565b606091505b5050905080611dad576001600160a01b038416600090815260036020526040902054611d93908490613c30565b6001600160a01b0385166000908152600360205260409020555b505b5050505050565b6001600160a01b0382166000908152600260209081526040808320848452909152812054600160801b90046001600160801b03168015801590611e3257506001600160a01b03841660009081526002602090815260408083208684529091529020600101546001600160801b03808316600160801b9092041610155b949350505050565b6000612710611e498385613c48565b6107939190613c7d565b6001600160a01b038281166000818152600260209081526040808320868452909152908190206003015490516331a9108f60e11b815260048101859052921691829190636352211e90602401602060405180830381865afa158015611ebc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee09190613a78565b6001600160a01b031603612012576040516323b872dd60e01b81526001600160a01b038281166004830152306024830152604482018490528416906323b872dd90606401600060405180830381600087803b158015611f3e57600080fd5b505af1158015611f52573d6000803e3d6000fd5b50506040516331a9108f60e11b8152600481018590523092506001600160a01b0386169150636352211e90602401602060405180830381865afa158015611f9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc19190613a78565b6001600160a01b03161461200d5760405162461bcd60e51b81526020600482015260136024820152721b999d081d1c985b9cd9995c8819985a5b1959606a1b60448201526064016105fa565b505050565b6040516331a9108f60e11b81526004810183905230906001600160a01b03851690636352211e90602401602060405180830381865afa158015612059573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061207d9190613a78565b6001600160a01b03161461200d5760405162461bcd60e51b815260206004820152601660248201527514d95b1b195c88191bd95cdb89dd081bdddb8813919560521b60448201526064016105fa565b426120d78383612ab1565b63ffffffff166120e79190613c91565b6001600160a01b038316600081815260026020908152604080832086845282529182902080546fffffffffffffffff00000000000000001916600160401b67ffffffffffffffff96871681029190911791829055835194855291840186905204909216918101919091527fc1ce6cc1337b95ed3c849e00bffc0d93e89e5e80cc5d198db838140827ac75949060600161149f565b6001600160a01b0382166000908152600260209081526040808320848452909152812054600160401b900467ffffffffffffffff16801580611e32575067ffffffffffffffff1642109392505050565b6001600160a01b038281166000908152600260208181526040808420868552909152822060038101549101549083169216906122078585612b08565b6001600160a01b0386166000908152600260209081526040808320888452909152902060010154909150600160801b90046001600160801b031661224b8686611c0e565b612260868686846001600160801b0316612b67565b6040516323b872dd60e01b81523060048201526001600160a01b038381166024830152604482018790528716906323b872dd90606401600060405180830381600087803b1580156122b057600080fd5b505af11580156122c4573d6000803e3d6000fd5b505050506122d28686612675565b604080516001600160a01b03808916825260208201889052808716928201929092526001600160801b0383166060820152818516608082015290831660a08201527f8df77c988c9550e96e43a66277f716818a74ed2188cdacb49d790623e6f225719060c001610b61565b6001600160a01b039182166000908152600260209081526040808320938352929052206004015416151590565b6000805b6001548110156124235760006001828154811061238d5761238d613af2565b6000918252602090912001546040516370a0823160e01b81523360048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156123de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124029190613cbd565b11156124115760019150612423565b8061241b81613cd6565b91505061236e565b50806124715760405162461bcd60e51b815260206004820152601e60248201527f53656e64657220686173206e6f2077686974656c6973746564204e465473000060448201526064016105fa565b506001600160a01b038085166000908152600260209081526040808320878452909152902060030154859185911633036124ed5760405162461bcd60e51b815260206004820152601b60248201527f4f776e65722063616e6e6f7420626964206f6e206f776e204e4654000000000060448201526064016105fa565b858585856124fd84848484612c93565b6125495760405162461bcd60e51b815260206004820181905260248201527f42696420746f20626520696e207370656369666965642045524332302f45746860448201526064016105fa565b898988612557838383612d30565b6125a35760405162461bcd60e51b815260206004820152601e60248201527f4e6f7420656e6f7567682066756e647320746f20626964206f6e204e4654000060448201526064016105fa565b6125ae8d8d8c612e3e565b7fdfd4ac8cb43d5458b7a6f74f2d6461d77d4985704bdbc2fd4c4816444bbfd5e08d8d33348f8f604051612626969594939291906001600160a01b03968716815260208101959095529285166040850152606084019190915290921660808201526001600160801b039190911660a082015260c00190565b60405180910390a16119ec8d8d612ea6565b6001600160a01b039190911660009081526002602090815260408083209383529290522060010154600160801b90046001600160801b0316151590565b6001600160a01b039190911660009081526002602090815260408083209383529290529081206001810180546001600160801b03191690559081556003810180546001600160a01b031990811690915560048201805482169055600690910180549091169055565b6126ec87878787878787612eec565b7f3379e969de5522101a0f0912ffe00daf15361dbcbf9cd5c328e0dd97aa25cdf987873388888861271d8e8e612ab1565b6127278f8f61318d565b8a8a60405161273f9a99989796959493929190613cef565b60405180910390a16127518787612ea6565b50505050505050565b815181518082146127a95760405162461bcd60e51b8152602060048201526019602482015278526563697069656e747320213d2070657263656e746167657360381b60448201526064016105fa565b826000805b82518110156127f0578281815181106127c9576127c9613af2565b6020026020010151826127dc9190613d7d565b9150806127e881613cd6565b9150506127ae565b506127108163ffffffff1611156128495760405162461bcd60e51b815260206004820152601e60248201527f4665652070657263656e746167657320657863656564206d6178696d756d000060448201526064016105fa565b6001600160a01b03891615612895576001600160a01b038b811660009081526002602090815260408083208e8452909152902060060180546001600160a01b031916918b169190911790555b6001600160a01b038b1660009081526002602090815260408083208d8452825290912087516128cc92600790920191890190613339565b506001600160a01b038b1660009081526002602090815260408083208d8452825290912086516129049260089092019188019061339e565b505050506001600160a01b039788166000908152600260209081526040808320998352989052969096206001810180546001600160801b03969096166001600160801b0319909616959095179094555050600482018054919095166001600160a01b031991821617909455600301805490931633179092555050565b600061298c838361233d565b158061079357506001600160a01b03808416600090815260026020818152604080842087855290915290912060048101549101548216911614610793565b6001600160a01b03821660009081526002602090815260408083208484529091528120600101546001600160801b03168015801590611e3257506001600160a01b03841660009081526002602090815260408083208684529091529020600101546001600160801b03808316600160801b90920416101591505092915050565b6001600160a01b03828116600090815260026020818152604080842086855290915290912090810154600190910154911690600160801b90046001600160801b0316612a968484611c0e565b612aab848484846001600160801b0316611c67565b50505050565b6001600160a01b0382166000908152600260209081526040808320848452909152812054640100000000900463ffffffff16808203612b01575050600454600160601b900463ffffffff16610796565b9050610796565b6001600160a01b03808316600090815260026020908152604080832085845290915281206005015490911680612b015750506001600160a01b038083166000908152600260208181526040808420868552909152909120015416610796565b6000805b6001600160a01b0386166000908152600260209081526040808320888452909152902060070154811015612c7d576001600160a01b038616600090815260026020908152604080832088845290915281206008018054612c0091869185908110612bd757612bd7613af2565b6000918252602090912060088204015460079091166004026101000a900463ffffffff16611e3a565b9050612c0c8184613c30565b6001600160a01b03881660009081526002602090815260408083208a845290915290206007018054919450612c6a918991899186908110612c4f57612c4f613af2565b6000918252602090912001546001600160a01b031684611c67565b5080612c7581613cd6565b915050612b6b565b50611daf858585612c8e8587613adb565b611c67565b6001600160a01b0384811660009081526002602090815260408083208784529091528120600601549091168015612d005734158015612ce35750836001600160a01b0316816001600160a01b0316145b8015612cf857506000836001600160801b0316115b915050611e32565b3415801590612d1657506001600160a01b038416155b8015612cf8575050506001600160801b0316159392505050565b6001600160a01b03831660009081526002602090815260408083208584529091528120600101546001600160801b03168015801590612d945750806001600160801b031634101580612d945750806001600160801b0316836001600160801b031610155b15612da3576001915050612e37565b6000612710612db2878761318d565b612dbe90612710613d7d565b6001600160a01b03881660009081526002602090815260408083208a8452909152902060010154612e059163ffffffff1690600160801b90046001600160801b0316613d9c565b612e0f9190613dcb565b6001600160801b031690508034101580612e32575080846001600160801b031610155b925050505b9392505050565b6001600160a01b03838116600090815260026020818152604080842087855290915290912090810154600190910154911690600160801b90046001600160801b0316612e8b8585856131ce565b6001600160a01b03821615611daf57611daf85858484611c67565b612eb082826129ca565b15612ec957612ebf8282611e53565b61116c82826121cb565b612ed38282611db6565b1561116c57612ee28282611e53565b61116c82826120cc565b82846001600160801b0382161580612f2a57506004546001600160801b0382811691612f2791851690600160401b900463ffffffff16611e3a565b10155b612f465760405162461bcd60e51b81526004016105fa906139d7565b83518351808214612f955760405162461bcd60e51b8152602060048201526019602482015278526563697069656e747320213d2070657263656e746167657360381b60448201526064016105fa565b846000805b8251811015612fdc57828181518110612fb557612fb5613af2565b602002602001015182612fc89190613d7d565b915080612fd481613cd6565b915050612f9a565b506127108163ffffffff1611156130355760405162461bcd60e51b815260206004820152601e60248201527f4665652070657263656e746167657320657863656564206d6178696d756d000060448201526064016105fa565b6001600160a01b038b16156130a3578a600260008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e815260200190815260200160002060060160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b6001600160a01b038d1660009081526002602090815260408083208f8452825290912089516130da926007909201918b0190613339565b506001600160a01b038d1660009081526002602090815260408083208f845282529091208851613112926008909201918a019061339e565b505050506001600160a01b039990991660009081526002602090815260408083209a8352999052979097206001810180546001600160801b039687166001600160801b03199091161790558054958516600160801b0295909416949094178355505060030180546001600160a01b0319163317905550505050565b6001600160a01b038216600090815260026020908152604080832084845290915281205463ffffffff16808203612b0157505060045463ffffffff16610796565b6001600160a01b0383811660009081526002602090815260408083208684529091529020600601541680156132c0576040516323b872dd60e01b81523360048201523060248201526001600160801b03831660448201526001600160a01b038216906323b872dd906064016020604051808303816000875af1158015613258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061327c9190613c0e565b506001600160a01b0384166000908152600260209081526040808320868452909152902060010180546001600160801b03808516600160801b0291161790556132ff565b6001600160a01b0384166000908152600260209081526040808320868452909152902060010180546001600160801b03348116600160801b0291161790555b50506001600160a01b0390911660009081526002602081815260408084209484529390529190200180546001600160a01b03191633179055565b82805482825590600052602060002090810192821561338e579160200282015b8281111561338e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613359565b5061339a929150613444565b5090565b8280548282559060005260206000209060070160089004810192821561338e5791602002820160005b8382111561340b57835183826101000a81548163ffffffff021916908363ffffffff16021790555092602001926004016020816003010492830192600103026133c7565b801561343b5782816101000a81549063ffffffff021916905560040160208160030104928301926001030261340b565b505061339a9291505b5b8082111561339a5760008155600101613445565b6001600160a01b038116811461346e57600080fd5b50565b6000806040838503121561348457600080fd5b823561348f81613459565b946020939093013593505050565b6000806000606084860312156134b257600080fd5b83356134bd81613459565b92506020840135915060408401356134d481613459565b809150509250925092565b80356001600160801b03811681146134f657600080fd5b919050565b60008060006060848603121561351057600080fd5b833561351b81613459565b925060208401359150613530604085016134df565b90509250925092565b600080600080600060a0868803121561355157600080fd5b853561355c81613459565b945060208601359350604086013561357381613459565b9250613581606087016134df565b9150608086013561359181613459565b809150509295509295909350565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156135de576135de61359f565b604052919050565b600067ffffffffffffffff8211156136005761360061359f565b5060051b60200190565b600082601f83011261361b57600080fd5b8135602061363061362b836135e6565b6135b5565b82815260059290921b8401810191818101908684111561364f57600080fd5b8286015b8481101561367357803561366681613459565b8352918301918301613653565b509695505050505050565b803563ffffffff811681146134f657600080fd5b600082601f8301126136a357600080fd5b813560206136b361362b836135e6565b82815260059290921b840181019181810190868411156136d257600080fd5b8286015b84811015613673576136e78161367e565b83529183019183016136d6565b600080600080600080600060e0888a03121561370f57600080fd5b873561371a81613459565b965060208801359550604088013561373181613459565b945061373f606089016134df565b935061374d608089016134df565b925060a088013567ffffffffffffffff8082111561376a57600080fd5b6137768b838c0161360a565b935060c08a013591508082111561378c57600080fd5b506137998a828b01613692565b91505092959891949750929550565b6000602082840312156137ba57600080fd5b5035919050565b600080600080608085870312156137d757600080fd5b84356137e281613459565b93506020850135925060408501356137f981613459565b9150613807606086016134df565b905092959194509250565b60006020828403121561382457600080fd5b813561079381613459565b600080600080600080600060e0888a03121561384a57600080fd5b873561385581613459565b965060208801359550604088013561386c81613459565b945061387a606089016134df565b9350608088013561374d81613459565b60008060008060008060008060006101208a8c0312156138a957600080fd5b89356138b481613459565b985060208a0135975060408a01356138cb81613459565b96506138d960608b016134df565b95506138e760808b016134df565b94506138f560a08b0161367e565b935061390360c08b0161367e565b925060e08a013567ffffffffffffffff8082111561392057600080fd5b61392c8d838e0161360a565b93506101008c013591508082111561394357600080fd5b506139508c828d01613692565b9150509295985092959850929598565b6020808252600f908201526e27b7363c9037333a1039b2b63632b960891b604082015260600190565b6001600160a01b0393841681526020810192909252909116604082015260600190565b602080825260119082015270050726963652063616e6e6f74206265203607c1b604082015260600190565b6020808252601d908201527f4d696e5072696365203e20383025206f66206275794e6f775072696365000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252818101527f41756374696f6e20616c72656164792073746172746564206279206f776e6572604082015260600190565b600060208284031215613a8a57600080fd5b815161079381613459565b60208082526016908201527514d95b99195c88191bd95cdb89dd081bdddb8813919560521b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b600082821015613aed57613aed613ac5565b500390565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b600081518084526020808501945080840160005b83811015613b575781516001600160a01b031687529582019590820190600101613b32565b509495945050505050565b600081518084526020808501945080840160005b83811015613b5757815163ffffffff1687529582019590820190600101613b76565b6001600160a01b03898116825260208201899052878116604083015286811660608301526001600160801b0386166080830152841660a082015261010060c08201819052600090613beb83820186613b1e565b905082810360e0840152613bff8185613b62565b9b9a5050505050505050505050565b600060208284031215613c2057600080fd5b8151801515811461079357600080fd5b60008219821115613c4357613c43613ac5565b500190565b6000816000190483118215151615613c6257613c62613ac5565b500290565b634e487b7160e01b600052601260045260246000fd5b600082613c8c57613c8c613c67565b500490565b600067ffffffffffffffff808316818516808303821115613cb457613cb4613ac5565b01949350505050565b600060208284031215613ccf57600080fd5b5051919050565b600060018201613ce857613ce8613ac5565b5060010190565b6001600160a01b038b81168252602082018b90528981166040830152881660608201526001600160801b038781166080830152861660a082015263ffffffff85811660c0830152841660e08201526101406101008201819052600090613d5783820186613b1e565b9050828103610120840152613d6c8185613b62565b9d9c50505050505050505050505050565b600063ffffffff808316818516808303821115613cb457613cb4613ac5565b60006001600160801b0380831681851681830481118215151615613dc257613dc2613ac5565b02949350505050565b60006001600160801b0380841680613de557613de5613c67565b9216919091049291505056fea26469706673582212206a536cf573a2864b43e335f913d2731550811ae78d2ef81b8f5eadbaeb12395764736f6c634300080d0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000d3228e099e6596988ae0b73eaa62591c875e56930000000000000000000000005dc23613fd54a87c3b8a7134534110f5180433c8000000000000000000000000932aeac0eebaa1fe8fdb53c4f81312cba5f771a8
-----Decoded View---------------
Arg [0] : _whitelistedPassCollectionsAddresses (address[]): 0xD3228e099E6596988Ae0b73EAa62591c875e5693,0x5DC23613fD54A87C3b8A7134534110F5180433C8,0x932aEAc0eEBaA1fE8fdB53C4f81312cBA5F771A8
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [2] : 000000000000000000000000d3228e099e6596988ae0b73eaa62591c875e5693
Arg [3] : 0000000000000000000000005dc23613fd54a87c3b8a7134534110f5180433c8
Arg [4] : 000000000000000000000000932aeac0eebaa1fe8fdb53c4f81312cba5f771a8
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.