Source Code
Latest 25 from a total of 17,445 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Bid | 24511734 | 15 mins ago | IN | 0.00169 ETH | 0.00008578 | ||||
| List | 24511711 | 19 mins ago | IN | 0 ETH | 0.00000915 | ||||
| List | 24511671 | 27 mins ago | IN | 0 ETH | 0.00023559 | ||||
| List | 24511664 | 29 mins ago | IN | 0 ETH | 0.00002768 | ||||
| Delist | 24511661 | 29 mins ago | IN | 0 ETH | 0.00010826 | ||||
| List | 24511505 | 1 hr ago | IN | 0 ETH | 0.00050063 | ||||
| List | 24511185 | 2 hrs ago | IN | 0 ETH | 0.000011 | ||||
| List | 24510855 | 3 hrs ago | IN | 0 ETH | 0.00046393 | ||||
| List | 24510842 | 3 hrs ago | IN | 0 ETH | 0.00046383 | ||||
| List | 24510759 | 3 hrs ago | IN | 0 ETH | 0.00000761 | ||||
| List | 24510508 | 4 hrs ago | IN | 0 ETH | 0.00046437 | ||||
| Bid | 24510479 | 4 hrs ago | IN | 0.6993 ETH | 0.00002122 | ||||
| List | 24510460 | 4 hrs ago | IN | 0 ETH | 0.00049872 | ||||
| Bid | 24510178 | 5 hrs ago | IN | 0.048 ETH | 0.00000226 | ||||
| Bid | 24510178 | 5 hrs ago | IN | 0.666 ETH | 0.00018671 | ||||
| Bid | 24510178 | 5 hrs ago | IN | 0.04725 ETH | 0.00018671 | ||||
| Bid | 24510176 | 5 hrs ago | IN | 0.045 ETH | 0.00026633 | ||||
| Settle Auction | 24509932 | 6 hrs ago | IN | 0 ETH | 0.00029464 | ||||
| List | 24509764 | 6 hrs ago | IN | 0 ETH | 0.00051787 | ||||
| List | 24509754 | 6 hrs ago | IN | 0 ETH | 0.00000723 | ||||
| List | 24509627 | 7 hrs ago | IN | 0 ETH | 0.00000149 | ||||
| List | 24509627 | 7 hrs ago | IN | 0 ETH | 0.00000149 | ||||
| List | 24509627 | 7 hrs ago | IN | 0 ETH | 0.00000705 | ||||
| Bid | 24509326 | 8 hrs ago | IN | 0.00011025 ETH | 0.0000029 | ||||
| List | 24509272 | 8 hrs ago | IN | 0 ETH | 0.00003023 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 24511734 | 15 mins ago | 0.0015 ETH | ||||
| Transfer | 24510479 | 4 hrs ago | 0.666 ETH | ||||
| Transfer | 24510178 | 5 hrs ago | 0.04725 ETH | ||||
| Transfer | 24510178 | 5 hrs ago | 0.045 ETH | ||||
| Transfer | 24509932 | 6 hrs ago | 0.67275 ETH | ||||
| Transfer | 24509932 | 6 hrs ago | 0.01725 ETH | ||||
| Transfer | 24509326 | 8 hrs ago | 0.000105 ETH | ||||
| Transfer | 24508927 | 9 hrs ago | 0.0067275 ETH | ||||
| Transfer | 24508927 | 9 hrs ago | 0.0001725 ETH | ||||
| Transfer | 24508593 | 10 hrs ago | 0.067275 ETH | ||||
| Transfer | 24508593 | 10 hrs ago | 0.001725 ETH | ||||
| Transfer | 24507814 | 13 hrs ago | 0.024375 ETH | ||||
| Transfer | 24507814 | 13 hrs ago | 0.000625 ETH | ||||
| Transfer | 24507802 | 13 hrs ago | 0.0013 ETH | ||||
| Transfer | 24507273 | 15 hrs ago | 0.10725 ETH | ||||
| Transfer | 24507273 | 15 hrs ago | 0.00275 ETH | ||||
| Transfer | 24506858 | 16 hrs ago | 0.00105 ETH | ||||
| Transfer | 24506570 | 17 hrs ago | 0.04875 ETH | ||||
| Transfer | 24506570 | 17 hrs ago | 0.00125 ETH | ||||
| Transfer | 24506545 | 17 hrs ago | 0.092 ETH | ||||
| Transfer | 24506333 | 18 hrs ago | 0.0001 ETH | ||||
| Transfer | 24505398 | 21 hrs ago | 0.001 ETH | ||||
| Transfer | 24504557 | 24 hrs ago | 0.0861 ETH | ||||
| Transfer | 24504167 | 25 hrs ago | 0.06825 ETH | ||||
| Transfer | 24504167 | 25 hrs ago | 0.00175 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TLAuctionHouse
Compiler Version
v0.8.22+commit.4fc1097e
Optimization Enabled:
Yes with 20000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;
import {Ownable} from "@openzeppelin-contracts-5.0.2/access/Ownable.sol";
import {Pausable} from "@openzeppelin-contracts-5.0.2/utils/Pausable.sol";
import {ReentrancyGuard} from "@openzeppelin-contracts-5.0.2/utils/ReentrancyGuard.sol";
import {IERC721} from "@openzeppelin-contracts-5.0.2/token/ERC721/IERC721.sol";
import {TransferHelper} from "tl-sol-tools-3.1.4/payments/TransferHelper.sol";
import {SanctionsCompliance} from "tl-sol-tools-3.1.4/payments/SanctionsCompliance.sol";
import {ListingType, Listing, ITLAuctionHouseEvents} from "./utils/TLAuctionHouseUtils.sol";
import {ICreatorLookup} from "./helpers/ICreatorLookup.sol";
import {IRoyaltyLookup} from "./helpers/IRoyaltyLookup.sol";
/// @title TLAuctionHouse
/// @notice Transient Labs Auction House for ERC-721 tokens
/// @author transientlabs.xyz
/// @custom:version-last-updated 2.6.1
contract TLAuctionHouse is
Ownable,
Pausable,
ReentrancyGuard,
SanctionsCompliance,
TransferHelper,
ITLAuctionHouseEvents
{
///////////////////////////////////////////////////////////////////////////
/// CONSTANTS
///////////////////////////////////////////////////////////////////////////
string public constant VERSION = "2.6.1";
uint256 public constant EXTENSION_TIME = 5 minutes;
uint256 public constant BASIS = 10_000;
uint256 public constant BID_INCREASE_BPS = 500; // 5% increase between bids
///////////////////////////////////////////////////////////////////////////
/// STATE VARIABLES
///////////////////////////////////////////////////////////////////////////
uint256 private _id; // listing id
address public protocolFeeReceiver; // receives protocol fee
uint256 public protocolFeeBps; // basis points for protocol fee
address public weth; // weth address
ICreatorLookup public creatorLookup; // creator lookup contract
IRoyaltyLookup public royaltyLookup; // royalty lookup contract
mapping(address => mapping(uint256 => Listing)) private _listings; // nft address -> token id -> listing
///////////////////////////////////////////////////////////////////////////
/// ERRORS
///////////////////////////////////////////////////////////////////////////
error InvalidListingType();
error NotTokenOwner();
error TokenNotTransferred();
error NotSeller();
error ListingNotSetup();
error AuctionStarted();
error AuctionNotStarted();
error AuctionNotEnded();
error CannotBidYet();
error CannotBuyYet();
error InvalidRecipient();
error BidTooLow();
error AuctionEnded();
error UnexpectedMsgValue();
error InvalidProtocolFeeBps();
///////////////////////////////////////////////////////////////////////////
/// CONSTRUCTOR
///////////////////////////////////////////////////////////////////////////
constructor(address initOwner, address initSanctionsOracle)
Ownable(initOwner)
Pausable()
ReentrancyGuard()
SanctionsCompliance(initSanctionsOracle)
{}
///////////////////////////////////////////////////////////////////////////
/// PUBLIC FUNCTIONS
///////////////////////////////////////////////////////////////////////////
/// @notice Function to list an NFT for sale
/// @dev Requirements
/// - only the token owner can list
/// - the token is escrowed upon listing
/// - if the auction house isn't approved for the token, escrowing will fail, so no need to check for that explicitly
/// @param nftAddress The nft contract address
/// @param tokenId The nft token id
/// @param type_ The ListingType
/// @param payoutReceiver The address that will receive payout for the sale
/// @param currencyAddress The address of the currency to use (zero address == ETH)
/// @param openTime The time at which the listing will open (if in the past, defaults to current block timestamp)
/// @param reservePrice The reserve price for the auction (if part of the listing type)
/// @param auctionDuration The duration of the auction
/// @param buyNowPrice The price at which the token can be instantly bought if the listing if properly configured for this
function list(
address nftAddress,
uint256 tokenId,
ListingType type_,
address payoutReceiver,
address currencyAddress,
uint256 openTime,
uint256 reservePrice,
uint256 auctionDuration,
uint256 buyNowPrice
) external whenNotPaused nonReentrant {
// check for sanctioned addresses
_isSanctioned(msg.sender, true);
_isSanctioned(payoutReceiver, true);
// check that the sender owns the token
IERC721 nftContract = IERC721(nftAddress);
if (nftContract.ownerOf(tokenId) != msg.sender) revert NotTokenOwner(); // once listed, can't list again as the msg.sender wouldn't be the owner
// if openTime is in a previous block, set to the current block timestamp
if (openTime < block.timestamp) {
openTime = block.timestamp;
}
// create listing
uint256 id = ++_id;
Listing memory listing = Listing({
type_: type_,
zeroProtocolFee: false,
seller: msg.sender,
payoutReceiver: payoutReceiver,
currencyAddress: currencyAddress,
openTime: openTime,
reservePrice: reservePrice,
buyNowPrice: buyNowPrice,
startTime: 0,
duration: auctionDuration,
recipient: address(0),
highestBidder: address(0),
highestBid: 0,
id: id
});
// adjust listing based on listing type
if (type_ == ListingType.SCHEDULED_AUCTION) {
listing.startTime = openTime;
listing.buyNowPrice = 0;
} else if (type_ == ListingType.RESERVE_AUCTION) {
listing.buyNowPrice = 0;
} else if (type_ == ListingType.RESERVE_AUCTION_PLUS_BUY_NOW) {
// do nothing
} else if (type_ == ListingType.BUY_NOW) {
listing.reservePrice = 0;
listing.duration = 0;
} else {
revert InvalidListingType();
}
// set listing
_listings[nftAddress][tokenId] = listing;
// escrow token, should revert if contract isn't approved
nftContract.transferFrom(msg.sender, address(this), tokenId);
// check to ensure it was escrowed
if (nftContract.ownerOf(tokenId) != address(this)) revert TokenNotTransferred();
emit ListingConfigured(msg.sender, nftAddress, tokenId, listing);
}
/// @notice Function to cancel a listing
/// @dev Requirements
/// - only the seller of the listing can delist
/// - the listing must be active
/// - the auction cannot have been started when delisting
/// @param nftAddress The nft contract address
/// @param tokenId The nft token id
function delist(address nftAddress, uint256 tokenId) external whenNotPaused nonReentrant {
// cache data
IERC721 nftContract = IERC721(nftAddress);
Listing memory listing = _listings[nftAddress][tokenId];
// revert if caller is not seller
// this also catches if the nft is not listing, as the seller is the zero address
if (msg.sender != listing.seller) revert NotSeller();
// check if auction has been bid on (this should always pass if listing type is BUY_NOW)
if (listing.highestBidder != address(0)) revert AuctionStarted();
// delete listing & auction
delete _listings[nftAddress][tokenId];
// transfer token back to seller
nftContract.transferFrom(address(this), listing.seller, tokenId);
emit ListingCanceled(msg.sender, nftAddress, tokenId, listing);
}
/// @notice Function to bid on a token that has an auction configured
/// @dev Requirements
/// - msg.sender & recipient can't be sanctioned addresses
/// - recipient cannot be the zero address
/// - a listing must be configured as an auction
/// - the block timestamp is past the listing open time
/// - the bid can't be too low (under reserve price for first bid or under next bid for subsequent bids)
/// - the auction can't have ended
/// - the funds sent must match `amount` exactly when bidding
/// - the previous bid is sent back
/// - if bidding with ERC-20 tokens, no ETH is allowed to be sent
/// - if a bid comes within `EXTENSION_TIME`, extend the auction back to `EXTENSION_TIME`
/// - the bidder can specify a recipient for the nft they are bidding on, which allows for cross-chain bids to occur
/// @param nftAddress The nft contract address
/// @param tokenId The nft token id
/// @param recipient The recipient that will receive the NFT if the bid is the winning bid
/// @param amount The amount to bid
function bid(address nftAddress, uint256 tokenId, address recipient, uint256 amount)
external
payable
whenNotPaused
nonReentrant
{
// check sender & recipient
_isSanctioned(msg.sender, true);
if (!_isValidRecipient(recipient)) revert InvalidRecipient();
// cache data
Listing memory listing = _listings[nftAddress][tokenId];
uint256 previousBid = listing.highestBid;
address previousBidder = listing.highestBidder;
// check the listing type
if (listing.type_ == ListingType.NOT_CONFIGURED || listing.type_ == ListingType.BUY_NOW) {
revert InvalidListingType();
}
// cannot bid if prior to listing.openTime
if (block.timestamp < listing.openTime) revert CannotBidYet();
// check constraints on first bid versus other bids
if (previousBidder == address(0)) {
// first bid cannot bid under reserve price
if (amount < listing.reservePrice) revert BidTooLow();
// set start time if reserve auction
if (
listing.type_ == ListingType.RESERVE_AUCTION
|| listing.type_ == ListingType.RESERVE_AUCTION_PLUS_BUY_NOW
) {
listing.startTime = block.timestamp;
}
// if scheduled auction, make sure that can't bid on a token that has gone past the scheduled duration without bids
if (listing.type_ == ListingType.SCHEDULED_AUCTION) {
if (block.timestamp > listing.startTime + listing.duration) revert AuctionEnded();
}
} else {
// subsequent bids
// cannot bid after auction is ended
if (block.timestamp > listing.startTime + listing.duration) revert AuctionEnded();
// ensure amount being bid is greater than minimum next bid
if (amount < _calcNextBid(listing.highestBid)) revert BidTooLow();
}
// update auction, extending duration if needed
listing.highestBid = amount;
listing.highestBidder = msg.sender;
listing.recipient = recipient;
uint256 timeRemaining = listing.startTime + listing.duration - block.timestamp; // checks for being past auction end time avoid underflow issues here
if (timeRemaining < EXTENSION_TIME) {
listing.duration += EXTENSION_TIME - timeRemaining;
}
// save new listing items in storage
_listings[nftAddress][tokenId].highestBid = listing.highestBid;
_listings[nftAddress][tokenId].highestBidder = listing.highestBidder;
_listings[nftAddress][tokenId].recipient = listing.recipient;
if (_listings[nftAddress][tokenId].startTime != listing.startTime) {
_listings[nftAddress][tokenId].startTime = listing.startTime;
}
if (_listings[nftAddress][tokenId].duration != listing.duration) {
_listings[nftAddress][tokenId].duration = listing.duration;
}
// transfer funds as needed for the bid
if (listing.currencyAddress == address(0)) {
// ETH
// escrow msg.value
if (msg.value != amount) revert UnexpectedMsgValue();
} else {
// ERC-20
// make sure they didn't send any ETH along
if (msg.value != 0) revert UnexpectedMsgValue();
// escrow amount from sender (not recipient)
_safeTransferFromERC20(msg.sender, address(this), listing.currencyAddress, amount);
}
// return previous bid, if it's a subsequent bid
_payout(previousBidder, listing.currencyAddress, previousBid);
emit AuctionBid(msg.sender, nftAddress, tokenId, listing);
}
/// @notice Function to settle an auction
/// @dev Requirements
/// - can be called by anyone on the blockchain
/// - the listing must be configured as an auction
/// - the auction must have been started AND ended
/// - royalties are paid out on secondary sales, where the creator of the token is not the seller
/// @param nftAddress The nft contract address
/// @param tokenId The nft token id
function settleAuction(address nftAddress, uint256 tokenId) external whenNotPaused nonReentrant {
// cache data
Listing memory listing = _listings[nftAddress][tokenId];
// check to make sure the listing is the right type
if (listing.type_ == ListingType.NOT_CONFIGURED || listing.type_ == ListingType.BUY_NOW) {
revert InvalidListingType();
}
// check that auction was bid on
if (listing.highestBidder == address(0)) revert AuctionNotStarted();
// ensure auction is ended
if (block.timestamp <= listing.startTime + listing.duration) revert AuctionNotEnded();
// delete listing & auction
delete _listings[nftAddress][tokenId];
// settle up
_settleUp(
nftAddress,
tokenId,
listing.zeroProtocolFee,
listing.recipient,
listing.currencyAddress,
listing.seller,
listing.payoutReceiver,
listing.highestBid
);
emit AuctionSettled(msg.sender, nftAddress, tokenId, listing);
}
/// @notice Function to buy a token at a fixed price
/// @dev Requirements
/// - msg.sender and recipient cannot be sanctioned
/// - recipient cannot be the zero address
/// - listing must be configured as a reserve auction with a buy now price or just a buy now
/// - if it's an auction + buy now, the auction cannot be started
/// - the listing must be open
/// - royalties are paid out for secondary sales, where the creator of the token is not the seller
/// @param nftAddress The nft contract address
/// @param tokenId The nft token id
/// @param recipient The recipient that will receive the NFT if the bid is the winning bid
function buyNow(address nftAddress, uint256 tokenId, address recipient)
external
payable
whenNotPaused
nonReentrant
{
// check sender & recipient
_isSanctioned(msg.sender, true);
if (!_isValidRecipient(recipient)) revert InvalidRecipient();
// cache data
Listing memory listing = _listings[nftAddress][tokenId];
// check the listing type
if (
listing.type_ == ListingType.NOT_CONFIGURED || listing.type_ == ListingType.SCHEDULED_AUCTION
|| listing.type_ == ListingType.RESERVE_AUCTION
) {
revert InvalidListingType();
}
// cannot buy if an auction is live
if (listing.highestBidder != address(0)) revert AuctionStarted();
// cannot buy if prior to listing.openTime
if (block.timestamp < listing.openTime) revert CannotBuyYet();
// delete listing & auction
delete _listings[nftAddress][tokenId];
// handle funds transfer
if (listing.currencyAddress == address(0)) {
// ETH
// escrow msg.value
if (msg.value != listing.buyNowPrice) revert UnexpectedMsgValue();
} else {
// ERC-20
// make sure they didn't send any ETH along
if (msg.value != 0) revert UnexpectedMsgValue();
// escrow amount from sender (not recipient)
_safeTransferFromERC20(msg.sender, address(this), listing.currencyAddress, listing.buyNowPrice);
}
// settle up
_settleUp(
nftAddress,
tokenId,
listing.zeroProtocolFee,
recipient,
listing.currencyAddress,
listing.seller,
listing.payoutReceiver,
listing.buyNowPrice
);
emit BuyNowFulfilled(msg.sender, nftAddress, tokenId, recipient, listing);
}
///////////////////////////////////////////////////////////////////////////
/// ADMIN FUNCTIONS
///////////////////////////////////////////////////////////////////////////
/// @notice Function to set a new weth address
/// @dev Requires owner
/// @param newWethAddress The weth contract address
function setWethAddress(address newWethAddress) external onlyOwner {
address prevWethAddress = weth;
weth = newWethAddress;
emit WethUpdated(prevWethAddress, newWethAddress);
}
/// @notice Function to set the protocol fee settings
/// @dev Requires owner
/// @dev The new protocol fee bps must be out of `BASIS`
/// @param newProtocolFeeReceiver The new address to receive protocol fees
/// @param newProtocolFeeBps The new bps for the protocol fee
function setProtocolFeeSettings(address newProtocolFeeReceiver, uint256 newProtocolFeeBps) external onlyOwner {
if (!_isValidRecipient(newProtocolFeeReceiver)) revert InvalidRecipient();
if (newProtocolFeeBps > BASIS) revert InvalidProtocolFeeBps();
protocolFeeReceiver = newProtocolFeeReceiver;
protocolFeeBps = newProtocolFeeBps;
emit ProtocolFeeUpdated(newProtocolFeeReceiver, newProtocolFeeBps);
}
/// @notice Function to set the sanctions oracle
/// @dev Requires owner
/// @param newOracle The new sanctions oracle address (zero address disables)
function setSanctionsOracle(address newOracle) external onlyOwner {
_updateSanctionsOracle(newOracle);
}
/// @notice Function to update the creator lookup contract
/// @dev Requires owner
/// @param newCreatorLookupAddress The helper contract address for looking up a token creator
function setCreatorLookup(address newCreatorLookupAddress) external onlyOwner {
address prevCreatorLookup = address(creatorLookup);
creatorLookup = ICreatorLookup(newCreatorLookupAddress);
emit CreatorLookupUpdated(prevCreatorLookup, newCreatorLookupAddress);
}
/// @notice Function to update the royalty lookup contract
/// @dev Requires owner
/// @param newRoyaltyLookupAddress The helper contract address for looking up token royalties
function setRoyaltyLookup(address newRoyaltyLookupAddress) external onlyOwner {
address prevRoyaltyLookup = address(royaltyLookup);
royaltyLookup = IRoyaltyLookup(newRoyaltyLookupAddress);
emit RoyaltyLookupUpdated(prevRoyaltyLookup, newRoyaltyLookupAddress);
}
/// @notice Function to pause the contract
/// @dev Requires owner
/// @param status The boolean flag for the paused status
function pause(bool status) external onlyOwner {
if (status) {
_pause();
} else {
_unpause();
}
}
/// @notice Function to remove protocol fee from a specific listing
/// @dev Requires owner
/// @param nftAddress The nft contract address
/// @param tokenId The nft token id
function removeProtocolFee(address nftAddress, uint256 tokenId) external onlyOwner {
if (_listings[nftAddress][tokenId].type_ == ListingType.NOT_CONFIGURED) revert InvalidListingType();
_listings[nftAddress][tokenId].zeroProtocolFee = true;
}
///////////////////////////////////////////////////////////////////////////
/// VIEW FUNCTIONS
///////////////////////////////////////////////////////////////////////////
/// @notice Function to get a specific listing
/// @param nftAddress The nft contract address
/// @param tokenId The nft token id
function getListing(address nftAddress, uint256 tokenId) external view returns (Listing memory) {
Listing memory listing = _listings[nftAddress][tokenId];
return listing;
}
/// @notice Function to get the next bid amount for a token
/// @param nftAddress The nft contract address
/// @param tokenId The nft token id
function getNextBid(address nftAddress, uint256 tokenId) external view returns (uint256) {
Listing memory listing = _listings[nftAddress][tokenId];
return _calcNextBid(listing.highestBid);
}
/// @notice Function to understand if the sale is a primary or secondary sale
/// @param nftAddress The nft contract address
/// @param tokenId The nft token id
function getIfPrimarySale(address nftAddress, uint256 tokenId) external view returns (bool) {
Listing memory listing = _listings[nftAddress][tokenId];
return creatorLookup.getCreator(nftAddress, tokenId) == listing.seller;
}
/// @notice Function to get the royalty amount that will be paid to the creator
/// @param nftAddress The nft contract address
/// @param tokenId The nft token id
/// @param value The value to check against
function getRoyalty(address nftAddress, uint256 tokenId, uint256 value)
external
view
returns (address payable[] memory, uint256[] memory)
{
if (address(royaltyLookup).code.length == 0) return (new address payable[](0), new uint256[](0));
try royaltyLookup.getRoyaltyView(nftAddress, tokenId, value) returns (
address payable[] memory recipients, uint256[] memory amounts
) {
return (recipients, amounts);
} catch {
return (new address payable[](0), new uint256[](0));
}
}
///////////////////////////////////////////////////////////////////////////
/// HELPER FUNCTIONS
///////////////////////////////////////////////////////////////////////////
/// @notice Internal function to check if an nft recipient is valid
/// @dev Returns false if the recipient is sanctioned or if it is the zero address
function _isValidRecipient(address recipient) private view returns (bool) {
if (recipient == address(0)) return false;
if (_isSanctioned(recipient, false)) return false;
return true;
}
/// @notice Internal function to calculate the next bid price
/// @param currentBid The current bid
/// @return nextBid The next bid
function _calcNextBid(uint256 currentBid) private pure returns (uint256 nextBid) {
uint256 inc = currentBid * BID_INCREASE_BPS / BASIS;
if (inc == 0) {
return currentBid + 1;
} else {
return currentBid + inc;
}
}
/// @notice Internal function to abstract payouts when settling a listing
function _payout(address to, address currencyAddress, uint256 value) private {
if (to == address(0) || value == 0) return;
if (currencyAddress == address(0)) {
_safeTransferETH(to, value, weth);
} else {
_safeTransferERC20(to, currencyAddress, value);
}
}
/// @notice Internal function to settle a sale/Auction
function _settleUp(
address nftAddress,
uint256 tokenId,
bool zeroProtocolFee,
address recipient,
address currencyAddress,
address seller,
address payoutReceiver,
uint256 value
) private {
uint256 remainingValue = value;
// take protocol fee (if not zeroed by contract owner)
if (!zeroProtocolFee) {
uint256 protocolFee = value * protocolFeeBps / BASIS;
remainingValue -= protocolFee;
_payout(protocolFeeReceiver, currencyAddress, protocolFee);
}
// if secondary sale, payout royalties (seller is not the creator)
address creator = creatorLookup.getCreator(nftAddress, tokenId);
if (seller != creator && address(royaltyLookup).code.length > 0) {
// secondary sale
try royaltyLookup.getRoyalty(nftAddress, tokenId, remainingValue) returns (
address payable[] memory recipients, uint256[] memory amounts
) {
if (recipients.length == amounts.length) {
// payout if array lengths match
for (uint256 i = 0; i < recipients.length; ++i) {
if (_isSanctioned(recipients[i], false)) continue; // don't pay to sanctioned addresses
if (amounts[i] > remainingValue) break;
remainingValue -= amounts[i];
_payout(recipients[i], currencyAddress, amounts[i]);
}
}
} catch {
// do nothing if royalty lookup call fails
// this causes the coverage test to say a line is missing coverage
}
}
// pay remaining amount to payout receiver (set by the seller)
_payout(payoutReceiver, currencyAddress, remainingValue);
// transfer nft to recipient
IERC721(nftAddress).transferFrom(address(this), recipient, tokenId);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. 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;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
bool private _paused;
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {SafeERC20} from "@openzeppelin-contracts-5.0.2/token/ERC20/utils/SafeERC20.sol";
import {IWETH, IERC20} from "./IWETH.sol";
/// @title Transfer Helper
/// @notice Abstract contract that has helper function for sending ETH and ERC20's safely
/// @author transientlabs.xyz
/// @custom:version 3.0.0
abstract contract TransferHelper {
/*//////////////////////////////////////////////////////////////////////////
Types
//////////////////////////////////////////////////////////////////////////*/
using SafeERC20 for IERC20;
using SafeERC20 for IWETH;
/*//////////////////////////////////////////////////////////////////////////
Errors
//////////////////////////////////////////////////////////////////////////*/
/// @dev ETH transfer failed
error ETHTransferFailed();
/// @dev Transferred too few ERC-20 tokens
error InsufficentERC20Transfer();
/*//////////////////////////////////////////////////////////////////////////
ETH Functions
//////////////////////////////////////////////////////////////////////////*/
/// @notice Function to force transfer ETH, defaulting to forwarding 100k gas
/// @dev On failure to send the ETH, the ETH is converted to WETH and sent
/// @dev Care should be taken to always pass the proper WETH address that adheres to IWETH
/// @param recipient The recipient of the ETH
/// @param amount The amount of ETH to send
/// @param weth The WETH token address
function _safeTransferETH(address recipient, uint256 amount, address weth) internal {
_safeTransferETH(recipient, amount, weth, 1e5);
}
/// @notice Function to force transfer ETH, with a gas limit
/// @dev On failure to send the ETH, the ETH is converted to WETH and sent
/// @dev Care should be taken to always pass the proper WETH address that adheres to IWETH
/// @dev If the `amount` is zero, the function returns in order to save gas
/// @param recipient The recipient of the ETH
/// @param amount The amount of ETH to send
/// @param weth The WETH token address
/// @param gasLimit The gas to forward
function _safeTransferETH(address recipient, uint256 amount, address weth, uint256 gasLimit) internal {
if (amount == 0) return;
(bool success,) = recipient.call{value: amount, gas: gasLimit}("");
if (!success) {
IWETH token = IWETH(weth);
token.deposit{value: amount}();
token.safeTransfer(recipient, amount);
}
}
/*//////////////////////////////////////////////////////////////////////////
ERC-20 Functions
//////////////////////////////////////////////////////////////////////////*/
/// @notice Function to safely transfer ERC-20 tokens from the contract, without checking for token tax
/// @dev Does not check if the sender has enough balance as that is handled by the token contract
/// @dev Does not check for token tax as that could lock up funds in the contract
/// @dev Reverts on failure to transfer
/// @dev If the `amount` is zero, the function returns in order to save gas
/// @param recipient The recipient of the ERC-20 token
/// @param currency The address of the ERC-20 token
/// @param amount The amount of ERC-20 to send
function _safeTransferERC20(address recipient, address currency, uint256 amount) internal {
if (amount == 0) return;
IERC20(currency).safeTransfer(recipient, amount);
}
/// @notice Function to safely transfer ERC-20 tokens from another address to a recipient
/// @dev Does not check if the sender has enough balance or allowance for this contract as that is handled by the token contract
/// @dev Reverts on failure to transfer
/// @dev Reverts if there is a token tax taken out
/// @dev Returns and doesn't do anything if the sender and recipient are the same address
/// @dev If the `amount` is zero, the function returns in order to save gas
/// @param sender The sender of the tokens
/// @param recipient The recipient of the ERC-20 token
/// @param currency The address of the ERC-20 token
/// @param amount The amount of ERC-20 to send
function _safeTransferFromERC20(address sender, address recipient, address currency, uint256 amount) internal {
if (amount == 0) return;
if (sender == recipient) return;
IERC20 token = IERC20(currency);
uint256 intialBalance = token.balanceOf(recipient);
token.safeTransferFrom(sender, recipient, amount);
uint256 finalBalance = token.balanceOf(recipient);
if (finalBalance - intialBalance < amount) revert InsufficentERC20Transfer();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {IChainalysisSanctionsOracle} from "./IChainalysisSanctionsOracle.sol";
/// @title Sanctions Compliance
/// @notice Abstract contract to comply with U.S. sanctioned addresses
/// @dev Uses the Chainalysis Sanctions Oracle for checking sanctions
/// @author transientlabs.xyz
/// @custom:version 3.0.0
contract SanctionsCompliance {
/*//////////////////////////////////////////////////////////////////////////
State Variables
//////////////////////////////////////////////////////////////////////////*/
IChainalysisSanctionsOracle public oracle;
/*//////////////////////////////////////////////////////////////////////////
Errors
//////////////////////////////////////////////////////////////////////////*/
/// @dev Sanctioned address by OFAC
error SanctionedAddress();
/*//////////////////////////////////////////////////////////////////////////
Events
//////////////////////////////////////////////////////////////////////////*/
event SanctionsOracleUpdated(address indexed prevOracle, address indexed newOracle);
/*//////////////////////////////////////////////////////////////////////////
Constructor
//////////////////////////////////////////////////////////////////////////*/
constructor(address initOracle) {
_updateSanctionsOracle(initOracle);
}
/*//////////////////////////////////////////////////////////////////////////
Internal Functions
//////////////////////////////////////////////////////////////////////////*/
/// @notice Internal function to change the sanctions oracle
/// @param newOracle The new sanctions oracle address
function _updateSanctionsOracle(address newOracle) internal {
address prevOracle = address(oracle);
oracle = IChainalysisSanctionsOracle(newOracle);
emit SanctionsOracleUpdated(prevOracle, newOracle);
}
/// @notice Internal function to check the sanctions oracle for an address
/// @dev Disable sanction checking by setting the oracle to the zero address
/// @param sender The address that is trying to send money
/// @param shouldRevertIfSanctioned A flag indicating if the call should revert if the sender is sanctioned. Set to false if wanting to get a result.
/// @return isSanctioned Boolean indicating if the sender is sanctioned
function _isSanctioned(address sender, bool shouldRevertIfSanctioned) internal view returns (bool isSanctioned) {
if (address(oracle) == address(0)) {
return false;
}
isSanctioned = oracle.isSanctioned(sender);
if (shouldRevertIfSanctioned && isSanctioned) revert SanctionedAddress();
return isSanctioned;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;
enum ListingType {
NOT_CONFIGURED,
SCHEDULED_AUCTION,
RESERVE_AUCTION,
RESERVE_AUCTION_PLUS_BUY_NOW,
BUY_NOW
}
/// @dev The Listing struct contains general information about the sale on the auction house,
/// such as the type of sale, seller, currency, when the listing opens, and the pricing mechanics (based on type)
struct Listing {
ListingType type_;
bool zeroProtocolFee;
address seller;
address payoutReceiver;
address currencyAddress;
uint256 openTime;
uint256 reservePrice;
uint256 buyNowPrice;
uint256 startTime;
uint256 duration;
address recipient;
address highestBidder;
uint256 highestBid;
uint256 id;
}
interface ITLAuctionHouseEvents {
event WethUpdated(address indexed prevWeth, address indexed newWeth);
event ProtocolFeeUpdated(address indexed newProtocolFeeReceiver, uint256 indexed newProtocolFee);
event CreatorLookupUpdated(address indexed prevCreatorLookup, address indexed newCreatorLookup);
event RoyaltyLookupUpdated(address indexed prevRoyaltyLookup, address indexed newRoyaltyLookup);
event ListingConfigured(
address indexed sender, address indexed nftAddress, uint256 indexed tokenId, Listing listing
);
event ListingCanceled(address indexed sender, address indexed nftAddress, uint256 indexed tokenId, Listing listing);
event AuctionBid(address indexed sender, address indexed nftAddress, uint256 indexed tokenId, Listing listing);
event AuctionSettled(address indexed sender, address indexed nftAddress, uint256 indexed tokenId, Listing listing);
event BuyNowFulfilled(
address indexed sender, address indexed nftAddress, uint256 indexed tokenId, address recipient, Listing listing
);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;
/// @title ICreatorLookup.sol
/// @notice Interface for the creator lookup helper contracts that help the TLAuctionHouse determine a primary from secondary sale
/// @author transientlabs.xyz
interface ICreatorLookup {
/// @notice Function to lookup the creator address for a given token
/// @dev Should return the null address if the creator can't be determined
function getCreator(address nftAddress, uint256 tokenId) external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.22;
/// @title IRoyaltyLookup.sol
/// @notice Interface for royalty lookup helper contracts that help the TLAuctionHouse determine the royalty to pay
/// @author transientlabs.xyz
interface IRoyaltyLookup {
/// @notice Function to lookup the creator address for a given token
/// @dev Should attempt to use the royalty registry under the hood where possible
function getRoyalty(address nftAddress, uint256 tokenId, uint256 value)
external
returns (address payable[] memory recipients, uint256[] memory amounts);
/// @notice Funciton to lookup the creator address for a given token, but only in a read-only view
/// @dev Should attempt to use the royalty registry under the hood where possible
function getRoyaltyView(address nftAddress, uint256 tokenId, uint256 value)
external
view
returns (address payable[] memory recipients, uint256[] memory amounts);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {IERC20} from "@openzeppelin-contracts-5.0.2/token/ERC20/IERC20.sol";
interface IWETH is IERC20 {
function deposit() external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IChainalysisSanctionsOracle {
function isSanctioned(address addr) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}{
"remappings": [
"forge-std-1.9.4/=dependencies/forge-std-1.9.4/src/",
"tl-creator-contracts-3.3.1/=dependencies/tl-creator-contracts-3.3.1/src/",
"@manifoldxyz/libraries-solidity/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/royalty-registry-solidity-1.0.0/lib/libraries-solidity/",
"@openzeppelin-contracts-5.0.2/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/@openzeppelin-contracts-5.0.2/",
"@openzeppelin-contracts-upgradeable-5.0.2/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/@openzeppelin-contracts-upgradeable-5.0.2/",
"@openzeppelin/contracts/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/@openzeppelin-contracts-5.0.2/",
"create2-helpers/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/royalty-registry-solidity-1.0.0/lib/create2-helpers/",
"create2-scripts/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/royalty-registry-solidity-1.0.0/lib/create2-helpers/script/",
"ds-test/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/royalty-registry-solidity-1.0.0/lib/forge-std/lib/ds-test/src/",
"forge-std/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/royalty-registry-solidity-1.0.0/lib/forge-std/src/",
"libraries-solidity/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/royalty-registry-solidity-1.0.0/lib/libraries-solidity/contracts/",
"openzeppelin-contracts-upgradeable/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/royalty-registry-solidity-1.0.0/lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/royalty-registry-solidity-1.0.0/lib/openzeppelin-contracts/",
"royalty-registry-solidity-1.0.0/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/dependencies/royalty-registry-solidity-1.0.0/contracts/",
"tl-sol-tools-3.1.4/=dependencies/tl-creator-contracts-3.3.1/dependencies/tl-sol-tools-3.1.4/src/"
],
"optimizer": {
"enabled": true,
"runs": 20000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"initOwner","type":"address"},{"internalType":"address","name":"initSanctionsOracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AuctionEnded","type":"error"},{"inputs":[],"name":"AuctionNotEnded","type":"error"},{"inputs":[],"name":"AuctionNotStarted","type":"error"},{"inputs":[],"name":"AuctionStarted","type":"error"},{"inputs":[],"name":"BidTooLow","type":"error"},{"inputs":[],"name":"CannotBidYet","type":"error"},{"inputs":[],"name":"CannotBuyYet","type":"error"},{"inputs":[],"name":"ETHTransferFailed","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InsufficentERC20Transfer","type":"error"},{"inputs":[],"name":"InvalidListingType","type":"error"},{"inputs":[],"name":"InvalidProtocolFeeBps","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"ListingNotSetup","type":"error"},{"inputs":[],"name":"NotSeller","type":"error"},{"inputs":[],"name":"NotTokenOwner","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"SanctionedAddress","type":"error"},{"inputs":[],"name":"TokenNotTransferred","type":"error"},{"inputs":[],"name":"UnexpectedMsgValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"enum ListingType","name":"type_","type":"uint8"},{"internalType":"bool","name":"zeroProtocolFee","type":"bool"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"address","name":"payoutReceiver","type":"address"},{"internalType":"address","name":"currencyAddress","type":"address"},{"internalType":"uint256","name":"openTime","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"uint256","name":"buyNowPrice","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint256","name":"highestBid","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"indexed":false,"internalType":"struct Listing","name":"listing","type":"tuple"}],"name":"AuctionBid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"enum ListingType","name":"type_","type":"uint8"},{"internalType":"bool","name":"zeroProtocolFee","type":"bool"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"address","name":"payoutReceiver","type":"address"},{"internalType":"address","name":"currencyAddress","type":"address"},{"internalType":"uint256","name":"openTime","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"uint256","name":"buyNowPrice","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint256","name":"highestBid","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"indexed":false,"internalType":"struct Listing","name":"listing","type":"tuple"}],"name":"AuctionSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"components":[{"internalType":"enum ListingType","name":"type_","type":"uint8"},{"internalType":"bool","name":"zeroProtocolFee","type":"bool"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"address","name":"payoutReceiver","type":"address"},{"internalType":"address","name":"currencyAddress","type":"address"},{"internalType":"uint256","name":"openTime","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"uint256","name":"buyNowPrice","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint256","name":"highestBid","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"indexed":false,"internalType":"struct Listing","name":"listing","type":"tuple"}],"name":"BuyNowFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevCreatorLookup","type":"address"},{"indexed":true,"internalType":"address","name":"newCreatorLookup","type":"address"}],"name":"CreatorLookupUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"enum ListingType","name":"type_","type":"uint8"},{"internalType":"bool","name":"zeroProtocolFee","type":"bool"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"address","name":"payoutReceiver","type":"address"},{"internalType":"address","name":"currencyAddress","type":"address"},{"internalType":"uint256","name":"openTime","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"uint256","name":"buyNowPrice","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint256","name":"highestBid","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"indexed":false,"internalType":"struct Listing","name":"listing","type":"tuple"}],"name":"ListingCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"enum ListingType","name":"type_","type":"uint8"},{"internalType":"bool","name":"zeroProtocolFee","type":"bool"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"address","name":"payoutReceiver","type":"address"},{"internalType":"address","name":"currencyAddress","type":"address"},{"internalType":"uint256","name":"openTime","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"uint256","name":"buyNowPrice","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint256","name":"highestBid","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"indexed":false,"internalType":"struct Listing","name":"listing","type":"tuple"}],"name":"ListingConfigured","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":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newProtocolFeeReceiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"newProtocolFee","type":"uint256"}],"name":"ProtocolFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevRoyaltyLookup","type":"address"},{"indexed":true,"internalType":"address","name":"newRoyaltyLookup","type":"address"}],"name":"RoyaltyLookupUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevOracle","type":"address"},{"indexed":true,"internalType":"address","name":"newOracle","type":"address"}],"name":"SanctionsOracleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevWeth","type":"address"},{"indexed":true,"internalType":"address","name":"newWeth","type":"address"}],"name":"WethUpdated","type":"event"},{"inputs":[],"name":"BASIS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BID_INCREASE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXTENSION_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"bid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"buyNow","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"creatorLookup","outputs":[{"internalType":"contract ICreatorLookup","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"delist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getIfPrimarySale","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getListing","outputs":[{"components":[{"internalType":"enum ListingType","name":"type_","type":"uint8"},{"internalType":"bool","name":"zeroProtocolFee","type":"bool"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"address","name":"payoutReceiver","type":"address"},{"internalType":"address","name":"currencyAddress","type":"address"},{"internalType":"uint256","name":"openTime","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"uint256","name":"buyNowPrice","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"highestBidder","type":"address"},{"internalType":"uint256","name":"highestBid","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"internalType":"struct Listing","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getNextBid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"getRoyalty","outputs":[{"internalType":"address payable[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"enum ListingType","name":"type_","type":"uint8"},{"internalType":"address","name":"payoutReceiver","type":"address"},{"internalType":"address","name":"currencyAddress","type":"address"},{"internalType":"uint256","name":"openTime","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"uint256","name":"auctionDuration","type":"uint256"},{"internalType":"uint256","name":"buyNowPrice","type":"uint256"}],"name":"list","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IChainalysisSanctionsOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"removeProtocolFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"royaltyLookup","outputs":[{"internalType":"contract IRoyaltyLookup","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newCreatorLookupAddress","type":"address"}],"name":"setCreatorLookup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newProtocolFeeReceiver","type":"address"},{"internalType":"uint256","name":"newProtocolFeeBps","type":"uint256"}],"name":"setProtocolFeeSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRoyaltyLookupAddress","type":"address"}],"name":"setRoyaltyLookup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOracle","type":"address"}],"name":"setSanctionsOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWethAddress","type":"address"}],"name":"setWethAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"settleAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b5060405162003bfd38038062003bfd833981016040819052620000349162000155565b80826001600160a01b0381166200006557604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b620000708162000096565b506000805460ff60a01b19169055600180556200008d81620000e6565b5050506200018d565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f9dc7a30661b0eef899195a36c42f80a98cafd90e68cd8a50af361f2b04916dbf90600090a35050565b80516001600160a01b03811681146200015057600080fd5b919050565b600080604083850312156200016957600080fd5b620001748362000138565b9150620001846020840162000138565b90509250929050565b613a60806200019d6000396000f3fe6080604052600436106101cd5760003560e01c8063825c7d10116100f7578063b567858811610095578063f074258e11610064578063f074258e14610519578063f2fde38b14610539578063f533b80214610559578063ffa1ad741461058757600080fd5b8063b5678588146104a6578063c7e3efe3146104b9578063d47e13bb146104d9578063df9efd7f146104f957600080fd5b80638da5cb5b116100d15780638da5cb5b146104285780639b14eb5b146104465780639ddd898214610466578063a96e24231461048657600080fd5b8063825c7d10146103bb578063866f5943146103db57806388700d1c146103fb57600080fd5b80635138b08c1161016f57806365f3952b1161013e57806365f3952b14610346578063715018a61461036657806372582b481461037b5780637dc0d1d01461039b57600080fd5b80635138b08c146102be578063528cfa98146102de5780635681104a146102f45780635c975abb1461030a57600080fd5b806326939c15116101ab57806326939c151461023057806335659fb81461025057806339a51be5146102665780633fc8cef31461029e57600080fd5b806302329a29146101d2578063049fefbe146101f45780631bd859e11461021d575b600080fd5b3480156101de57600080fd5b506101f26101ed366004613290565b6105dd565b005b34801561020057600080fd5b5061020a6101f481565b6040519081526020015b60405180910390f35b6101f261022b3660046132c2565b6105fe565b34801561023c57600080fd5b506101f261024b366004613304565b610a42565b34801561025c57600080fd5b5061020a60055481565b34801561027257600080fd5b50600454610286906001600160a01b031681565b6040516001600160a01b039091168152602001610214565b3480156102aa57600080fd5b50600654610286906001600160a01b031681565b3480156102ca57600080fd5b506101f26102d9366004613304565b610b08565b3480156102ea57600080fd5b5061020a61271081565b34801561030057600080fd5b5061020a61012c81565b34801561031657600080fd5b5060005474010000000000000000000000000000000000000000900460ff165b6040519015158152602001610214565b34801561035257600080fd5b506101f2610361366004613330565b610e6c565b34801561037257600080fd5b506101f2611416565b34801561038757600080fd5b5061020a610396366004613304565b61142a565b3480156103a757600080fd5b50600254610286906001600160a01b031681565b3480156103c757600080fd5b506101f26103d6366004613304565b61154a565b3480156103e757600080fd5b50600754610286906001600160a01b031681565b34801561040757600080fd5b5061041b610416366004613304565b611638565b6040516102149190613517565b34801561043457600080fd5b506000546001600160a01b0316610286565b34801561045257600080fd5b506101f2610461366004613526565b6117ab565b34801561047257600080fd5b506101f2610481366004613526565b61181d565b34801561049257600080fd5b506101f26104a1366004613526565b61182e565b6101f26104b4366004613543565b6118a0565b3480156104c557600080fd5b506101f26104d4366004613526565b611edd565b3480156104e557600080fd5b50600854610286906001600160a01b031681565b34801561050557600080fd5b50610336610514366004613304565b611f4f565b34801561052557600080fd5b506101f2610534366004613304565b6120fe565b34801561054557600080fd5b506101f2610554366004613526565b61243e565b34801561056557600080fd5b5061057961057436600461358b565b612497565b6040516102149291906135c0565b34801561059357600080fd5b506105d06040518060400160405280600581526020017f322e362e3100000000000000000000000000000000000000000000000000000081525081565b6040516102149190613668565b6105e56125bf565b80156105f6576105f3612605565b50565b6105f3612691565b6106066126e8565b61060e61273d565b610619336001612780565b5061062381612865565b610659576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815260096020908152604080832085845290915280822081516101c081019092528054829060ff16600481111561069f5761069f6133bf565b60048111156106b0576106b06133bf565b8152815460ff61010080830491909116151560208401526001600160a01b036201000090920482166040840152600184015482166060840152600284015482166080840152600384015460a0840152600484015460c0840152600584015460e0840152600684015490830152600783015461012083015260088301548116610140830152600983015416610160820152600a820154610180820152600b909101546101a090910152905060008151600481111561076f5761076f6133bf565b148061078d575060018151600481111561078b5761078b6133bf565b145b806107aa57506002815160048111156107a8576107a86133bf565b145b156107e1576040517fe9184ea200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101608101516001600160a01b031615610827576040517fc8f99b9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060a00151421015610865576040517ff76338d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038085166000908152600960208181526040808420888552909152822080547fffffffffffffffffffff000000000000000000000000000000000000000000001681556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600282018054821690556003820184905560048201849055600582018490556006820184905560078201849055600882018054821690559181018054909216909155600a8101829055600b0155608082015116610975578060e001513414610970576040517fbd28e88900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c1565b34156109ad576040517fbd28e88900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c1333083608001518460e0015161289d565b6109e584848360200151858560800151866040015187606001518860e00151612a31565b82846001600160a01b0316336001600160a01b03167f19fa05c932bb0a66ab6522bdf2bda21ca0eeeb678dfc19839b0371622f744a548585604051610a2b9291906136b9565b60405180910390a450610a3d60018055565b505050565b610a4a6125bf565b6001600160a01b038216600090815260096020908152604080832084845290915281205460ff166004811115610a8257610a826133bf565b03610ab9576040517fe9184ea200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0390911660009081526009602090815260408083209383529290522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b610b106126e8565b610b1861273d565b6001600160a01b038216600090815260096020908152604080832084845290915280822081516101c081019092528054829060ff166004811115610b5e57610b5e6133bf565b6004811115610b6f57610b6f6133bf565b8152815460ff61010080830491909116151560208401526001600160a01b036201000090920482166040840152600184015482166060840152600284015482166080840152600384015460a0840152600484015460c0840152600584015460e0840152600684015490830152600783015461012083015260088301548116610140830152600983015416610160820152600a820154610180820152600b909101546101a0909101529050600081516004811115610c2e57610c2e6133bf565b1480610c4c5750600481516004811115610c4a57610c4a6133bf565b145b15610c83576040517fe9184ea200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101608101516001600160a01b0316610cc8576040517feffaea8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806101200151816101000151610cde9190613706565b4211610d16576040517f6463738900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0383166000908152600960208181526040808420868552825280842080547fffffffffffffffffffff000000000000000000000000000000000000000000001681556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600282018054821690556003820186905560048201869055600582018690556006820186905560078201869055600882018054821690559381018054909416909355600a8301849055600b90920192909255908201516101408301516080840151928401516060850151610180860151610e129589958995909490939192909190612a31565b81836001600160a01b0316336001600160a01b03167fc52e7ef6df45fb1214ab4d4798bd31974d9b0afbb2667144d6932ddfb1a03ac884604051610e569190613517565b60405180910390a450610e6860018055565b5050565b610e746126e8565b610e7c61273d565b610e87336001612780565b50610e93866001612780565b506040517f6352211e00000000000000000000000000000000000000000000000000000000815260048101899052899033906001600160a01b03831690636352211e90602401602060405180830381865afa158015610ef6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1a9190613719565b6001600160a01b031614610f5a576040517f59dc379f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42851015610f66574294505b6000600360008154610f7790613736565b91905081905590506000604051806101c001604052808b6004811115610f9f57610f9f6133bf565b81526000602082018190523360408301526001600160a01b038c811660608401528b16608083015260a082018a905260c0820189905260e0820187905261010082018190526101208201889052610140820181905261016082018190526101808201526101a001839052905060018a600481111561101f5761101f6133bf565b03611038576101008101879052600060e08201526110d5565b60028a600481111561104c5761104c6133bf565b0361105d57600060e08201526110d5565b60038a6004811115611071576110716133bf565b146110d55760048a600481111561108a5761108a6133bf565b036110a357600060c082018190526101208201526110d5565b6040517fe9184ea200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038c1660009081526009602090815260408083208e84529091529020815181548392919082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836004811115611138576111386133bf565b0217905550602082015181546040808501517fffffffffffffffffffff000000000000000000000000000000000000000000ff90921661010093151584027fffffffffffffffffffff0000000000000000000000000000000000000000ffff1617620100006001600160a01b039384160217845560608501516001850180547fffffffffffffffffffffffff00000000000000000000000000000000000000009081169285169290921790556080860151600286018054831691851691909117905560a0860151600386015560c086015160048087019190915560e0870151600587015593860151600686015561012086015160078601556101408601516008860180548316918516919091179055610160860151600986018054909216908416179055610180850151600a8501556101a090940151600b9093019290925591517f23b872dd0000000000000000000000000000000000000000000000000000000081523392810192909252306024830152604482018d90528416906323b872dd90606401600060405180830381600087803b1580156112d757600080fd5b505af11580156112eb573d6000803e3d6000fd5b50506040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018e90523092506001600160a01b0386169150636352211e90602401602060405180830381865afa15801561134f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113739190613719565b6001600160a01b0316146113b3576040517f93ac15de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a8c6001600160a01b0316336001600160a01b03167fd63da9eb66a685346e9841fa559fa2b364689ef42cf9d5a84942f5d2fbc5b6dc846040516113f79190613517565b60405180910390a450505061140b60018055565b505050505050505050565b61141e6125bf565b6114286000612d5c565b565b6001600160a01b038216600090815260096020908152604080832084845290915280822081516101c08101909252805483929190829060ff166004811115611474576114746133bf565b6004811115611485576114856133bf565b8152815460ff61010080830491909116151560208401526001600160a01b036201000090920482166040840152600184015482166060840152600284015482166080840152600384015460a0840152600484015460c0840152600584015460e0840152600684015490830152600783015461012083015260088301548116610140830152600983015416610160820152600a82015461018080830191909152600b909201546101a09091015281015190915061154090612dc4565b9150505b92915050565b6115526125bf565b61155b82612865565b611591576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127108111156115cd576040517fa535919f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03841690811790915560058290556040518291907f389f6e01d911ce2a6919bdcf4e57d270003243ca9c54e7911454a70f89aee19e90600090a35050565b604080516101c0808201835260008083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e08401829052610100840182905261012084018290526101408401829052610160840182905261018084018290526101a084018290526001600160a01b03871682526009815284822086835290528381208451928301909452835492939092829060ff1660048111156116e9576116e96133bf565b60048111156116fa576116fa6133bf565b8152815460ff61010080830491909116151560208401526001600160a01b036201000090920482166040840152600184015482166060840152600284015482166080840152600384015460a0840152600484015460c0840152600584015460e0840152600684015490830152600783015461012083015260088301548116610140830152600983015416610160820152600a820154610180820152600b909101546101a09091015291505092915050565b6117b36125bf565b600780546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907fd0e4e983667a08a1813ab08b3dcf5fc3bd3f6f66ccf1d9f6a317369dfb6df6e090600090a35050565b6118256125bf565b6105f381612e06565b6118366125bf565b600680546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907fdfc4c08fb23afd3ed9497c154a48cb9a7eb5e5ef2307e641ec9faef507d4e38a90600090a35050565b6118a86126e8565b6118b061273d565b6118bb336001612780565b506118c582612865565b6118fb576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038416600090815260096020908152604080832086845290915280822081516101c081019092528054829060ff166004811115611941576119416133bf565b6004811115611952576119526133bf565b8152815460ff61010080830491909116151560208401526001600160a01b036201000090920482166040840152600184015482166060840152600284015482166080840152600384015460a0840152600484015460c0840152600584015460e084015260068401549083015260078301546101208301526008830154811661014083015260098301541661016080830191909152600a83015461018080840191909152600b909301546101a090920191909152908201519082015191925090600083516004811115611a2657611a266133bf565b1480611a445750600483516004811115611a4257611a426133bf565b145b15611a7b576040517fe9184ea200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a00151421015611ab9576040517fb722c5a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116611bb3578260c00151841015611b05576040517fa0d26eb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600283516004811115611b1a57611b1a6133bf565b1480611b385750600383516004811115611b3657611b366133bf565b145b15611b4557426101008401525b600183516004811115611b5a57611b5a6133bf565b03611bae57826101200151836101000151611b759190613706565b421115611bae576040517fa0e9298400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c49565b826101200151836101000151611bc99190613706565b421115611c02576040517fa0e9298400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c10836101800151612dc4565b841015611c49576040517fa0d26eb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101808301849052336101608401526001600160a01b0385166101408401526101208301516101008401516000914291611c839190613706565b611c8d919061376e565b905061012c811015611cbb57611ca58161012c61376e565b8461012001818151611cb79190613706565b9052505b6101808401516001600160a01b0389811660009081526009602081815260408084208d8552909152909120600a81019390935561016087015190830180549183167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617905561014087015160088401805491909316911617905561010085015160069091015414611d77576101008401516001600160a01b03891660009081526009602090815260408083208b84529091529020600601555b6101208401516001600160a01b03891660009081526009602090815260408083208b845290915290206007015414611dd7576101208401516001600160a01b03891660009081526009602090815260408083208b84529091529020600701555b60808401516001600160a01b0316611e2757843414611e22576040517fbd28e88900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e6f565b3415611e5f576040517fbd28e88900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e6f333086608001518861289d565b611e7e82856080015185612e70565b86886001600160a01b0316336001600160a01b03167fec3d0c3ed87fd441707a880ed0b47c57cb0df7d321cc44199fb96a012bbbfd8d87604051611ec29190613517565b60405180910390a450505050611ed760018055565b50505050565b611ee56125bf565b600880546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f5ec630642fcf2e8cf5a0935fd70f1a00c37521eb7758bbbf5ae3155c59fe9cc790600090a35050565b6001600160a01b038216600090815260096020908152604080832084845290915280822081516101c08101909252805483929190829060ff166004811115611f9957611f996133bf565b6004811115611faa57611faa6133bf565b8152815461010080820460ff1615156020840152620100009091046001600160a01b03908116604080850191909152600185015482166060850152600285015482166080850152600385015460a085015260048086015460c0860152600586015460e08601526006860154938501939093526007808601546101208601526008860154831661014086015260098601548316610160860152600a860154610180860152600b909501546101a09094019390935284830151935492517f748690890000000000000000000000000000000000000000000000000000000081528982169281019290925260248201889052939450918316921690637486908990604401602060405180830381865afa1580156120c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ec9190613719565b6001600160a01b031614949350505050565b6121066126e8565b61210e61273d565b6001600160a01b038216600090815260096020908152604080832084845290915280822081516101c0810190925280548593929190829060ff166004811115612159576121596133bf565b600481111561216a5761216a6133bf565b8152815461010080820460ff1615156020840152620100009091046001600160a01b03908116604080850191909152600185015482166060850152600285015482166080850152600385015460a0850152600485015460c0850152600585015460e085015260068501549284019290925260078401546101208401526008840154811661014084015260098401548116610160840152600a840154610180840152600b909301546101a09092019190915282015191925016331461225a576040517f5ec8235100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101608101516001600160a01b0316156122a0576040517fc8f99b9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03848116600090815260096020818152604080842088855290915280832080547fffffffffffffffffffff000000000000000000000000000000000000000000001681556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600282018054821690556003820185905560048083018690556005830186905560068301869055600783018690556008830180548316905593820180549091169055600a8101849055600b01929092558382015191517f23b872dd0000000000000000000000000000000000000000000000000000000081523091810191909152908216602482015260448101859052908316906323b872dd90606401600060405180830381600087803b1580156123cf57600080fd5b505af11580156123e3573d6000803e3d6000fd5b5050505082846001600160a01b0316336001600160a01b03167f50d73552a7c03b8dc819baed087a15a97fe6abdc907b7a06e4bb0e300712395d8460405161242b9190613517565b60405180910390a45050610e6860018055565b6124466125bf565b6001600160a01b03811661248e576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024015b60405180910390fd5b6105f381612d5c565b60085460609081906001600160a01b03163b6000036124f65760005b6040519080825280602002602001820160405280156124dc578160200160208202803683370190505b5060408051600081526020810190915290925090506125b7565b6008546040517f3e1040140000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152602482018790526044820186905290911690633e10401490606401600060405180830381865afa9250505080156125a657506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526125a39190810190613892565b60015b6125b15760006124b3565b90925090505b935093915050565b6000546001600160a01b03163314611428576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401612485565b61260d6126e8565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586126743390565b6040516001600160a01b03909116815260200160405180910390a1565b612699612ec0565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612674565b60005474010000000000000000000000000000000000000000900460ff1615611428576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260015403612779576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b6002546000906001600160a01b031661279b57506000611544565b6002546040517fdf592f7d0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301529091169063df592f7d90602401602060405180830381865afa1580156127fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128229190613957565b905081801561282e5750805b15611544576040517f2e70c0b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001600160a01b03821661287d57506000919050565b612888826000612780565b1561289557506000919050565b506001919050565b8015611ed757826001600160a01b0316846001600160a01b03160315611ed7576040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015283916000918316906370a0823190602401602060405180830381865afa158015612921573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129459190613974565b905061295c6001600160a01b038316878786612f14565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152600091908416906370a0823190602401602060405180830381865afa1580156129bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e39190613974565b9050836129f0838361376e565b1015612a28576040517f35bfbdb000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b8086612a7c57600061271060055484612a4a919061398d565b612a5491906139a4565b9050612a60818361376e565b600454909250612a7a906001600160a01b03168783612e70565b505b6007546040517f748690890000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b90526000921690637486908990604401602060405180830381865afa158015612ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0b9190613719565b9050806001600160a01b0316856001600160a01b031614158015612b3a57506008546001600160a01b03163b15155b15612cc4576008546040517ff533b8020000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c9052604482018590529091169063f533b802906064016000604051808303816000875af1925050508015612bf157506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612bee9190810190613892565b60015b15612cc4578051825103612cc15760005b8251811015612cbf57612c2f838281518110612c2057612c206139df565b60200260200101516000612780565b612cb75784828281518110612c4657612c466139df565b602002602001015111612cbf57818181518110612c6557612c656139df565b602002602001015185612c78919061376e565b9450612cb7838281518110612c8f57612c8f6139df565b60200260200101518a848481518110612caa57612caa6139df565b6020026020010151612e70565b600101612c02565b505b50505b612ccf848784612e70565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038881166024830152604482018b90528b16906323b872dd90606401600060405180830381600087803b158015612d3857600080fd5b505af1158015612d4c573d6000803e3d6000fd5b5050505050505050505050505050565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080612710612dd66101f48561398d565b612de091906139a4565b905080600003612dfc57612df5836001613706565b9392505050565b612df58184613706565b600280546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f9dc7a30661b0eef899195a36c42f80a98cafd90e68cd8a50af361f2b04916dbf90600090a35050565b6001600160a01b0383161580612e84575080155b15612e8e57505050565b6001600160a01b038216612eb557600654610a3d90849083906001600160a01b0316612f90565b610a3d838383612f9f565b60005474010000000000000000000000000000000000000000900460ff16611428576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038481166024830152838116604483015260648201839052611ed79186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612fc0565b610a3d838383620186a061303c565b80600003612fac57505050565b610a3d6001600160a01b0383168483613118565b6000612fd56001600160a01b03841683613149565b90508051600014158015612ffa575080806020019051810190612ff89190613957565b155b15610a3d576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401612485565b8215611ed7576000846001600160a01b0316848390604051600060405180830381858888f193505050503d8060008114613092576040519150601f19603f3d011682016040523d82523d6000602084013e613097565b606091505b5050905080613111576000839050806001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b1580156130e057600080fd5b505af11580156130f4573d6000803e3d6000fd5b5061310f935050506001600160a01b03831690508787613118565b505b5050505050565b6040516001600160a01b03838116602483015260448201839052610a3d91859182169063a9059cbb90606401612f49565b6060612df58383600084600080856001600160a01b0316848660405161316f9190613a0e565b60006040518083038185875af1925050503d80600081146131ac576040519150601f19603f3d011682016040523d82523d6000602084013e6131b1565b606091505b50915091506131c18683836131cb565b9695505050505050565b6060826131e0576131db82613240565b612df5565b81511580156131f757506001600160a01b0384163b155b15613239576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401612485565b5080612df5565b8051156132505780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80151581146105f357600080fd5b6000602082840312156132a257600080fd5b8135612df581613282565b6001600160a01b03811681146105f357600080fd5b6000806000606084860312156132d757600080fd5b83356132e2816132ad565b92506020840135915060408401356132f9816132ad565b809150509250925092565b6000806040838503121561331757600080fd5b8235613322816132ad565b946020939093013593505050565b60008060008060008060008060006101208a8c03121561334f57600080fd5b893561335a816132ad565b985060208a0135975060408a01356005811061337557600080fd5b965060608a0135613385816132ad565b955060808a0135613395816132ad565b989b979a50959894979660a0860135965060c08601359560e0810135955061010001359350915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60058110613425577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6134348282516133ee565b6020810151613447602084018215159052565b50604081015161346260408401826001600160a01b03169052565b50606081015161347d60608401826001600160a01b03169052565b50608081015161349860808401826001600160a01b03169052565b5060a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201516134ea828501826001600160a01b03169052565b5050610160818101516001600160a01b03169083015261018080820151908301526101a090810151910152565b6101c081016115448284613429565b60006020828403121561353857600080fd5b8135612df5816132ad565b6000806000806080858703121561355957600080fd5b8435613564816132ad565b935060208501359250604085013561357b816132ad565b9396929550929360600135925050565b6000806000606084860312156135a057600080fd5b83356135ab816132ad565b95602085013595506040909401359392505050565b604080825283519082018190526000906020906060840190828701845b828110156136025781516001600160a01b0316845292840192908401906001016135dd565b5050508381038285015284518082528583019183019060005b818110156136375783518352928401929184019160010161361b565b5090979650505050505050565b60005b8381101561365f578181015183820152602001613647565b50506000910152565b6020815260008251806020840152613687816040850160208701613644565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6001600160a01b03831681526101e08101612df56020830184613429565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115611544576115446136d7565b60006020828403121561372b57600080fd5b8151612df5816132ad565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613767576137676136d7565b5060010190565b81810381811115611544576115446136d7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156137f7576137f7613781565b604052919050565b600067ffffffffffffffff82111561381957613819613781565b5060051b60200190565b600082601f83011261383457600080fd5b81516020613849613844836137ff565b6137b0565b8083825260208201915060208460051b87010193508684111561386b57600080fd5b602086015b848110156138875780518352918301918301613870565b509695505050505050565b600080604083850312156138a557600080fd5b825167ffffffffffffffff808211156138bd57600080fd5b818501915085601f8301126138d157600080fd5b815160206138e1613844836137ff565b82815260059290921b8401810191818101908984111561390057600080fd5b948201945b83861015613927578551613918816132ad565b82529482019490820190613905565b9188015191965090935050508082111561394057600080fd5b5061394d85828601613823565b9150509250929050565b60006020828403121561396957600080fd5b8151612df581613282565b60006020828403121561398657600080fd5b5051919050565b8082028115828204841417611544576115446136d7565b6000826139da577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008251613a20818460208701613644565b919091019291505056fea264697066735822122033ad2450b468d590536058cf2ff4a0eeb1a99152fef663fa318f1b5a1210c2f764736f6c6343000816003300000000000000000000000077b35947d508012589a91ca4c9d168824376cc7d0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106101cd5760003560e01c8063825c7d10116100f7578063b567858811610095578063f074258e11610064578063f074258e14610519578063f2fde38b14610539578063f533b80214610559578063ffa1ad741461058757600080fd5b8063b5678588146104a6578063c7e3efe3146104b9578063d47e13bb146104d9578063df9efd7f146104f957600080fd5b80638da5cb5b116100d15780638da5cb5b146104285780639b14eb5b146104465780639ddd898214610466578063a96e24231461048657600080fd5b8063825c7d10146103bb578063866f5943146103db57806388700d1c146103fb57600080fd5b80635138b08c1161016f57806365f3952b1161013e57806365f3952b14610346578063715018a61461036657806372582b481461037b5780637dc0d1d01461039b57600080fd5b80635138b08c146102be578063528cfa98146102de5780635681104a146102f45780635c975abb1461030a57600080fd5b806326939c15116101ab57806326939c151461023057806335659fb81461025057806339a51be5146102665780633fc8cef31461029e57600080fd5b806302329a29146101d2578063049fefbe146101f45780631bd859e11461021d575b600080fd5b3480156101de57600080fd5b506101f26101ed366004613290565b6105dd565b005b34801561020057600080fd5b5061020a6101f481565b6040519081526020015b60405180910390f35b6101f261022b3660046132c2565b6105fe565b34801561023c57600080fd5b506101f261024b366004613304565b610a42565b34801561025c57600080fd5b5061020a60055481565b34801561027257600080fd5b50600454610286906001600160a01b031681565b6040516001600160a01b039091168152602001610214565b3480156102aa57600080fd5b50600654610286906001600160a01b031681565b3480156102ca57600080fd5b506101f26102d9366004613304565b610b08565b3480156102ea57600080fd5b5061020a61271081565b34801561030057600080fd5b5061020a61012c81565b34801561031657600080fd5b5060005474010000000000000000000000000000000000000000900460ff165b6040519015158152602001610214565b34801561035257600080fd5b506101f2610361366004613330565b610e6c565b34801561037257600080fd5b506101f2611416565b34801561038757600080fd5b5061020a610396366004613304565b61142a565b3480156103a757600080fd5b50600254610286906001600160a01b031681565b3480156103c757600080fd5b506101f26103d6366004613304565b61154a565b3480156103e757600080fd5b50600754610286906001600160a01b031681565b34801561040757600080fd5b5061041b610416366004613304565b611638565b6040516102149190613517565b34801561043457600080fd5b506000546001600160a01b0316610286565b34801561045257600080fd5b506101f2610461366004613526565b6117ab565b34801561047257600080fd5b506101f2610481366004613526565b61181d565b34801561049257600080fd5b506101f26104a1366004613526565b61182e565b6101f26104b4366004613543565b6118a0565b3480156104c557600080fd5b506101f26104d4366004613526565b611edd565b3480156104e557600080fd5b50600854610286906001600160a01b031681565b34801561050557600080fd5b50610336610514366004613304565b611f4f565b34801561052557600080fd5b506101f2610534366004613304565b6120fe565b34801561054557600080fd5b506101f2610554366004613526565b61243e565b34801561056557600080fd5b5061057961057436600461358b565b612497565b6040516102149291906135c0565b34801561059357600080fd5b506105d06040518060400160405280600581526020017f322e362e3100000000000000000000000000000000000000000000000000000081525081565b6040516102149190613668565b6105e56125bf565b80156105f6576105f3612605565b50565b6105f3612691565b6106066126e8565b61060e61273d565b610619336001612780565b5061062381612865565b610659576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038316600090815260096020908152604080832085845290915280822081516101c081019092528054829060ff16600481111561069f5761069f6133bf565b60048111156106b0576106b06133bf565b8152815460ff61010080830491909116151560208401526001600160a01b036201000090920482166040840152600184015482166060840152600284015482166080840152600384015460a0840152600484015460c0840152600584015460e0840152600684015490830152600783015461012083015260088301548116610140830152600983015416610160820152600a820154610180820152600b909101546101a090910152905060008151600481111561076f5761076f6133bf565b148061078d575060018151600481111561078b5761078b6133bf565b145b806107aa57506002815160048111156107a8576107a86133bf565b145b156107e1576040517fe9184ea200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101608101516001600160a01b031615610827576040517fc8f99b9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060a00151421015610865576040517ff76338d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038085166000908152600960208181526040808420888552909152822080547fffffffffffffffffffff000000000000000000000000000000000000000000001681556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600282018054821690556003820184905560048201849055600582018490556006820184905560078201849055600882018054821690559181018054909216909155600a8101829055600b0155608082015116610975578060e001513414610970576040517fbd28e88900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c1565b34156109ad576040517fbd28e88900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109c1333083608001518460e0015161289d565b6109e584848360200151858560800151866040015187606001518860e00151612a31565b82846001600160a01b0316336001600160a01b03167f19fa05c932bb0a66ab6522bdf2bda21ca0eeeb678dfc19839b0371622f744a548585604051610a2b9291906136b9565b60405180910390a450610a3d60018055565b505050565b610a4a6125bf565b6001600160a01b038216600090815260096020908152604080832084845290915281205460ff166004811115610a8257610a826133bf565b03610ab9576040517fe9184ea200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0390911660009081526009602090815260408083209383529290522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b610b106126e8565b610b1861273d565b6001600160a01b038216600090815260096020908152604080832084845290915280822081516101c081019092528054829060ff166004811115610b5e57610b5e6133bf565b6004811115610b6f57610b6f6133bf565b8152815460ff61010080830491909116151560208401526001600160a01b036201000090920482166040840152600184015482166060840152600284015482166080840152600384015460a0840152600484015460c0840152600584015460e0840152600684015490830152600783015461012083015260088301548116610140830152600983015416610160820152600a820154610180820152600b909101546101a0909101529050600081516004811115610c2e57610c2e6133bf565b1480610c4c5750600481516004811115610c4a57610c4a6133bf565b145b15610c83576040517fe9184ea200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101608101516001600160a01b0316610cc8576040517feffaea8000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806101200151816101000151610cde9190613706565b4211610d16576040517f6463738900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0383166000908152600960208181526040808420868552825280842080547fffffffffffffffffffff000000000000000000000000000000000000000000001681556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600282018054821690556003820186905560048201869055600582018690556006820186905560078201869055600882018054821690559381018054909416909355600a8301849055600b90920192909255908201516101408301516080840151928401516060850151610180860151610e129589958995909490939192909190612a31565b81836001600160a01b0316336001600160a01b03167fc52e7ef6df45fb1214ab4d4798bd31974d9b0afbb2667144d6932ddfb1a03ac884604051610e569190613517565b60405180910390a450610e6860018055565b5050565b610e746126e8565b610e7c61273d565b610e87336001612780565b50610e93866001612780565b506040517f6352211e00000000000000000000000000000000000000000000000000000000815260048101899052899033906001600160a01b03831690636352211e90602401602060405180830381865afa158015610ef6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1a9190613719565b6001600160a01b031614610f5a576040517f59dc379f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b42851015610f66574294505b6000600360008154610f7790613736565b91905081905590506000604051806101c001604052808b6004811115610f9f57610f9f6133bf565b81526000602082018190523360408301526001600160a01b038c811660608401528b16608083015260a082018a905260c0820189905260e0820187905261010082018190526101208201889052610140820181905261016082018190526101808201526101a001839052905060018a600481111561101f5761101f6133bf565b03611038576101008101879052600060e08201526110d5565b60028a600481111561104c5761104c6133bf565b0361105d57600060e08201526110d5565b60038a6004811115611071576110716133bf565b146110d55760048a600481111561108a5761108a6133bf565b036110a357600060c082018190526101208201526110d5565b6040517fe9184ea200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038c1660009081526009602090815260408083208e84529091529020815181548392919082907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836004811115611138576111386133bf565b0217905550602082015181546040808501517fffffffffffffffffffff000000000000000000000000000000000000000000ff90921661010093151584027fffffffffffffffffffff0000000000000000000000000000000000000000ffff1617620100006001600160a01b039384160217845560608501516001850180547fffffffffffffffffffffffff00000000000000000000000000000000000000009081169285169290921790556080860151600286018054831691851691909117905560a0860151600386015560c086015160048087019190915560e0870151600587015593860151600686015561012086015160078601556101408601516008860180548316918516919091179055610160860151600986018054909216908416179055610180850151600a8501556101a090940151600b9093019290925591517f23b872dd0000000000000000000000000000000000000000000000000000000081523392810192909252306024830152604482018d90528416906323b872dd90606401600060405180830381600087803b1580156112d757600080fd5b505af11580156112eb573d6000803e3d6000fd5b50506040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018e90523092506001600160a01b0386169150636352211e90602401602060405180830381865afa15801561134f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113739190613719565b6001600160a01b0316146113b3576040517f93ac15de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a8c6001600160a01b0316336001600160a01b03167fd63da9eb66a685346e9841fa559fa2b364689ef42cf9d5a84942f5d2fbc5b6dc846040516113f79190613517565b60405180910390a450505061140b60018055565b505050505050505050565b61141e6125bf565b6114286000612d5c565b565b6001600160a01b038216600090815260096020908152604080832084845290915280822081516101c08101909252805483929190829060ff166004811115611474576114746133bf565b6004811115611485576114856133bf565b8152815460ff61010080830491909116151560208401526001600160a01b036201000090920482166040840152600184015482166060840152600284015482166080840152600384015460a0840152600484015460c0840152600584015460e0840152600684015490830152600783015461012083015260088301548116610140830152600983015416610160820152600a82015461018080830191909152600b909201546101a09091015281015190915061154090612dc4565b9150505b92915050565b6115526125bf565b61155b82612865565b611591576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127108111156115cd576040517fa535919f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03841690811790915560058290556040518291907f389f6e01d911ce2a6919bdcf4e57d270003243ca9c54e7911454a70f89aee19e90600090a35050565b604080516101c0808201835260008083526020808401829052838501829052606084018290526080840182905260a0840182905260c0840182905260e08401829052610100840182905261012084018290526101408401829052610160840182905261018084018290526101a084018290526001600160a01b03871682526009815284822086835290528381208451928301909452835492939092829060ff1660048111156116e9576116e96133bf565b60048111156116fa576116fa6133bf565b8152815460ff61010080830491909116151560208401526001600160a01b036201000090920482166040840152600184015482166060840152600284015482166080840152600384015460a0840152600484015460c0840152600584015460e0840152600684015490830152600783015461012083015260088301548116610140830152600983015416610160820152600a820154610180820152600b909101546101a09091015291505092915050565b6117b36125bf565b600780546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907fd0e4e983667a08a1813ab08b3dcf5fc3bd3f6f66ccf1d9f6a317369dfb6df6e090600090a35050565b6118256125bf565b6105f381612e06565b6118366125bf565b600680546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907fdfc4c08fb23afd3ed9497c154a48cb9a7eb5e5ef2307e641ec9faef507d4e38a90600090a35050565b6118a86126e8565b6118b061273d565b6118bb336001612780565b506118c582612865565b6118fb576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038416600090815260096020908152604080832086845290915280822081516101c081019092528054829060ff166004811115611941576119416133bf565b6004811115611952576119526133bf565b8152815460ff61010080830491909116151560208401526001600160a01b036201000090920482166040840152600184015482166060840152600284015482166080840152600384015460a0840152600484015460c0840152600584015460e084015260068401549083015260078301546101208301526008830154811661014083015260098301541661016080830191909152600a83015461018080840191909152600b909301546101a090920191909152908201519082015191925090600083516004811115611a2657611a266133bf565b1480611a445750600483516004811115611a4257611a426133bf565b145b15611a7b576040517fe9184ea200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a00151421015611ab9576040517fb722c5a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038116611bb3578260c00151841015611b05576040517fa0d26eb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600283516004811115611b1a57611b1a6133bf565b1480611b385750600383516004811115611b3657611b366133bf565b145b15611b4557426101008401525b600183516004811115611b5a57611b5a6133bf565b03611bae57826101200151836101000151611b759190613706565b421115611bae576040517fa0e9298400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c49565b826101200151836101000151611bc99190613706565b421115611c02576040517fa0e9298400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c10836101800151612dc4565b841015611c49576040517fa0d26eb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101808301849052336101608401526001600160a01b0385166101408401526101208301516101008401516000914291611c839190613706565b611c8d919061376e565b905061012c811015611cbb57611ca58161012c61376e565b8461012001818151611cb79190613706565b9052505b6101808401516001600160a01b0389811660009081526009602081815260408084208d8552909152909120600a81019390935561016087015190830180549183167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617905561014087015160088401805491909316911617905561010085015160069091015414611d77576101008401516001600160a01b03891660009081526009602090815260408083208b84529091529020600601555b6101208401516001600160a01b03891660009081526009602090815260408083208b845290915290206007015414611dd7576101208401516001600160a01b03891660009081526009602090815260408083208b84529091529020600701555b60808401516001600160a01b0316611e2757843414611e22576040517fbd28e88900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e6f565b3415611e5f576040517fbd28e88900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e6f333086608001518861289d565b611e7e82856080015185612e70565b86886001600160a01b0316336001600160a01b03167fec3d0c3ed87fd441707a880ed0b47c57cb0df7d321cc44199fb96a012bbbfd8d87604051611ec29190613517565b60405180910390a450505050611ed760018055565b50505050565b611ee56125bf565b600880546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f5ec630642fcf2e8cf5a0935fd70f1a00c37521eb7758bbbf5ae3155c59fe9cc790600090a35050565b6001600160a01b038216600090815260096020908152604080832084845290915280822081516101c08101909252805483929190829060ff166004811115611f9957611f996133bf565b6004811115611faa57611faa6133bf565b8152815461010080820460ff1615156020840152620100009091046001600160a01b03908116604080850191909152600185015482166060850152600285015482166080850152600385015460a085015260048086015460c0860152600586015460e08601526006860154938501939093526007808601546101208601526008860154831661014086015260098601548316610160860152600a860154610180860152600b909501546101a09094019390935284830151935492517f748690890000000000000000000000000000000000000000000000000000000081528982169281019290925260248201889052939450918316921690637486908990604401602060405180830381865afa1580156120c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ec9190613719565b6001600160a01b031614949350505050565b6121066126e8565b61210e61273d565b6001600160a01b038216600090815260096020908152604080832084845290915280822081516101c0810190925280548593929190829060ff166004811115612159576121596133bf565b600481111561216a5761216a6133bf565b8152815461010080820460ff1615156020840152620100009091046001600160a01b03908116604080850191909152600185015482166060850152600285015482166080850152600385015460a0850152600485015460c0850152600585015460e085015260068501549284019290925260078401546101208401526008840154811661014084015260098401548116610160840152600a840154610180840152600b909301546101a09092019190915282015191925016331461225a576040517f5ec8235100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101608101516001600160a01b0316156122a0576040517fc8f99b9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03848116600090815260096020818152604080842088855290915280832080547fffffffffffffffffffff000000000000000000000000000000000000000000001681556001810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155600282018054821690556003820185905560048083018690556005830186905560068301869055600783018690556008830180548316905593820180549091169055600a8101849055600b01929092558382015191517f23b872dd0000000000000000000000000000000000000000000000000000000081523091810191909152908216602482015260448101859052908316906323b872dd90606401600060405180830381600087803b1580156123cf57600080fd5b505af11580156123e3573d6000803e3d6000fd5b5050505082846001600160a01b0316336001600160a01b03167f50d73552a7c03b8dc819baed087a15a97fe6abdc907b7a06e4bb0e300712395d8460405161242b9190613517565b60405180910390a45050610e6860018055565b6124466125bf565b6001600160a01b03811661248e576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024015b60405180910390fd5b6105f381612d5c565b60085460609081906001600160a01b03163b6000036124f65760005b6040519080825280602002602001820160405280156124dc578160200160208202803683370190505b5060408051600081526020810190915290925090506125b7565b6008546040517f3e1040140000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152602482018790526044820186905290911690633e10401490606401600060405180830381865afa9250505080156125a657506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526125a39190810190613892565b60015b6125b15760006124b3565b90925090505b935093915050565b6000546001600160a01b03163314611428576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401612485565b61260d6126e8565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586126743390565b6040516001600160a01b03909116815260200160405180910390a1565b612699612ec0565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612674565b60005474010000000000000000000000000000000000000000900460ff1615611428576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600260015403612779576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600155565b6002546000906001600160a01b031661279b57506000611544565b6002546040517fdf592f7d0000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301529091169063df592f7d90602401602060405180830381865afa1580156127fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128229190613957565b905081801561282e5750805b15611544576040517f2e70c0b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001600160a01b03821661287d57506000919050565b612888826000612780565b1561289557506000919050565b506001919050565b8015611ed757826001600160a01b0316846001600160a01b03160315611ed7576040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015283916000918316906370a0823190602401602060405180830381865afa158015612921573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129459190613974565b905061295c6001600160a01b038316878786612f14565b6040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b038681166004830152600091908416906370a0823190602401602060405180830381865afa1580156129bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e39190613974565b9050836129f0838361376e565b1015612a28576040517f35bfbdb000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b8086612a7c57600061271060055484612a4a919061398d565b612a5491906139a4565b9050612a60818361376e565b600454909250612a7a906001600160a01b03168783612e70565b505b6007546040517f748690890000000000000000000000000000000000000000000000000000000081526001600160a01b038b81166004830152602482018b90526000921690637486908990604401602060405180830381865afa158015612ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0b9190613719565b9050806001600160a01b0316856001600160a01b031614158015612b3a57506008546001600160a01b03163b15155b15612cc4576008546040517ff533b8020000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c9052604482018590529091169063f533b802906064016000604051808303816000875af1925050508015612bf157506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612bee9190810190613892565b60015b15612cc4578051825103612cc15760005b8251811015612cbf57612c2f838281518110612c2057612c206139df565b60200260200101516000612780565b612cb75784828281518110612c4657612c466139df565b602002602001015111612cbf57818181518110612c6557612c656139df565b602002602001015185612c78919061376e565b9450612cb7838281518110612c8f57612c8f6139df565b60200260200101518a848481518110612caa57612caa6139df565b6020026020010151612e70565b600101612c02565b505b50505b612ccf848784612e70565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038881166024830152604482018b90528b16906323b872dd90606401600060405180830381600087803b158015612d3857600080fd5b505af1158015612d4c573d6000803e3d6000fd5b5050505050505050505050505050565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080612710612dd66101f48561398d565b612de091906139a4565b905080600003612dfc57612df5836001613706565b9392505050565b612df58184613706565b600280546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f9dc7a30661b0eef899195a36c42f80a98cafd90e68cd8a50af361f2b04916dbf90600090a35050565b6001600160a01b0383161580612e84575080155b15612e8e57505050565b6001600160a01b038216612eb557600654610a3d90849083906001600160a01b0316612f90565b610a3d838383612f9f565b60005474010000000000000000000000000000000000000000900460ff16611428576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038481166024830152838116604483015260648201839052611ed79186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612fc0565b610a3d838383620186a061303c565b80600003612fac57505050565b610a3d6001600160a01b0383168483613118565b6000612fd56001600160a01b03841683613149565b90508051600014158015612ffa575080806020019051810190612ff89190613957565b155b15610a3d576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401612485565b8215611ed7576000846001600160a01b0316848390604051600060405180830381858888f193505050503d8060008114613092576040519150601f19603f3d011682016040523d82523d6000602084013e613097565b606091505b5050905080613111576000839050806001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b1580156130e057600080fd5b505af11580156130f4573d6000803e3d6000fd5b5061310f935050506001600160a01b03831690508787613118565b505b5050505050565b6040516001600160a01b03838116602483015260448201839052610a3d91859182169063a9059cbb90606401612f49565b6060612df58383600084600080856001600160a01b0316848660405161316f9190613a0e565b60006040518083038185875af1925050503d80600081146131ac576040519150601f19603f3d011682016040523d82523d6000602084013e6131b1565b606091505b50915091506131c18683836131cb565b9695505050505050565b6060826131e0576131db82613240565b612df5565b81511580156131f757506001600160a01b0384163b155b15613239576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401612485565b5080612df5565b8051156132505780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80151581146105f357600080fd5b6000602082840312156132a257600080fd5b8135612df581613282565b6001600160a01b03811681146105f357600080fd5b6000806000606084860312156132d757600080fd5b83356132e2816132ad565b92506020840135915060408401356132f9816132ad565b809150509250925092565b6000806040838503121561331757600080fd5b8235613322816132ad565b946020939093013593505050565b60008060008060008060008060006101208a8c03121561334f57600080fd5b893561335a816132ad565b985060208a0135975060408a01356005811061337557600080fd5b965060608a0135613385816132ad565b955060808a0135613395816132ad565b989b979a50959894979660a0860135965060c08601359560e0810135955061010001359350915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60058110613425577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6134348282516133ee565b6020810151613447602084018215159052565b50604081015161346260408401826001600160a01b03169052565b50606081015161347d60608401826001600160a01b03169052565b50608081015161349860808401826001600160a01b03169052565b5060a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201516134ea828501826001600160a01b03169052565b5050610160818101516001600160a01b03169083015261018080820151908301526101a090810151910152565b6101c081016115448284613429565b60006020828403121561353857600080fd5b8135612df5816132ad565b6000806000806080858703121561355957600080fd5b8435613564816132ad565b935060208501359250604085013561357b816132ad565b9396929550929360600135925050565b6000806000606084860312156135a057600080fd5b83356135ab816132ad565b95602085013595506040909401359392505050565b604080825283519082018190526000906020906060840190828701845b828110156136025781516001600160a01b0316845292840192908401906001016135dd565b5050508381038285015284518082528583019183019060005b818110156136375783518352928401929184019160010161361b565b5090979650505050505050565b60005b8381101561365f578181015183820152602001613647565b50506000910152565b6020815260008251806020840152613687816040850160208701613644565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6001600160a01b03831681526101e08101612df56020830184613429565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115611544576115446136d7565b60006020828403121561372b57600080fd5b8151612df5816132ad565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613767576137676136d7565b5060010190565b81810381811115611544576115446136d7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156137f7576137f7613781565b604052919050565b600067ffffffffffffffff82111561381957613819613781565b5060051b60200190565b600082601f83011261383457600080fd5b81516020613849613844836137ff565b6137b0565b8083825260208201915060208460051b87010193508684111561386b57600080fd5b602086015b848110156138875780518352918301918301613870565b509695505050505050565b600080604083850312156138a557600080fd5b825167ffffffffffffffff808211156138bd57600080fd5b818501915085601f8301126138d157600080fd5b815160206138e1613844836137ff565b82815260059290921b8401810191818101908984111561390057600080fd5b948201945b83861015613927578551613918816132ad565b82529482019490820190613905565b9188015191965090935050508082111561394057600080fd5b5061394d85828601613823565b9150509250929050565b60006020828403121561396957600080fd5b8151612df581613282565b60006020828403121561398657600080fd5b5051919050565b8082028115828204841417611544576115446136d7565b6000826139da577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008251613a20818460208701613644565b919091019291505056fea264697066735822122033ad2450b468d590536058cf2ff4a0eeb1a99152fef663fa318f1b5a1210c2f764736f6c63430008160033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000077b35947d508012589a91ca4c9d168824376cc7d0000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : initOwner (address): 0x77B35947d508012589a91CA4c9d168824376Cc7D
Arg [1] : initSanctionsOracle (address): 0x0000000000000000000000000000000000000000
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000077b35947d508012589a91ca4c9d168824376cc7d
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
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.