Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 1,812 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Set Approval For... | 24550635 | 4 hrs ago | IN | 0 ETH | 0.00000193 | ||||
| Auction Mint | 24548617 | 11 hrs ago | IN | 0.096 ETH | 0.00033445 | ||||
| Two For One Mint | 24517390 | 4 days ago | IN | 0 ETH | 0.00000548 | ||||
| Set Approval For... | 24452022 | 13 days ago | IN | 0 ETH | 0.00000126 | ||||
| Set Approval For... | 24450300 | 14 days ago | IN | 0 ETH | 0.00005431 | ||||
| Withdraw Safe | 24420465 | 18 days ago | IN | 0 ETH | 0.00026672 | ||||
| Transfer Ownersh... | 24420434 | 18 days ago | IN | 0 ETH | 0.00000886 | ||||
| Safe Transfer Fr... | 24405413 | 20 days ago | IN | 0 ETH | 0.00000971 | ||||
| Safe Transfer Fr... | 24405411 | 20 days ago | IN | 0 ETH | 0.00001038 | ||||
| Safe Transfer Fr... | 24405409 | 20 days ago | IN | 0 ETH | 0.00000913 | ||||
| Safe Transfer Fr... | 24405408 | 20 days ago | IN | 0 ETH | 0.00000834 | ||||
| Safe Transfer Fr... | 24405407 | 20 days ago | IN | 0 ETH | 0.00000838 | ||||
| Safe Transfer Fr... | 24405403 | 20 days ago | IN | 0 ETH | 0.00000918 | ||||
| Safe Transfer Fr... | 24405401 | 20 days ago | IN | 0 ETH | 0.00000804 | ||||
| Safe Transfer Fr... | 24405398 | 20 days ago | IN | 0 ETH | 0.00000893 | ||||
| Safe Transfer Fr... | 24405380 | 20 days ago | IN | 0 ETH | 0.00000964 | ||||
| Safe Transfer Fr... | 24405377 | 20 days ago | IN | 0 ETH | 0.0000117 | ||||
| Safe Transfer Fr... | 24369583 | 25 days ago | IN | 0 ETH | 0.00016992 | ||||
| Safe Transfer Fr... | 24368826 | 25 days ago | IN | 0 ETH | 0.00018567 | ||||
| Set Approval For... | 24363386 | 26 days ago | IN | 0 ETH | 0.00004279 | ||||
| Set Approval For... | 24363346 | 26 days ago | IN | 0 ETH | 0.00005348 | ||||
| Set Approval For... | 24349330 | 28 days ago | IN | 0 ETH | 0.00012853 | ||||
| Set Approval For... | 24330962 | 30 days ago | IN | 0 ETH | 0.00000236 | ||||
| Two For One Mint | 24274348 | 38 days ago | IN | 0 ETH | 0.00001532 | ||||
| Set Approval For... | 24260566 | 40 days ago | IN | 0 ETH | 0.0000979 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 24420465 | 18 days ago | 0.05616 ETH | ||||
| Transfer | 24420465 | 18 days ago | 0.8424 ETH | ||||
| Transfer | 24420465 | 18 days ago | 0.8424 ETH | ||||
| Transfer | 24420465 | 18 days ago | 9.49104 ETH | ||||
| Transfer | 23797467 | 105 days ago | 0.17192444 ETH | ||||
| Transfer | 23665921 | 123 days ago | 0.0691289 ETH | ||||
| Transfer | 23630916 | 128 days ago | 0.08686 ETH | ||||
| Transfer | 23629789 | 128 days ago | 0.01189556 ETH | ||||
| Transfer | 23626591 | 129 days ago | 0.01391556 ETH | ||||
| Transfer | 23626310 | 129 days ago | 0.00816 ETH | ||||
| Transfer | 23626310 | 129 days ago | 0.1224 ETH | ||||
| Transfer | 23626310 | 129 days ago | 0.1224 ETH | ||||
| Transfer | 23626310 | 129 days ago | 1.37904 ETH | ||||
| Transfer | 23625839 | 129 days ago | 0.00583557 ETH | ||||
| Transfer | 23625670 | 129 days ago | 0.00673334 ETH | ||||
| Transfer | 23619377 | 130 days ago | 0.309408 ETH | ||||
| Transfer | 23619377 | 130 days ago | 4.64112 ETH | ||||
| Transfer | 23619377 | 130 days ago | 4.64112 ETH | ||||
| Transfer | 23619377 | 130 days ago | 52.289952 ETH | ||||
| Transfer | 23614274 | 131 days ago | 0.09022667 ETH | ||||
| Transfer | 23614153 | 131 days ago | 0.03501334 ETH | ||||
| Transfer | 23610494 | 131 days ago | 0.10840667 ETH | ||||
| Transfer | 23605707 | 132 days ago | 0.02222 ETH | ||||
| Transfer | 23597994 | 133 days ago | 0.14858222 ETH | ||||
| Transfer | 23597830 | 133 days ago | 0.05454 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
MidnightBreezeV2
Compiler Version
v0.8.30+commit.73712a01
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@limitbreak/creator-token-standards/src/erc721c/ERC721C.sol";
import "@limitbreak/creator-token-standards/src/programmable-royalties/BasicRoyalties.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@limitbreak/creator-token-standards/src/access/OwnableBasic.sol";
/*
██████████ █████ █████ █████ ███ █████
▒███▒▒▒▒███ ▒▒███ ▒▒███ ▒▒███ ▒▒▒ ▒▒███
▒███ ▒▒███ █████ ████ ███████ ██████ ▒███████ ███████ ████ ███████ ██████
▒███ ▒███▒▒███ ▒███ ▒▒▒███▒ ███▒▒███ ▒███▒▒███ ▒▒▒███▒ ▒▒███ ███▒▒███ ███▒▒███
▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒▒▒ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███████
▒███ ███ ▒███ ▒███ ▒███ ███▒███ ███ ▒███ ▒███ ▒███ ███ ▒███ ▒███ ▒███ ▒███▒▒▒
██████████ ▒▒████████ ▒▒█████ ▒▒██████ ████ █████ ▒▒█████ █████▒▒████████▒▒██████
▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒
█████ █████
▒▒███ ▒▒███
▒▒███ ███
▒▒█████
███▒███
███ ▒▒███
█████ █████
▒▒▒▒▒ ▒▒▒▒▒
███████████ █████ ████ █████
▒███▒▒▒▒▒███ ▒▒███ ▒▒███ ▒▒███
▒███ ▒███ ██████ ▒███████ ▒███ ██████ ███████ ██████ █████ █████
▒██████████ ▒▒▒▒▒███ ▒███▒▒███ ▒███ ███▒▒███ ███▒▒███ ███▒▒███▒▒███ ▒▒███
▒███▒▒▒▒▒▒ ███████ ▒███ ▒███ ▒███ ▒███ ▒███▒███ ▒███ ▒███████ ▒███ ▒███
▒███ ███▒▒███ ▒███ ▒███ ▒███ ▒███ ▒███▒███ ▒███ ▒███▒▒▒ ▒▒███ ███
█████ ▒▒████████ ████████ █████▒▒██████ ▒▒████████▒▒██████ ▒▒█████
▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒▒▒▒
██████ ██████ ███ █████ ███ █████ █████ ███████████ ████████
▒▒██████ ██████ ▒▒▒ ▒▒███ ▒▒▒ ▒▒███ ▒▒███ ▒▒███▒▒▒▒▒███ ███▒▒▒▒███
▒███▒█████▒███ ████ ███████ ████████ ████ ███████ ▒███████ ███████ ▒███ ▒███ ████████ ██████ ██████ █████████ ██████ ▒▒▒ ▒███
▒███▒▒███ ▒███ ▒▒███ ███▒▒███ ▒▒███▒▒███ ▒▒███ ███▒▒███ ▒███▒▒███ ▒▒▒███▒ ▒██████████ ▒▒███▒▒███ ███▒▒███ ███▒▒███ ▒█▒▒▒▒███ ███▒▒███ ███████
▒███ ▒▒▒ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███▒▒▒▒▒███ ▒███ ▒▒▒ ▒███████ ▒███████ ▒ ███▒ ▒███████ ███▒▒▒▒
▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ▒███ ███ ▒███ ▒███ ▒███ ▒███▒▒▒ ▒███▒▒▒ ███▒ █▒███▒▒▒ ███ █
█████ █████ █████▒▒████████ ████ █████ █████▒▒███████ ████ █████ ▒▒█████ ███████████ █████ ▒▒██████ ▒▒██████ █████████▒▒██████ ▒██████████
▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒███▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒
███ ▒███
▒▒██████
▒▒▒▒▒▒
*/
contract MidnightBreezeV2 is
ERC721C,
BasicRoyalties,
OwnableBasic,
ReentrancyGuard
{
struct Auction {
uint256 startBlock;
uint256 endBlock;
uint256 discountRate;
uint256 startingPrice;
uint256 minPrice;
uint256 lastPrice;
uint256 amountPurchased;
uint256 totalPaid;
bool active;
}
string public upgradableTokensURI;
string public publicMintTokensURI;
address private devpablo = 0x7e41cb2eCA64793532d6730b38d10575fD62B37F;
address private devasto = 0x0B884DfbadE931b8eA5DB16Cc28434EC23f4054E;
address private dutchtide = 0x11c6AFEB38B7B31a0E997AaaC9A16538b86CDE63;
address private derak = 0x5D8F48b84937aeEEe870E4376821956303F79903;
address private V1Address;
address private burnAddress = 0x0000000000000000000000000000000000000001;
bool public oneForOneBurnStarted = false;
bool public oneForOneClaimStarted = false;
bool public travelersWhitelistStarted = false;
bool public dedicatedWhitelistStarted = false;
bool public twoForOneMintStarted = false;
bytes32 public travelersMerkleRoot = bytes32(0);
bytes32 public dedicatedMerkleRoot = bytes32(0);
uint256 public constant MAX_SUPPLY = 10000;
uint256 public constant UPGRADABLE_SUPPLY = 6969;
uint256 public constant PUBLIC_START_ID = UPGRADABLE_SUPPLY + 1;
uint256 public travelersReserve = 400;
uint256 public dedicatedReserve = 100;
uint256 public constant MAX_PER_MINT = 69;
uint256 public nextPublicId = PUBLIC_START_ID;
uint256 public totalMintedPublic = 0;
uint256 public totalMintedTravelers = 0;
uint256 public dedicatedPrice = 0;
uint256 public travelerPrice = 0;
mapping(address => uint256) public travelersWhitelistMinted;
mapping(uint256 => Auction) public auctions;
mapping(address => mapping(uint256 => uint256)) public auctionParticipation;
mapping(address => mapping(uint256 => uint256)) public auctionAmountPaid;
mapping(address => uint256[]) private V1BreezesBurned;
uint256 private auctionCount = 0;
bool public transfersBlocked = true;
constructor(
string memory baseURI,
address _V1Address
)
ERC721OpenZeppelin("MidnightBreezeV2", "MBV2")
BasicRoyalties(msg.sender, 0) // every 100 is 1%
{
upgradableTokensURI = baseURI;
publicMintTokensURI = baseURI;
V1Address = _V1Address;
}
function setURI(
string memory _upgradableTokensURI,
string memory _publicMintTokensURI
) external {
_requireCallerIsContractOwner();
upgradableTokensURI = _upgradableTokensURI;
publicMintTokensURI = _publicMintTokensURI;
}
function tokenURI(
uint256 _tokenId
) public view override returns (string memory) {
require(_exists(_tokenId), "Token does not exist.");
if (_tokenId <= UPGRADABLE_SUPPLY) {
return
string(
abi.encodePacked(
upgradableTokensURI,
Strings.toString(_tokenId)
)
);
} else {
return
string(
abi.encodePacked(
publicMintTokensURI,
Strings.toString(_tokenId)
)
);
}
}
function createAuction(
uint256 startBlock,
uint256 endBlock,
uint256 discountRate,
uint256 startingPrice,
uint256 minPrice
) external {
_requireCallerIsContractOwner();
require(minPrice > 0, "Min price can't reach zero");
require(
startingPrice > minPrice,
"Start price must be higher than min price"
);
require(
startBlock >= block.number,
"Can't start an auction in the past"
);
require(startBlock < endBlock, "Start block must be before end block");
auctions[auctionCount] = Auction({
startBlock: startBlock,
endBlock: endBlock,
discountRate: discountRate,
startingPrice: startingPrice,
minPrice: minPrice,
lastPrice: startingPrice,
amountPurchased: 0,
totalPaid: 0,
active: true
});
auctionCount++;
}
function stopAuction(uint256 auctionId) external {
_requireCallerIsContractOwner();
auctions[auctionId].active = false;
}
function getAuctionPrice(uint256 auctionId) public view returns (uint256) {
Auction storage auction = auctions[auctionId];
require(block.number >= auction.startBlock, "Auction not started");
require(block.number <= auction.endBlock, "Auction ended");
require(auction.active, "Auction disabled");
uint256 elapsedBlocks = block.number - auction.startBlock;
uint256 discount = auction.discountRate * elapsedBlocks;
uint256 price = auction.startingPrice > discount
? auction.startingPrice - discount
: auction.minPrice; //uint can't deal with negative values...
return price >= auction.minPrice ? price : auction.minPrice;
}
function _mintPublicTo(address to) internal {
require(nextPublicId <= MAX_SUPPLY, "No public supply left");
_safeMint(to, nextPublicId);
nextPublicId++;
}
function auctionMint(
uint256 auctionId,
uint256 mintAmount
) external payable nonReentrant {
Auction storage auction = auctions[auctionId];
require(auction.active, "Auction not active");
require(
mintAmount > 0 && mintAmount <= MAX_PER_MINT,
"Invalid mint amount"
);
require(
block.number >= auction.startBlock &&
block.number <= auction.endBlock,
"Invalid auction period"
);
require(
nextPublicId + mintAmount - 1 <=
MAX_SUPPLY - travelersReserve - dedicatedReserve,
"Auctionable supply depleted"
);
uint256 price = getAuctionPrice(auctionId);
uint256 totalCost = price * mintAmount;
require(msg.value >= totalCost, "Insufficient payment");
for (uint256 i = 0; i < mintAmount; i++) {
_mintPublicTo(msg.sender);
}
// track participation and payments
auctionParticipation[msg.sender][auctionId] += mintAmount;
auctionAmountPaid[msg.sender][auctionId] += totalCost;
auction.lastPrice = price;
auction.amountPurchased += mintAmount;
auction.totalPaid += totalCost;
// refund any overpayment
uint256 over = msg.value - totalCost;
if (over > 0) {
(bool ok, ) = msg.sender.call{value: over}("");
require(ok, "Refund failed");
}
}
function claimAuctionRefund(uint256 auctionId) external nonReentrant {
uint256 paid = auctionAmountPaid[msg.sender][auctionId];
require(paid > 0, "No refund due");
uint256 purchased = auctionParticipation[msg.sender][auctionId];
require(purchased > 0, "No auction purchase recorded");
uint256 last = auctions[auctionId].lastPrice;
uint256 owed = last * purchased;
require(paid > owed, "No refund due");
uint256 refundable = paid - owed;
auctionAmountPaid[msg.sender][auctionId] = owed;
auctions[auctionId].totalPaid -= refundable;
(bool sent, ) = msg.sender.call{value: refundable}("");
require(sent, "Refund transfer failed");
}
event OneForOneBurn(address from, uint256[] burned);
event OneForOneClaim(address from, uint256[] upgraded);
event TwoForOneMint(address from, uint256[] upgraded, uint256[] burned);
function oneForOneBurn(uint[] memory toBurn) external nonReentrant {
require(oneForOneBurnStarted, "One for one burn has not started");
require(!twoForOneMintStarted, "Two for one mint has started");
require(toBurn.length > 0, "Empty burn array");
for (uint i = 0; i < toBurn.length; i++) {
IERC721(V1Address).safeTransferFrom(
_msgSender(),
burnAddress,
toBurn[i]
);
V1BreezesBurned[msg.sender].push(toBurn[i]);
}
emit OneForOneBurn(msg.sender, toBurn);
}
function claimBurnedBreezes(uint256 count) external nonReentrant {
require(oneForOneClaimStarted, "One for one claim has not started");
uint256 len = V1BreezesBurned[msg.sender].length;
require(len > 0, "Nothing to claim");
require(count > 0 && count <= len, "Invalid count");
uint256[] memory claimed = new uint256[](count);
for (uint256 i = 0; i < count; i++) {
uint256 tokenId = V1BreezesBurned[msg.sender][i];
_safeMint(_msgSender(), tokenId);
claimed[i] = tokenId;
}
emit OneForOneClaim(msg.sender, claimed);
for (uint256 i = count; i < len; i++) {
V1BreezesBurned[msg.sender][i - count] = V1BreezesBurned[
msg.sender
][i];
}
for (uint256 i = 0; i < count; i++) {
V1BreezesBurned[msg.sender].pop();
}
}
function twoForOneMint(
uint[] memory toUpgrade,
uint[] memory toBurn
) external nonReentrant {
require(twoForOneMintStarted, "Two for one mint has not started");
require(toUpgrade.length == toBurn.length, "Arrays must match");
require(toUpgrade.length > 0, "Empty upgrade array");
for (uint i = 0; i < toUpgrade.length; i++) {
IERC721(V1Address).safeTransferFrom(
_msgSender(),
burnAddress,
toBurn[i]
);
IERC721(V1Address).safeTransferFrom(
_msgSender(),
burnAddress,
toUpgrade[i]
);
_safeMint(_msgSender(), toUpgrade[i]);
}
emit TwoForOneMint(msg.sender, toUpgrade, toBurn);
}
function travelersWhitelistMint(
bytes32[] calldata proof
) external payable nonReentrant {
require(
travelersWhitelistStarted,
"Travelers whitelist mint not started"
);
require(travelerPrice > 0, "Travelers price not set");
require(
travelersWhitelistMinted[msg.sender] == 0,
"Traveler already minted"
);
require(
totalMintedTravelers + 1 <= travelersReserve,
"Travelers supply depleted"
);
bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
require(
MerkleProof.verify(proof, travelersMerkleRoot, leaf),
"Invalid whitelist proof"
);
require(msg.value == travelerPrice, "Incorrect payment");
// ensure there's at least one public token available
_mintPublicTo(msg.sender);
travelersWhitelistMinted[msg.sender] += 1;
totalMintedTravelers += 1;
}
function dedicatedWhitelistMint(
uint256 mintAmount,
bytes32[] calldata proof
) external payable nonReentrant {
require(
dedicatedWhitelistStarted,
"Dedicated whitelist mint not started"
);
require(
!travelersWhitelistStarted,
"Traveler whitelist mint still ongoing"
);
require(dedicatedPrice > 0, "Dedicated price not set");
require(
nextPublicId + mintAmount - 1 <= MAX_SUPPLY,
"Dedicated supply exceeded"
);
bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
require(
MerkleProof.verify(proof, dedicatedMerkleRoot, leaf),
"Invalid whitelist proof"
);
require(msg.value == mintAmount * dedicatedPrice, "Incorrect payment");
for (uint256 i = 0; i < mintAmount; i++) {
_mintPublicTo(msg.sender);
}
}
function batchTransferFrom(
address _from,
address _to,
uint256[] memory _tokenIds
) public {
for (uint256 i = 0; i < _tokenIds.length; i++) {
transferFrom(_from, _to, _tokenIds[i]);
}
}
function batchSafeTransferFrom(
address _from,
address _to,
uint256[] memory _tokenIds,
bytes memory data_
) public {
for (uint256 i = 0; i < _tokenIds.length; i++) {
safeTransferFrom(_from, _to, _tokenIds[i], data_);
}
}
function getBurned(address user) external view returns (uint256[] memory) {
return V1BreezesBurned[user];
}
function setTravelersMerkleRoot(bytes32 root) external {
_requireCallerIsContractOwner();
require(root != bytes32(0), "Invalid root");
travelersMerkleRoot = root;
}
function setDedicatedMerkleRoot(bytes32 root) external {
_requireCallerIsContractOwner();
require(root != bytes32(0), "Invalid root");
dedicatedMerkleRoot = root;
}
function setTravelersPrice(uint price) external {
_requireCallerIsContractOwner();
require(price > 0, "Price can't be zero");
travelerPrice = price;
}
function setDedicatedPrice(uint price) external {
_requireCallerIsContractOwner();
require(price > 0, "Price can't be zero");
dedicatedPrice = price;
}
function setTravelersReserve(uint amount) external {
_requireCallerIsContractOwner();
travelersReserve = amount;
}
function setDedicatedReserve(uint amount) external {
_requireCallerIsContractOwner();
dedicatedReserve = amount;
}
function startTravelersMint() external {
_requireCallerIsContractOwner();
require(travelerPrice > 0, "Set price first!");
require(travelersMerkleRoot != bytes32(0), "Set root first!");
travelersWhitelistStarted = true;
}
function stopTravelersMint() external {
_requireCallerIsContractOwner();
travelersWhitelistStarted = false;
}
function startDedicatedMint() external {
_requireCallerIsContractOwner();
require(dedicatedPrice > 0, "Set price first!");
require(dedicatedMerkleRoot != bytes32(0), "Set root first!");
require(!travelersWhitelistStarted, "Stop traveler mint first");
dedicatedWhitelistStarted = true;
}
function stopDedicatedMint() external {
_requireCallerIsContractOwner();
dedicatedWhitelistStarted = false;
}
function startOneForOneBurning() external {
_requireCallerIsContractOwner();
oneForOneBurnStarted = true;
}
function stopOneForOneBurning() external {
_requireCallerIsContractOwner();
oneForOneBurnStarted = false;
}
function startTwoForOneMint() external {
_requireCallerIsContractOwner();
twoForOneMintStarted = true;
}
function stopTwoForOneMint() external {
_requireCallerIsContractOwner();
twoForOneMintStarted = false;
}
function startOneForOneClaiming() external {
_requireCallerIsContractOwner();
oneForOneClaimStarted = true;
}
function stopOneForOneClaiming() external {
_requireCallerIsContractOwner();
oneForOneClaimStarted = false;
}
// Returns the maximum refund liability for a single auction.
// - Active auction: conservatively assume lastPrice may drop to minPrice (worst-case).
// - Ended auction: lastPrice is final.
function auctionMaxRefundLiability(
uint256 auctionId
) public view returns (uint256) {
Auction storage a = auctions[auctionId];
// Determine which price to use for refund liability
uint256 priceForLiability;
if (
a.active &&
block.number <= a.endBlock &&
block.number >= a.startBlock
) {
// Active auction: future buyers may lower lastPrice, use minPrice conservatively
priceForLiability = a.minPrice;
} else {
// Ended auction: lastPrice is final
priceForLiability = a.lastPrice;
}
// Refundable amount = totalPaid - priceForLiability * total minted in this auction
if (a.totalPaid > priceForLiability * a.amountPurchased) {
return a.totalPaid - priceForLiability * a.amountPurchased;
}
return 0;
}
//Returns sum of all auction refund liabilities (conservative)
function totalAuctionLiabilities() public view returns (uint256) {
uint256 sum = 0;
for (uint256 i = 0; i < auctionCount; i++) {
sum += auctionMaxRefundLiability(i);
}
return sum;
}
//Maximum safe withdrawable amount from contract
function withdrawable() public view returns (uint256) {
uint256 bal = address(this).balance;
uint256 liabilities = totalAuctionLiabilities();
if (bal > liabilities) {
return bal - liabilities;
}
return 0;
}
//Withdraw funds safely, leaving enough ETH to cover refunds
function withdrawSafe() external nonReentrant {
_requireCallerIsContractOwner();
uint256 available = withdrawable();
require(available > 0, "No withdrawable funds");
uint256 devpablo_fee = (available * 75) / 1000;
uint256 devasto_fee = (available * 75) / 1000;
uint256 derak_fee = (available * 5) / 1000;
uint256 remaining = available - devpablo_fee - devasto_fee - derak_fee;
(bool ok1, ) = payable(dutchtide).call{value: remaining}("");
require(ok1, "Transfer failed");
(bool ok2, ) = payable(devpablo).call{value: devpablo_fee}("");
require(ok2, "Transfer failed");
(bool ok3, ) = payable(devasto).call{value: devasto_fee}("");
require(ok3, "Transfer failed");
(bool ok4, ) = payable(derak).call{value: derak_fee}("");
require(ok4, "Transfer failed");
}
function supportsInterface(
bytes4 interfaceId
) public view virtual override(ERC721C, ERC2981) returns (bool) {
return super.supportsInterface(interfaceId);
}
function setDefaultRoyalty(address receiver, uint96 feeNumerator) public {
_requireCallerIsContractOwner();
_setDefaultRoyalty(receiver, feeNumerator);
}
function setTokenRoyalty(
uint256 tokenId,
address receiver,
uint96 feeNumerator
) public {
_requireCallerIsContractOwner();
_setTokenRoyalty(tokenId, receiver, feeNumerator);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId,
uint256 batchSize
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId, batchSize);
// Allow minting (from 0 address) and burning (to 0 address)
if (from != address(0) && to != address(0)) {
require(!transfersBlocked, "Transfers are currently disabled");
}
}
function approve(address to, uint256 tokenId) public virtual override {
require(!transfersBlocked, "Approvals are currently disabled");
super.approve(to, tokenId);
}
function setApprovalForAll(
address operator,
bool approved
) public virtual override {
require(!transfersBlocked, "Approvals are currently disabled");
super.setApprovalForAll(operator, approved);
}
function startTransfers() external {
_requireCallerIsContractOwner();
transfersBlocked = false;
}
function stopTransfers() external {
_requireCallerIsContractOwner();
transfersBlocked = true;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "./OwnablePermissions.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
abstract contract OwnableBasic is OwnablePermissions, Ownable {
function _requireCallerIsContractOwner() internal view virtual override {
_checkOwner();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @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;
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
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// 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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)
pragma solidity ^0.8.0;
/**
* @dev These functions deal with verification of Merkle Tree proofs.
*
* The tree and the proofs can be generated using our
* https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
* You will find a quickstart guide in the readme.
*
* WARNING: You should avoid using leaf values that are 64 bytes long prior to
* hashing, or use a hash function other than keccak256 for hashing leaves.
* This is because the concatenation of a sorted pair of internal nodes in
* the merkle tree could be reinterpreted as a leaf value.
* OpenZeppelin's JavaScript library generates merkle trees that are safe
* against this attack out of the box.
*/
library MerkleProof {
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
/**
* @dev Calldata version of {verify}
*
* _Available since v4.7._
*/
function verifyCalldata(
bytes32[] calldata proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leafs & pre-images are assumed to be sorted.
*
* _Available since v4.4._
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Calldata version of {processProof}
*
* _Available since v4.7._
*/
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
/**
* @dev Calldata version of {multiProofVerify}
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*
* _Available since v4.7._
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the merkle tree.
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
return hashes[totalHashes - 1];
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Calldata version of {processMultiProof}.
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the merkle tree.
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
return hashes[totalHashes - 1];
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/common/ERC2981.sol";
/**
* @title BasicRoyaltiesBase
* @author Limit Break, Inc.
* @dev Base functionality of an NFT mix-in contract implementing the most basic form of programmable royalties.
*/
abstract contract BasicRoyaltiesBase is ERC2981 {
event DefaultRoyaltySet(address indexed receiver, uint96 feeNumerator);
event TokenRoyaltySet(uint256 indexed tokenId, address indexed receiver, uint96 feeNumerator);
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual override {
super._setDefaultRoyalty(receiver, feeNumerator);
emit DefaultRoyaltySet(receiver, feeNumerator);
}
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual override {
super._setTokenRoyalty(tokenId, receiver, feeNumerator);
emit TokenRoyaltySet(tokenId, receiver, feeNumerator);
}
}
/**
* @title BasicRoyalties
* @author Limit Break, Inc.
* @notice Constructable BasicRoyalties Contract implementation.
*/
abstract contract BasicRoyalties is BasicRoyaltiesBase {
constructor(address receiver, uint96 feeNumerator) {
_setDefaultRoyalty(receiver, feeNumerator);
}
}
/**
* @title BasicRoyaltiesInitializable
* @author Limit Break, Inc.
* @notice Initializable BasicRoyalties Contract implementation to allow for EIP-1167 clones.
*/
abstract contract BasicRoyaltiesInitializable is BasicRoyaltiesBase {}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "../utils/AutomaticValidatorTransferApproval.sol";
import "../utils/CreatorTokenBase.sol";
import "../token/erc721/ERC721OpenZeppelin.sol";
import "../interfaces/ITransferValidatorSetTokenType.sol";
import {TOKEN_TYPE_ERC721} from "@limitbreak/permit-c/src/Constants.sol";
/**
* @title ERC721C
* @author Limit Break, Inc.
* @notice Extends OpenZeppelin's ERC721 implementation with Creator Token functionality, which
* allows the contract owner to update the transfer validation logic by managing a security policy in
* an external transfer validation security policy registry. See {CreatorTokenTransferValidator}.
*/
abstract contract ERC721C is ERC721OpenZeppelin, CreatorTokenBase, AutomaticValidatorTransferApproval {
/**
* @notice Overrides behavior of isApprovedFor all such that if an operator is not explicitly approved
* for all, the contract owner can optionally auto-approve the 721-C transfer validator for transfers.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool isApproved) {
isApproved = super.isApprovedForAll(owner, operator);
if (!isApproved) {
if (autoApproveTransfersFromValidator) {
isApproved = operator == address(getTransferValidator());
}
}
}
/**
* @notice Indicates whether the contract implements the specified interface.
* @dev Overrides supportsInterface in ERC165.
* @param interfaceId The interface id
* @return true if the contract implements the specified interface, false otherwise
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return
interfaceId == type(ICreatorToken).interfaceId ||
interfaceId == type(ICreatorTokenLegacy).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @notice Returns the function selector for the transfer validator's validation function to be called
* @notice for transaction simulation.
*/
function getTransferValidationFunction() external pure returns (bytes4 functionSignature, bool isViewFunction) {
functionSignature = bytes4(keccak256("validateTransfer(address,address,address,uint256)"));
isViewFunction = true;
}
/// @dev Ties the open-zeppelin _beforeTokenTransfer hook to more granular transfer validation logic
function _beforeTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize) internal virtual override {
for (uint256 i = 0; i < batchSize;) {
_validateBeforeTransfer(from, to, firstTokenId + i);
unchecked {
++i;
}
}
}
/// @dev Ties the open-zeppelin _afterTokenTransfer hook to more granular transfer validation logic
function _afterTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize) internal virtual override {
for (uint256 i = 0; i < batchSize;) {
_validateAfterTransfer(from, to, firstTokenId + i);
unchecked {
++i;
}
}
}
function _tokenType() internal pure override returns(uint16) {
return uint16(TOKEN_TYPE_ERC721);
}
}
/**
* @title ERC721CInitializable
* @author Limit Break, Inc.
* @notice Initializable implementation of ERC721C to allow for EIP-1167 proxy clones.
*/
abstract contract ERC721CInitializable is ERC721OpenZeppelinInitializable, CreatorTokenBase, AutomaticValidatorTransferApproval {
function initializeERC721(string memory name_, string memory symbol_) public override {
super.initializeERC721(name_, symbol_);
_emitDefaultTransferValidator();
_registerTokenType(getTransferValidator());
}
/**
* @notice Overrides behavior of isApprovedFor all such that if an operator is not explicitly approved
* for all, the contract owner can optionally auto-approve the 721-C transfer validator for transfers.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool isApproved) {
isApproved = super.isApprovedForAll(owner, operator);
if (!isApproved) {
if (autoApproveTransfersFromValidator) {
isApproved = operator == address(getTransferValidator());
}
}
}
/**
* @notice Indicates whether the contract implements the specified interface.
* @dev Overrides supportsInterface in ERC165.
* @param interfaceId The interface id
* @return true if the contract implements the specified interface, false otherwise
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return
interfaceId == type(ICreatorToken).interfaceId ||
interfaceId == type(ICreatorTokenLegacy).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @notice Returns the function selector for the transfer validator's validation function to be called
* @notice for transaction simulation.
*/
function getTransferValidationFunction() external pure returns (bytes4 functionSignature, bool isViewFunction) {
functionSignature = bytes4(keccak256("validateTransfer(address,address,address,uint256)"));
isViewFunction = true;
}
/// @dev Ties the open-zeppelin _beforeTokenTransfer hook to more granular transfer validation logic
function _beforeTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize) internal virtual override {
for (uint256 i = 0; i < batchSize;) {
_validateBeforeTransfer(from, to, firstTokenId + i);
unchecked {
++i;
}
}
}
/// @dev Ties the open-zeppelin _afterTokenTransfer hook to more granular transfer validation logic
function _afterTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize) internal virtual override {
for (uint256 i = 0; i < batchSize;) {
_validateAfterTransfer(from, to, firstTokenId + i);
unchecked {
++i;
}
}
}
function _tokenType() internal pure override returns(uint16) {
return uint16(TOKEN_TYPE_ERC721);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)
pragma solidity ^0.8.0;
import "../../interfaces/IERC2981.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
*
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
*
* Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
* fee is specified in basis points by default.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*
* _Available since v4.5._
*/
abstract contract ERC2981 is IERC2981, ERC165 {
struct RoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @inheritdoc IERC2981
*/
function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) {
RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];
if (royalty.receiver == address(0)) {
royalty = _defaultRoyaltyInfo;
}
uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();
return (royalty.receiver, royaltyAmount);
}
/**
* @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
* fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
* override.
*/
function _feeDenominator() internal pure virtual returns (uint96) {
return 10000;
}
/**
* @dev Sets the royalty information that all ids in this contract will default to.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: invalid receiver");
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Removes default royalty information.
*/
function _deleteDefaultRoyalty() internal virtual {
delete _defaultRoyaltyInfo;
}
/**
* @dev Sets the royalty information for a specific token id, overriding the global default.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/
function _setTokenRoyalty(
uint256 tokenId,
address receiver,
uint96 feeNumerator
) internal virtual {
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver != address(0), "ERC2981: Invalid parameters");
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Resets royalty information for the token id back to the global default.
*/
function _resetTokenRoyalty(uint256 tokenId) internal virtual {
delete _tokenRoyaltyInfo[tokenId];
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @dev Constant bytes32 value of 0x000...000
bytes32 constant ZERO_BYTES32 = bytes32(0);
/// @dev Constant value of 0
uint256 constant ZERO = 0;
/// @dev Constant value of 1
uint256 constant ONE = 1;
/// @dev Constant value representing an open order in storage
uint8 constant ORDER_STATE_OPEN = 0;
/// @dev Constant value representing a filled order in storage
uint8 constant ORDER_STATE_FILLED = 1;
/// @dev Constant value representing a cancelled order in storage
uint8 constant ORDER_STATE_CANCELLED = 2;
/// @dev Constant value representing the ERC721 token type for signatures and transfer hooks
uint256 constant TOKEN_TYPE_ERC721 = 721;
/// @dev Constant value representing the ERC1155 token type for signatures and transfer hooks
uint256 constant TOKEN_TYPE_ERC1155 = 1155;
/// @dev Constant value representing the ERC20 token type for signatures and transfer hooks
uint256 constant TOKEN_TYPE_ERC20 = 20;
/// @dev Constant value to mask the upper bits of a signature that uses a packed `vs` value to extract `s`
bytes32 constant UPPER_BIT_MASK = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
/// @dev EIP-712 typehash used for validating signature based stored approvals
bytes32 constant UPDATE_APPROVAL_TYPEHASH =
keccak256("UpdateApprovalBySignature(uint256 tokenType,address token,uint256 id,uint256 amount,uint256 nonce,address operator,uint256 approvalExpiration,uint256 sigDeadline,uint256 masterNonce)");
/// @dev EIP-712 typehash used for validating a single use permit without additional data
bytes32 constant SINGLE_USE_PERMIT_TYPEHASH =
keccak256("PermitTransferFrom(uint256 tokenType,address token,uint256 id,uint256 amount,uint256 nonce,address operator,uint256 expiration,uint256 masterNonce)");
/// @dev EIP-712 typehash used for validating a single use permit with additional data
string constant SINGLE_USE_PERMIT_TRANSFER_ADVANCED_TYPEHASH_STUB =
"PermitTransferFromWithAdditionalData(uint256 tokenType,address token,uint256 id,uint256 amount,uint256 nonce,address operator,uint256 expiration,uint256 masterNonce,";
/// @dev EIP-712 typehash used for validating an order permit that updates storage as it fills
string constant PERMIT_ORDER_ADVANCED_TYPEHASH_STUB =
"PermitOrderWithAdditionalData(uint256 tokenType,address token,uint256 id,uint256 amount,uint256 salt,address operator,uint256 expiration,uint256 masterNonce,";
/// @dev Pausable flag for stored approval transfers of ERC721 assets
uint256 constant PAUSABLE_APPROVAL_TRANSFER_FROM_ERC721 = 1 << 0;
/// @dev Pausable flag for stored approval transfers of ERC1155 assets
uint256 constant PAUSABLE_APPROVAL_TRANSFER_FROM_ERC1155 = 1 << 1;
/// @dev Pausable flag for stored approval transfers of ERC20 assets
uint256 constant PAUSABLE_APPROVAL_TRANSFER_FROM_ERC20 = 1 << 2;
/// @dev Pausable flag for single use permit transfers of ERC721 assets
uint256 constant PAUSABLE_PERMITTED_TRANSFER_FROM_ERC721 = 1 << 3;
/// @dev Pausable flag for single use permit transfers of ERC1155 assets
uint256 constant PAUSABLE_PERMITTED_TRANSFER_FROM_ERC1155 = 1 << 4;
/// @dev Pausable flag for single use permit transfers of ERC20 assets
uint256 constant PAUSABLE_PERMITTED_TRANSFER_FROM_ERC20 = 1 << 5;
/// @dev Pausable flag for order fill transfers of ERC1155 assets
uint256 constant PAUSABLE_ORDER_TRANSFER_FROM_ERC1155 = 1 << 6;
/// @dev Pausable flag for order fill transfers of ERC20 assets
uint256 constant PAUSABLE_ORDER_TRANSFER_FROM_ERC20 = 1 << 7;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
interface ITransferValidatorSetTokenType {
function setTokenTypeOfCollection(address collection, uint16 tokenType) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "../../access/OwnablePermissions.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
abstract contract ERC721OpenZeppelinBase is ERC721 {
// Token name
string internal _contractName;
// Token symbol
string internal _contractSymbol;
function name() public view virtual override returns (string memory) {
return _contractName;
}
function symbol() public view virtual override returns (string memory) {
return _contractSymbol;
}
function _setNameAndSymbol(string memory name_, string memory symbol_) internal {
_contractName = name_;
_contractSymbol = symbol_;
}
}
abstract contract ERC721OpenZeppelin is ERC721OpenZeppelinBase {
constructor(string memory name_, string memory symbol_) ERC721("", "") {
_setNameAndSymbol(name_, symbol_);
}
}
abstract contract ERC721OpenZeppelinInitializable is OwnablePermissions, ERC721OpenZeppelinBase {
error ERC721OpenZeppelinInitializable__AlreadyInitializedERC721();
/// @notice Specifies whether or not the contract is initialized
bool private _erc721Initialized;
/// @dev Initializes parameters of ERC721 tokens.
/// These cannot be set in the constructor because this contract is optionally compatible with EIP-1167.
function initializeERC721(string memory name_, string memory symbol_) public virtual {
_requireCallerIsContractOwner();
if(_erc721Initialized) {
revert ERC721OpenZeppelinInitializable__AlreadyInitializedERC721();
}
_erc721Initialized = true;
_setNameAndSymbol(name_, symbol_);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "../access/OwnablePermissions.sol";
import "../interfaces/ICreatorToken.sol";
import "../interfaces/ICreatorTokenLegacy.sol";
import "../interfaces/ITransferValidator.sol";
import "./TransferValidation.sol";
import "../interfaces/ITransferValidatorSetTokenType.sol";
/**
* @title CreatorTokenBase
* @author Limit Break, Inc.
* @notice CreatorTokenBaseV3 is an abstract contract that provides basic functionality for managing token
* transfer policies through an implementation of ICreatorTokenTransferValidator/ICreatorTokenTransferValidatorV2/ICreatorTokenTransferValidatorV3.
* This contract is intended to be used as a base for creator-specific token contracts, enabling customizable transfer
* restrictions and security policies.
*
* <h4>Features:</h4>
* <ul>Ownable: This contract can have an owner who can set and update the transfer validator.</ul>
* <ul>TransferValidation: Implements the basic token transfer validation interface.</ul>
*
* <h4>Benefits:</h4>
* <ul>Provides a flexible and modular way to implement custom token transfer restrictions and security policies.</ul>
* <ul>Allows creators to enforce policies such as account and codehash blacklists, whitelists, and graylists.</ul>
* <ul>Can be easily integrated into other token contracts as a base contract.</ul>
*
* <h4>Intended Usage:</h4>
* <ul>Use as a base contract for creator token implementations that require advanced transfer restrictions and
* security policies.</ul>
* <ul>Set and update the ICreatorTokenTransferValidator implementation contract to enforce desired policies for the
* creator token.</ul>
*
* <h4>Compatibility:</h4>
* <ul>Backward and Forward Compatible - V1/V2/V3 Creator Token Base will work with V1/V2/V3 Transfer Validators.</ul>
*/
abstract contract CreatorTokenBase is OwnablePermissions, TransferValidation, ICreatorToken {
/// @dev Thrown when setting a transfer validator address that has no deployed code.
error CreatorTokenBase__InvalidTransferValidatorContract();
/// @dev The default transfer validator that will be used if no transfer validator has been set by the creator.
address public constant DEFAULT_TRANSFER_VALIDATOR = address(0x721C008fdff27BF06E7E123956E2Fe03B63342e3);
/// @dev Used to determine if the default transfer validator is applied.
/// @dev Set to true when the creator sets a transfer validator address.
bool private isValidatorInitialized;
/// @dev Address of the transfer validator to apply to transactions.
address private transferValidator;
constructor() {
_emitDefaultTransferValidator();
_registerTokenType(DEFAULT_TRANSFER_VALIDATOR);
}
/**
* @notice Sets the transfer validator for the token contract.
*
* @dev Throws when provided validator contract is not the zero address and does not have code.
* @dev Throws when the caller is not the contract owner.
*
* @dev <h4>Postconditions:</h4>
* 1. The transferValidator address is updated.
* 2. The `TransferValidatorUpdated` event is emitted.
*
* @param transferValidator_ The address of the transfer validator contract.
*/
function setTransferValidator(address transferValidator_) public {
_requireCallerIsContractOwner();
bool isValidTransferValidator = transferValidator_.code.length > 0;
if(transferValidator_ != address(0) && !isValidTransferValidator) {
revert CreatorTokenBase__InvalidTransferValidatorContract();
}
emit TransferValidatorUpdated(address(getTransferValidator()), transferValidator_);
isValidatorInitialized = true;
transferValidator = transferValidator_;
_registerTokenType(transferValidator_);
}
/**
* @notice Returns the transfer validator contract address for this token contract.
*/
function getTransferValidator() public view override returns (address validator) {
validator = transferValidator;
if (validator == address(0)) {
if (!isValidatorInitialized) {
validator = DEFAULT_TRANSFER_VALIDATOR;
}
}
}
/**
* @dev Pre-validates a token transfer, reverting if the transfer is not allowed by this token's security policy.
* Inheriting contracts are responsible for overriding the _beforeTokenTransfer function, or its equivalent
* and calling _validateBeforeTransfer so that checks can be properly applied during token transfers.
*
* @dev Be aware that if the msg.sender is the transfer validator, the transfer is automatically permitted, as the
* transfer validator is expected to pre-validate the transfer.
*
* @dev Throws when the transfer doesn't comply with the collection's transfer policy, if the transferValidator is
* set to a non-zero address.
*
* @param caller The address of the caller.
* @param from The address of the sender.
* @param to The address of the receiver.
* @param tokenId The token id being transferred.
*/
function _preValidateTransfer(
address caller,
address from,
address to,
uint256 tokenId,
uint256 /*value*/) internal virtual override {
address validator = getTransferValidator();
if (validator != address(0)) {
if (msg.sender == validator) {
return;
}
ITransferValidator(validator).validateTransfer(caller, from, to, tokenId);
}
}
/**
* @dev Pre-validates a token transfer, reverting if the transfer is not allowed by this token's security policy.
* Inheriting contracts are responsible for overriding the _beforeTokenTransfer function, or its equivalent
* and calling _validateBeforeTransfer so that checks can be properly applied during token transfers.
*
* @dev Be aware that if the msg.sender is the transfer validator, the transfer is automatically permitted, as the
* transfer validator is expected to pre-validate the transfer.
*
* @dev Used for ERC20 and ERC1155 token transfers which have an amount value to validate in the transfer validator.
* @dev The `tokenId` for ERC20 tokens should be set to `0`.
*
* @dev Throws when the transfer doesn't comply with the collection's transfer policy, if the transferValidator is
* set to a non-zero address.
*
* @param caller The address of the caller.
* @param from The address of the sender.
* @param to The address of the receiver.
* @param tokenId The token id being transferred.
* @param amount The amount of token being transferred.
*/
function _preValidateTransfer(
address caller,
address from,
address to,
uint256 tokenId,
uint256 amount,
uint256 /*value*/) internal virtual override {
address validator = getTransferValidator();
if (validator != address(0)) {
if (msg.sender == validator) {
return;
}
ITransferValidator(validator).validateTransfer(caller, from, to, tokenId, amount);
}
}
function _tokenType() internal virtual pure returns(uint16);
function _registerTokenType(address validator) internal {
if (validator != address(0)) {
uint256 validatorCodeSize;
assembly {
validatorCodeSize := extcodesize(validator)
}
if(validatorCodeSize > 0) {
try ITransferValidatorSetTokenType(validator).setTokenTypeOfCollection(address(this), _tokenType()) {
} catch { }
}
}
}
/**
* @dev Used during contract deployment for constructable and cloneable creator tokens
* @dev to emit the `TransferValidatorUpdated` event signaling the validator for the contract
* @dev is the default transfer validator.
*/
function _emitDefaultTransferValidator() internal {
emit TransferValidatorUpdated(address(0), DEFAULT_TRANSFER_VALIDATOR);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "../access/OwnablePermissions.sol";
/**
* @title AutomaticValidatorTransferApproval
* @author Limit Break, Inc.
* @notice Base contract mix-in that provides boilerplate code giving the contract owner the
* option to automatically approve a 721-C transfer validator implementation for transfers.
*/
abstract contract AutomaticValidatorTransferApproval is OwnablePermissions {
/// @dev Emitted when the automatic approval flag is modified by the creator.
event AutomaticApprovalOfTransferValidatorSet(bool autoApproved);
/// @dev If true, the collection's transfer validator is automatically approved to transfer holder's tokens.
bool public autoApproveTransfersFromValidator;
/**
* @notice Sets if the transfer validator is automatically approved as an operator for all token owners.
*
* @dev Throws when the caller is not the contract owner.
*
* @param autoApprove If true, the collection's transfer validator will be automatically approved to
* transfer holder's tokens.
*/
function setAutomaticApprovalOfTransfersFromValidator(bool autoApprove) external {
_requireCallerIsContractOwner();
autoApproveTransfersFromValidator = autoApprove;
emit AutomaticApprovalOfTransferValidatorSet(autoApprove);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/utils/Context.sol";
abstract contract OwnablePermissions is Context {
function _requireCallerIsContractOwner() internal view virtual;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)
pragma solidity ^0.8.0;
import "../utils/introspection/IERC165.sol";
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*
* _Available since v4.5._
*/
interface IERC2981 is IERC165 {
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
*/
function royaltyInfo(uint256 tokenId, uint256 salePrice)
external
view
returns (address receiver, uint256 royaltyAmount);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/utils/Context.sol";
/**
* @title TransferValidation
* @author Limit Break, Inc.
* @notice A mix-in that can be combined with ERC-721 contracts to provide more granular hooks.
* Openzeppelin's ERC721 contract only provides hooks for before and after transfer. This allows
* developers to validate or customize transfers within the context of a mint, a burn, or a transfer.
*/
abstract contract TransferValidation is Context {
/// @dev Thrown when the from and to address are both the zero address.
error ShouldNotMintToBurnAddress();
/*************************************************************************/
/* Transfers Without Amounts */
/*************************************************************************/
/// @dev Inheriting contracts should call this function in the _beforeTokenTransfer function to get more granular hooks.
function _validateBeforeTransfer(address from, address to, uint256 tokenId) internal virtual {
bool fromZeroAddress = from == address(0);
bool toZeroAddress = to == address(0);
if(fromZeroAddress && toZeroAddress) {
revert ShouldNotMintToBurnAddress();
} else if(fromZeroAddress) {
_preValidateMint(_msgSender(), to, tokenId, msg.value);
} else if(toZeroAddress) {
_preValidateBurn(_msgSender(), from, tokenId, msg.value);
} else {
_preValidateTransfer(_msgSender(), from, to, tokenId, msg.value);
}
}
/// @dev Inheriting contracts should call this function in the _afterTokenTransfer function to get more granular hooks.
function _validateAfterTransfer(address from, address to, uint256 tokenId) internal virtual {
bool fromZeroAddress = from == address(0);
bool toZeroAddress = to == address(0);
if(fromZeroAddress && toZeroAddress) {
revert ShouldNotMintToBurnAddress();
} else if(fromZeroAddress) {
_postValidateMint(_msgSender(), to, tokenId, msg.value);
} else if(toZeroAddress) {
_postValidateBurn(_msgSender(), from, tokenId, msg.value);
} else {
_postValidateTransfer(_msgSender(), from, to, tokenId, msg.value);
}
}
/// @dev Optional validation hook that fires before a mint
function _preValidateMint(address caller, address to, uint256 tokenId, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires after a mint
function _postValidateMint(address caller, address to, uint256 tokenId, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires before a burn
function _preValidateBurn(address caller, address from, uint256 tokenId, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires after a burn
function _postValidateBurn(address caller, address from, uint256 tokenId, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires before a transfer
function _preValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires after a transfer
function _postValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 value) internal virtual {}
/*************************************************************************/
/* Transfers With Amounts */
/*************************************************************************/
/// @dev Inheriting contracts should call this function in the _beforeTokenTransfer function to get more granular hooks.
function _validateBeforeTransfer(address from, address to, uint256 tokenId, uint256 amount) internal virtual {
bool fromZeroAddress = from == address(0);
bool toZeroAddress = to == address(0);
if(fromZeroAddress && toZeroAddress) {
revert ShouldNotMintToBurnAddress();
} else if(fromZeroAddress) {
_preValidateMint(_msgSender(), to, tokenId, amount, msg.value);
} else if(toZeroAddress) {
_preValidateBurn(_msgSender(), from, tokenId, amount, msg.value);
} else {
_preValidateTransfer(_msgSender(), from, to, tokenId, amount, msg.value);
}
}
/// @dev Inheriting contracts should call this function in the _afterTokenTransfer function to get more granular hooks.
function _validateAfterTransfer(address from, address to, uint256 tokenId, uint256 amount) internal virtual {
bool fromZeroAddress = from == address(0);
bool toZeroAddress = to == address(0);
if(fromZeroAddress && toZeroAddress) {
revert ShouldNotMintToBurnAddress();
} else if(fromZeroAddress) {
_postValidateMint(_msgSender(), to, tokenId, amount, msg.value);
} else if(toZeroAddress) {
_postValidateBurn(_msgSender(), from, tokenId, amount, msg.value);
} else {
_postValidateTransfer(_msgSender(), from, to, tokenId, amount, msg.value);
}
}
/// @dev Optional validation hook that fires before a mint
function _preValidateMint(address caller, address to, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires after a mint
function _postValidateMint(address caller, address to, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires before a burn
function _preValidateBurn(address caller, address from, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires after a burn
function _postValidateBurn(address caller, address from, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires before a transfer
function _preValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}
/// @dev Optional validation hook that fires after a transfer
function _postValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 amount, uint256 value) internal virtual {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
interface ITransferValidator {
function applyCollectionTransferPolicy(address caller, address from, address to) external view;
function validateTransfer(address caller, address from, address to) external view;
function validateTransfer(address caller, address from, address to, uint256 tokenId) external view;
function validateTransfer(address caller, address from, address to, uint256 tokenId, uint256 amount) external;
function beforeAuthorizedTransfer(address operator, address token, uint256 tokenId) external;
function afterAuthorizedTransfer(address token, uint256 tokenId) external;
function beforeAuthorizedTransfer(address operator, address token) external;
function afterAuthorizedTransfer(address token) external;
function beforeAuthorizedTransfer(address token, uint256 tokenId) external;
function beforeAuthorizedTransferWithAmount(address token, uint256 tokenId, uint256 amount) external;
function afterAuthorizedTransferWithAmount(address token, uint256 tokenId) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
interface ICreatorTokenLegacy {
event TransferValidatorUpdated(address oldValidator, address newValidator);
function getTransferValidator() external view returns (address validator);
function setTransferValidator(address validator) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
interface ICreatorToken {
event TransferValidatorUpdated(address oldValidator, address newValidator);
function getTransferValidator() external view returns (address validator);
function setTransferValidator(address validator) external;
function getTransferValidationFunction() external view returns (bytes4 functionSignature, bool isViewFunction);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.2) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: address zero is not a valid owner");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _ownerOf(tokenId);
require(owner != address(0), "ERC721: invalid token ID");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
_requireMinted(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not token owner or approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_safeTransfer(from, to, tokenId, data);
}
/**
* @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.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _ownerOf(tokenId) != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId, 1);
// Check that tokenId was not minted by `_beforeTokenTransfer` hook
require(!_exists(tokenId), "ERC721: token already minted");
unchecked {
// Will not overflow unless all 2**256 token ids are minted to the same owner.
// Given that tokens are minted one by one, it is impossible in practice that
// this ever happens. Might change if we allow batch minting.
// The ERC fails to describe this case.
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId, 1);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId, 1);
// Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
owner = ERC721.ownerOf(tokenId);
// Clear approvals
delete _tokenApprovals[tokenId];
unchecked {
// Cannot overflow, as that would require more tokens to be burned/transferred
// out than the owner initially received through minting and transferring in.
_balances[owner] -= 1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId, 1);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId, 1);
// Check that tokenId was not transferred by `_beforeTokenTransfer` hook
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
// Clear approvals from the previous owner
delete _tokenApprovals[tokenId];
unchecked {
// `_balances[from]` cannot overflow for the same reason as described in `_burn`:
// `from`'s balance is the number of token held, which is at least one before the current
// transfer.
// `_balances[to]` could overflow in the conditions described in `_mint`. That would require
// all 2**256 token ids to be minted, which in practice is impossible.
_balances[from] -= 1;
_balances[to] += 1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId, 1);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits an {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` has not been minted yet.
*/
function _requireMinted(uint256 tokenId) internal view virtual {
require(_exists(tokenId), "ERC721: invalid token ID");
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
* - When `from` is zero, the tokens will be minted for `to`.
* - When `to` is zero, ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize
) internal virtual {}
/**
* @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
* - When `from` is zero, the tokens were minted for `to`.
* - When `to` is zero, ``from``'s tokens were burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize
) internal virtual {}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant
* being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such
* that `ownerOf(tokenId)` is `a`.
*/
// solhint-disable-next-line func-name-mixedcase
function __unsafe_increaseBalance(address account, uint256 amount) internal {
_balances[account] += amount;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: 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 caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": []
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"address","name":"_V1Address","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CreatorTokenBase__InvalidTransferValidatorContract","type":"error"},{"inputs":[],"name":"ShouldNotMintToBurnAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"autoApproved","type":"bool"}],"name":"AutomaticApprovalOfTransferValidatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"DefaultRoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"burned","type":"uint256[]"}],"name":"OneForOneBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"upgraded","type":"uint256[]"}],"name":"OneForOneClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"TokenRoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldValidator","type":"address"},{"indexed":false,"internalType":"address","name":"newValidator","type":"address"}],"name":"TransferValidatorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"upgraded","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"burned","type":"uint256[]"}],"name":"TwoForOneMint","type":"event"},{"inputs":[],"name":"DEFAULT_TRANSFER_VALIDATOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PER_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_START_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADABLE_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctionAmountPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"auctionMaxRefundLiability","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"},{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"auctionMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctionParticipation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"auctions","outputs":[{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"uint256","name":"discountRate","type":"uint256"},{"internalType":"uint256","name":"startingPrice","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"uint256","name":"lastPrice","type":"uint256"},{"internalType":"uint256","name":"amountPurchased","type":"uint256"},{"internalType":"uint256","name":"totalPaid","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"autoApproveTransfersFromValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"batchSafeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"batchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"claimAuctionRefund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"claimBurnedBreezes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"uint256","name":"discountRate","type":"uint256"},{"internalType":"uint256","name":"startingPrice","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"}],"name":"createAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dedicatedMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dedicatedPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dedicatedReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mintAmount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"dedicatedWhitelistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"dedicatedWhitelistStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"getAuctionPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getBurned","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransferValidationFunction","outputs":[{"internalType":"bytes4","name":"functionSignature","type":"bytes4"},{"internalType":"bool","name":"isViewFunction","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransferValidator","outputs":[{"internalType":"address","name":"validator","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"isApproved","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextPublicId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"toBurn","type":"uint256[]"}],"name":"oneForOneBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oneForOneBurnStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oneForOneClaimStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicMintTokensURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"autoApprove","type":"bool"}],"name":"setAutomaticApprovalOfTransfersFromValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"setDedicatedMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"name":"setDedicatedPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setDedicatedReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"setTokenRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"transferValidator_","type":"address"}],"name":"setTransferValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"setTravelersMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"price","type":"uint256"}],"name":"setTravelersPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setTravelersReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_upgradableTokensURI","type":"string"},{"internalType":"string","name":"_publicMintTokensURI","type":"string"}],"name":"setURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startDedicatedMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startOneForOneBurning","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startOneForOneClaiming","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTransfers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTravelersMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTwoForOneMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"auctionId","type":"uint256"}],"name":"stopAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopDedicatedMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopOneForOneBurning","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopOneForOneClaiming","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopTransfers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopTravelersMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopTwoForOneMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAuctionLiabilities","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMintedPublic","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMintedTravelers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transfersBlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"travelerPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"travelersMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"travelersReserve","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"travelersWhitelistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"travelersWhitelistMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"travelersWhitelistStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"toUpgrade","type":"uint256[]"},{"internalType":"uint256[]","name":"toBurn","type":"uint256[]"}],"name":"twoForOneMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"twoForOneMintStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"upgradableTokensURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6080604052600f80546001600160a01b0319908116737e41cb2eca64793532d6730b38d10575fd62b37f17909155601080548216730b884dfbade931b8ea5db16cc28434ec23f4054e1790556011805482167311c6afeb38b7b31a0e997aaac9a16538b86cde6317905560128054909116735d8f48b84937aeeee870e4376821956303f79903179055601480546001600160c81b03191660019081179091555f601581905560165561019060175560646018556100bf90611b39906104a6565b6019555f601a819055601b819055601c819055601d8190556023556024805460ff191660011790553480156100f2575f5ffd5b50604051615793380380615793833981016040819052610111916104fa565b604080518082018252601081526f26b4b23734b3b43a213932b2bd32ab1960811b60208083019190915282518084018452600481526326a12b1960e11b81830152835180830185525f80825285519384019095528483523394939284610177838261063e565b506001610184828261063e565b505050610197828261021a60201b60201c565b506101a29050610238565b6101bf73721c008fdff27bf06e7e123956e2fe03b63342e3610286565b6101c982826102fe565b506101d5905033610353565b6001600c55600d6101e6838261063e565b50600e6101f3838261063e565b50601380546001600160a01b0319166001600160a01b0392909216919091179055506106f8565b6006610226838261063e565b506007610233828261063e565b505050565b604080515f815273721c008fdff27bf06e7e123956e2fe03b63342e360208201527fcc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac910160405180910390a1565b6001600160a01b038116156102fb57803b80156102f9576040805163fb2de5d760e01b81523060048201526102d1602482015290516001600160a01b0384169163fb2de5d7916044808301925f92919082900301818387803b1580156102ea575f5ffd5b505af192505050801561023357505b505b50565b61030882826103a4565b6040516001600160601b03821681526001600160a01b038316907f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9060200160405180910390a25050565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6127106001600160601b03821611156104175760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b60648201526084015b60405180910390fd5b6001600160a01b03821661046d5760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c696420726563656976657200000000000000604482015260640161040e565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600955565b808201808211156104c557634e487b7160e01b5f52601160045260245ffd5b92915050565b634e487b7160e01b5f52604160045260245ffd5b80516001600160a01b03811681146104f5575f5ffd5b919050565b5f5f6040838503121561050b575f5ffd5b82516001600160401b03811115610520575f5ffd5b8301601f81018513610530575f5ffd5b80516001600160401b03811115610549576105496104cb565b604051601f8201601f19908116603f011681016001600160401b0381118282101715610577576105776104cb565b60405281815282820160200187101561058e575f5ffd5b8160208401602083015e5f602083830101528094505050506105b2602084016104df565b90509250929050565b600181811c908216806105cf57607f821691505b6020821081036105ed57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561023357805f5260205f20601f840160051c810160208510156106185750805b601f840160051c820191505b81811015610637575f8155600101610624565b5050505050565b81516001600160401b03811115610657576106576104cb565b61066b8161066584546105bb565b846105f3565b6020601f82116001811461069d575f83156106865750848201515b5f19600385901b1c1916600184901b178455610637565b5f84815260208120601f198516915b828110156106cc57878501518255602094850194600190920191016106ac565b50848210156106e957868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b61508e806107055f395ff3fe6080604052600436106104a5575f3560e01c806376c2ccc111610262578063a9439c081161014a578063cdf6a11e116100be578063ef533a2211610083578063ef533a2214610e29578063f2fde38b14610e3e578063f3993d1114610e5d578063f510f6ae14610e7c578063f645a95214610e9b578063fa7c01eb14610eba575f5ffd5b8063cdf6a11e14610d95578063d1aa7c5d14610db5578063d2c3dcfc14610dca578063e324353d14610df6578063e985e9c514610e0a575f5ffd5b8063b719b3301161010f578063b719b33014610cfd578063b83094bf14610d11578063b88d4fde14610d25578063bba8a59514610d44578063bf2db4c814610d57578063c87b56dd14610d76575f5ffd5b8063a9439c0814610c6d578063a9fc664e14610c8c578063ac65f10914610cab578063b02f8e5214610cbf578063b3d6e51414610cde575f5ffd5b8063917d009e116101e1578063a02b2b0e116101a6578063a02b2b0e14610bdd578063a22cb46514610bfc578063a2620c8914610c1b578063a3e9b78514610c30578063a82ce4fd14610c44578063a85e2b9d14610c58575f5ffd5b8063917d009e14610b6357806395d89b4114610b8257806396916dd814610b965780639c7aa88e14610baa5780639e05d24014610bbe575f5ffd5b806387607945116102275780638760794514610ae1578063890f3fc514610af45780638a157df314610b135780638c366d8c14610b325780638da5cb5b14610b46575f5ffd5b806376c2ccc114610a5a578063773dcb9814610a855780637adac0e614610a995780637fc7e21a14610aad57806383584aec14610acc575f5ffd5b80632fc1d0f91161039057806353179413116103045780635a4fee30116102c95780635a4fee30146109955780635ffc6575146109b45780636221d13c146109e85780636352211e14610a0857806370a0823114610a27578063715018a614610a46575f5ffd5b8063531794131461088757806353e8f948146108a0578063571a26a0146108b55780635944c7531461096257806359775b6114610981575f5ffd5b80633be2e117116103555780633be2e117146107f75780633fa783bd1461081757806342842e0e1461082b57806342b324b01461084a578063501883011461085f5780635033091f14610873575f5ffd5b80632fc1d0f91461077b57806330e891171461079a57806332cb6b0c146107b9578063342ecb3d146107ce57806337016250146107e2575f5ffd5b8063098144d41161042757806318215aa8116103ec57806318215aa8146106aa5780631d860744146106bf5780631f9f7a1e146106df57806323b872dd146106fe57806324cbaba81461071d5780632a55205a1461073d575f5ffd5b8063098144d41461063357806309d42b30146106475780630b25c9401461065b5780630c96d38e146106705780630d705df614610683575f5ffd5b806304ebe6ba1161046d57806304ebe6ba1461057157806306fdde03146105b5578063081812fc146105d65780630955da0a146105f5578063095ea7b314610614575f5ffd5b80630104ba22146104a957806301463546146104de57806301ffc9a71461051d57806302a373731461053c57806304634d8d14610552575b5f5ffd5b3480156104b4575f5ffd5b506014546104c990600160b01b900460ff1681565b60405190151581526020015b60405180910390f35b3480156104e9575f5ffd5b5061050573721c008fdff27bf06e7e123956e2fe03b63342e381565b6040516001600160a01b0390911681526020016104d5565b348015610528575f5ffd5b506104c961053736600461455b565b610ece565b348015610547575f5ffd5b50610550610ede565b005b34801561055d575f5ffd5b5061055061056c3660046145a2565b610fdf565b34801561057c575f5ffd5b506105a761058b3660046145d3565b602160209081525f928352604080842090915290825290205481565b6040519081526020016104d5565b3480156105c0575f5ffd5b506105c9610ff5565b6040516104d59190614629565b3480156105e1575f5ffd5b506105056105f036600461463b565b611085565b348015610600575f5ffd5b5061055061060f36600461463b565b6110aa565b34801561061f575f5ffd5b5061055061062e3660046145d3565b6110b7565b34801561063e575f5ffd5b50610505611114565b348015610652575f5ffd5b506105a7604581565b348015610666575f5ffd5b506105a7611b3981565b61055061067e366004614652565b61114e565b34801561068e575f5ffd5b506040805163657711f560e11b815260016020820152016104d5565b3480156106b5575f5ffd5b506105a7601a5481565b3480156106ca575f5ffd5b506014546104c990600160b81b900460ff1681565b3480156106ea575f5ffd5b506105506106f936600461463b565b611497565b348015610709575f5ffd5b50610550610718366004614672565b6116a4565b348015610728575f5ffd5b506014546104c990600160c01b900460ff1681565b348015610748575f5ffd5b5061075c610757366004614652565b6116da565b604080516001600160a01b0390931683526020830191909152016104d5565b348015610786575f5ffd5b5061055061079536600461463b565b611786565b3480156107a5575f5ffd5b506105a76107b436600461463b565b611793565b3480156107c4575f5ffd5b506105a761271081565b3480156107d9575f5ffd5b50610550611827565b3480156107ed575f5ffd5b506105a7601c5481565b348015610802575f5ffd5b506014546104c990600160a01b900460ff1681565b348015610822575f5ffd5b50610550611844565b348015610836575f5ffd5b50610550610845366004614672565b61185b565b348015610855575f5ffd5b506105a7601d5481565b34801561086a575f5ffd5b506105a7611875565b34801561087e575f5ffd5b506105506118a3565b348015610892575f5ffd5b506024546104c99060ff1681565b3480156108ab575f5ffd5b506105a760175481565b3480156108c0575f5ffd5b5061091c6108cf36600461463b565b601f6020525f908152604090208054600182015460028301546003840154600485015460058601546006870154600788015460089098015496979596949593949293919290919060ff1689565b60408051998a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e08301521515610100820152610120016104d5565b34801561096d575f5ffd5b5061055061097c3660046146ac565b6118c0565b34801561098c575f5ffd5b506105506118d3565b3480156109a0575f5ffd5b506105506109af36600461480f565b6118f0565b3480156109bf575f5ffd5b506105a76109ce3660046145d3565b60208080525f928352604080842090915290825290205481565b3480156109f3575f5ffd5b506008546104c990600160a81b900460ff1681565b348015610a13575f5ffd5b50610505610a2236600461463b565b61192f565b348015610a32575f5ffd5b506105a7610a41366004614892565b61198e565b348015610a51575f5ffd5b50610550611a12565b348015610a65575f5ffd5b506105a7610a74366004614892565b601e6020525f908152604090205481565b348015610a90575f5ffd5b50610550611a25565b348015610aa4575f5ffd5b50610550611a39565b348015610ab8575f5ffd5b50610550610ac73660046148ab565b611a50565b348015610ad7575f5ffd5b506105a7601b5481565b610550610aef36600461491c565b611c8d565b348015610aff575f5ffd5b50610550610b0e36600461463b565b611f52565b348015610b1e575f5ffd5b50610550610b2d366004614963565b611fa4565b348015610b3d575f5ffd5b506105c96121cf565b348015610b51575f5ffd5b50600b546001600160a01b0316610505565b348015610b6e575f5ffd5b506105a7610b7d36600461463b565b61225b565b348015610b8d575f5ffd5b506105c96123a7565b348015610ba1575f5ffd5b506105506123b6565b348015610bb5575f5ffd5b506105506123cd565b348015610bc9575f5ffd5b50610550610bd83660046149a9565b612679565b348015610be8575f5ffd5b50610550610bf736600461463b565b6126d9565b348015610c07575f5ffd5b50610550610c163660046149c2565b612722565b348015610c26575f5ffd5b506105a760195481565b348015610c3b575f5ffd5b5061055061277f565b348015610c4f575f5ffd5b506105c9612821565b348015610c63575f5ffd5b506105a760185481565b348015610c78575f5ffd5b50610550610c8736600461463b565b61282e565b348015610c97575f5ffd5b50610550610ca6366004614892565b612877565b348015610cb6575f5ffd5b50610550612930565b348015610cca575f5ffd5b50610550610cd93660046149ea565b612947565b348015610ce9575f5ffd5b50610550610cf836600461463b565b612bfa565b348015610d08575f5ffd5b506105a7612c4c565b348015610d1c575f5ffd5b50610550612c5c565b348015610d30575f5ffd5b50610550610d3f366004614a4d565b612c73565b610550610d52366004614a98565b612cab565b348015610d62575f5ffd5b50610550610d71366004614ad6565b612f77565b348015610d81575f5ffd5b506105c9610d9036600461463b565b612f98565b348015610da0575f5ffd5b506014546104c990600160a81b900460ff1681565b348015610dc0575f5ffd5b506105a760155481565b348015610dd5575f5ffd5b50610de9610de4366004614892565b613041565b6040516104d59190614b69565b348015610e01575f5ffd5b506105a76130aa565b348015610e15575f5ffd5b506104c9610e24366004614b7b565b6130db565b348015610e34575f5ffd5b506105a760165481565b348015610e49575f5ffd5b50610550610e58366004614892565b61313e565b348015610e68575f5ffd5b50610550610e77366004614ba3565b6131b4565b348015610e87575f5ffd5b50610550610e9636600461463b565b6131eb565b348015610ea6575f5ffd5b50610550610eb536600461463b565b61320d565b348015610ec5575f5ffd5b506105506134c1565b5f610ed8826134d8565b92915050565b610ee66134fc565b5f601c5411610f2f5760405162461bcd60e51b815260206004820152601060248201526f5365742070726963652066697273742160801b60448201526064015b60405180910390fd5b601654610f705760405162461bcd60e51b815260206004820152600f60248201526e53657420726f6f742066697273742160881b6044820152606401610f26565b601454600160b01b900460ff1615610fca5760405162461bcd60e51b815260206004820152601860248201527f53746f702074726176656c6572206d696e7420666972737400000000000000006044820152606401610f26565b6014805460ff60b81b1916600160b81b179055565b610fe76134fc565b610ff18282613504565b5050565b60606006805461100490614bfc565b80601f016020809104026020016040519081016040528092919081815260200182805461103090614bfc565b801561107b5780601f106110525761010080835404028352916020019161107b565b820191905f5260205f20905b81548152906001019060200180831161105e57829003601f168201915b5050505050905090565b5f61108f82613559565b505f908152600460205260409020546001600160a01b031690565b6110b26134fc565b601755565b60245460ff161561110a5760405162461bcd60e51b815260206004820181905260248201527f417070726f76616c73206172652063757272656e746c792064697361626c65646044820152606401610f26565b610ff182826135b7565b60085461010090046001600160a01b03168061114b5760085460ff1661114b575073721c008fdff27bf06e7e123956e2fe03b63342e35b90565b6111566136c6565b5f828152601f60205260409020600881015460ff166111ac5760405162461bcd60e51b815260206004820152601260248201527141756374696f6e206e6f742061637469766560701b6044820152606401610f26565b5f821180156111bc575060458211155b6111fe5760405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152606401610f26565b80544310801590611213575080600101544311155b6112585760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a5908185d58dd1a5bdb881c195c9a5bd960521b6044820152606401610f26565b60185460175461126a90612710614c42565b6112749190614c42565b6001836019546112849190614c55565b61128e9190614c42565b11156112dc5760405162461bcd60e51b815260206004820152601b60248201527f41756374696f6e61626c6520737570706c79206465706c6574656400000000006044820152606401610f26565b5f6112e68461225b565b90505f6112f38483614c68565b90508034101561133c5760405162461bcd60e51b8152602060048201526014602482015273125b9cdd59999a58da595b9d081c185e5b595b9d60621b6044820152606401610f26565b5f5b848110156113575761134f3361371f565b60010161133e565b50335f908152602080805260408083208884529091528120805486929061137f908490614c55565b9091555050335f908152602160209081526040808320888452909152812080548392906113ad908490614c55565b9091555050600583018290556006830180548591905f906113cf908490614c55565b9250508190555080836007015f8282546113e99190614c55565b909155505f90506113fa8234614c42565b90508015611489576040515f90339083908381818185875af1925050503d805f8114611441576040519150601f19603f3d011682016040523d82523d5f602084013e611446565b606091505b50509050806114875760405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b6044820152606401610f26565b505b50505050610ff16001600c55565b61149f6136c6565b335f908152602160209081526040808320848452909152902054806114f65760405162461bcd60e51b815260206004820152600d60248201526c4e6f20726566756e642064756560981b6044820152606401610f26565b335f908152602080805260408083208584529091529020548061155b5760405162461bcd60e51b815260206004820152601c60248201527f4e6f2061756374696f6e207075726368617365207265636f72646564000000006044820152606401610f26565b5f838152601f6020526040812060050154906115778383614c68565b90508084116115b85760405162461bcd60e51b815260206004820152600d60248201526c4e6f20726566756e642064756560981b6044820152606401610f26565b5f6115c38286614c42565b335f9081526021602090815260408083208a84528252808320869055601f9091528120600701805492935083929091906115fe908490614c42565b90915550506040515f90339083908381818185875af1925050503d805f8114611642576040519150601f19603f3d011682016040523d82523d5f602084013e611647565b606091505b50509050806116915760405162461bcd60e51b81526020600482015260166024820152751499599d5b99081d1c985b9cd9995c8819985a5b195960521b6044820152606401610f26565b5050505050506116a16001600c55565b50565b6116ae338261378e565b6116ca5760405162461bcd60e51b8152600401610f2690614c7f565b6116d58383836137eb565b505050565b5f828152600a602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b031692820192909252829161174e5750604080518082019091526009546001600160a01b0381168252600160a01b90046001600160601b031660208201525b60208101515f906127109061176c906001600160601b031687614c68565b6117769190614ccc565b91519350909150505b9250929050565b61178e6134fc565b601855565b5f818152601f602052604081206008810154829060ff1680156117ba575081600101544311155b80156117c7575081544310155b156117d7575060048101546117de565b5060058101545b60068201546117ed9082614c68565b8260070154111561181e5760068201546118079082614c68565b82600701546118169190614c42565b949350505050565b505f9392505050565b61182f6134fc565b6014805460ff60c01b1916600160c01b179055565b61184c6134fc565b6014805460ff60b81b19169055565b6116d583838360405180602001604052805f815250612c73565b5f47816118806130aa565b90508082111561189b576118948183614c42565b9250505090565b5f9250505090565b6118ab6134fc565b6014805460ff60a01b1916600160a01b179055565b6118c86134fc565b6116d5838383613962565b6118db6134fc565b6014805460ff60a81b1916600160a81b179055565b5f5b825181101561192857611920858585848151811061191257611912614ceb565b602002602001015185612c73565b6001016118f2565b5050505050565b5f818152600260205260408120546001600160a01b031680610ed85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610f26565b5f6001600160a01b0382166119f75760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610f26565b506001600160a01b03165f9081526003602052604090205490565b611a1a6139bc565b611a235f613a16565b565b611a2d6134fc565b6024805460ff19169055565b611a416134fc565b6024805460ff19166001179055565b611a586136c6565b601454600160a01b900460ff16611ab15760405162461bcd60e51b815260206004820181905260248201527f4f6e6520666f72206f6e65206275726e20686173206e6f7420737461727465646044820152606401610f26565b601454600160c01b900460ff1615611b0b5760405162461bcd60e51b815260206004820152601c60248201527f54776f20666f72206f6e65206d696e74206861732073746172746564000000006044820152606401610f26565b5f815111611b4e5760405162461bcd60e51b815260206004820152601060248201526f456d707479206275726e20617272617960801b6044820152606401610f26565b5f5b8151811015611c49576013546001600160a01b03166342842e0e3360145485516001600160a01b0390911690869086908110611b8e57611b8e614ceb565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064015f604051808303815f87803b158015611be5575f5ffd5b505af1158015611bf7573d5f5f3e3d5ffd5b5050335f908152602260205260409020845190925084915083908110611c1f57611c1f614ceb565b6020908102919091018101518254600181810185555f948552929093209092019190915501611b50565b507faa0422371149feb53467e40d00ddab7f792ebba34ad9666d508f23ce8a0d7a1e3382604051611c7b929190614cff565b60405180910390a16116a16001600c55565b611c956136c6565b601454600160b81b900460ff16611cfa5760405162461bcd60e51b8152602060048201526024808201527f4465646963617465642077686974656c697374206d696e74206e6f74207374616044820152631c9d195960e21b6064820152608401610f26565b601454600160b01b900460ff1615611d625760405162461bcd60e51b815260206004820152602560248201527f54726176656c65722077686974656c697374206d696e74207374696c6c206f6e604482015264676f696e6760d81b6064820152608401610f26565b5f601c5411611db35760405162461bcd60e51b815260206004820152601760248201527f446564696361746564207072696365206e6f74207365740000000000000000006044820152606401610f26565b612710600184601954611dc69190614c55565b611dd09190614c42565b1115611e1e5760405162461bcd60e51b815260206004820152601960248201527f44656469636174656420737570706c79206578636565646564000000000000006044820152606401610f26565b6040516bffffffffffffffffffffffff193360601b1660208201525f90603401604051602081830303815290604052805190602001209050611e968383808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506016549150849050613a67565b611edc5760405162461bcd60e51b815260206004820152601760248201527624b73b30b634b2103bb434ba32b634b9ba10383937b7b360491b6044820152606401610f26565b601c54611ee99085614c68565b3414611f2b5760405162461bcd60e51b8152602060048201526011602482015270125b98dbdc9c9958dd081c185e5b595b9d607a1b6044820152606401610f26565b5f5b84811015611f4657611f3e3361371f565b600101611f2d565b50506116d56001600c55565b611f5a6134fc565b5f8111611f9f5760405162461bcd60e51b815260206004820152601360248201527250726963652063616e2774206265207a65726f60681b6044820152606401610f26565b601c55565b611fac6134fc565b5f8111611ffb5760405162461bcd60e51b815260206004820152601a60248201527f4d696e2070726963652063616e2774207265616368207a65726f0000000000006044820152606401610f26565b80821161205c5760405162461bcd60e51b815260206004820152602960248201527f5374617274207072696365206d75737420626520686967686572207468616e206044820152686d696e20707269636560b81b6064820152608401610f26565b438510156120b75760405162461bcd60e51b815260206004820152602260248201527f43616e277420737461727420616e2061756374696f6e20696e207468652070616044820152611cdd60f21b6064820152608401610f26565b8385106121125760405162461bcd60e51b8152602060048201526024808201527f537461727420626c6f636b206d757374206265206265666f726520656e6420626044820152636c6f636b60e01b6064820152608401610f26565b60408051610120810182528681526020808201878152828401878152606084018781526080850187815260a086018981525f60c0880181815260e0890182815260016101008b01818152602380548652601f909b529b84209a518b559751978a0197909755945160028901559251600388015590516004870155516005860155905160068501559051600784015592516008909201805460ff1916921515929092179091558054916121c383614d22565b91905055505050505050565b600e80546121dc90614bfc565b80601f016020809104026020016040519081016040528092919081815260200182805461220890614bfc565b80156122535780601f1061222a57610100808354040283529160200191612253565b820191905f5260205f20905b81548152906001019060200180831161223657829003601f168201915b505050505081565b5f818152601f6020526040812080544310156122af5760405162461bcd60e51b8152602060048201526013602482015272105d58dd1a5bdb881b9bdd081cdd185c9d1959606a1b6044820152606401610f26565b80600101544311156122f35760405162461bcd60e51b815260206004820152600d60248201526c105d58dd1a5bdb88195b991959609a1b6044820152606401610f26565b600881015460ff1661233a5760405162461bcd60e51b815260206004820152601060248201526f105d58dd1a5bdb88191a5cd8589b195960821b6044820152606401610f26565b80545f906123489043614c42565b90505f81836002015461235b9190614c68565b90505f81846003015411612373578360040154612383565b8184600301546123839190614c42565b9050836004015481101561239b57836004015461239d565b805b9695505050505050565b60606007805461100490614bfc565b6123be6134fc565b6014805460ff60b01b19169055565b6123d56136c6565b6123dd6134fc565b5f6123e6611875565b90505f811161242f5760405162461bcd60e51b81526020600482015260156024820152744e6f20776974686472617761626c652066756e647360581b6044820152606401610f26565b5f6103e861243e83604b614c68565b6124489190614ccc565b90505f6103e861245984604b614c68565b6124639190614ccc565b90505f6103e8612474856005614c68565b61247e9190614ccc565b90505f818361248d8688614c42565b6124979190614c42565b6124a19190614c42565b6011546040519192505f916001600160a01b039091169083908381818185875af1925050503d805f81146124f0576040519150601f19603f3d011682016040523d82523d5f602084013e6124f5565b606091505b50509050806125165760405162461bcd60e51b8152600401610f2690614d3a565b600f546040515f916001600160a01b03169087908381818185875af1925050503d805f8114612560576040519150601f19603f3d011682016040523d82523d5f602084013e612565565b606091505b50509050806125865760405162461bcd60e51b8152600401610f2690614d3a565b6010546040515f916001600160a01b03169087908381818185875af1925050503d805f81146125d0576040519150601f19603f3d011682016040523d82523d5f602084013e6125d5565b606091505b50509050806125f65760405162461bcd60e51b8152600401610f2690614d3a565b6012546040515f916001600160a01b03169087908381818185875af1925050503d805f8114612640576040519150601f19603f3d011682016040523d82523d5f602084013e612645565b606091505b50509050806126665760405162461bcd60e51b8152600401610f2690614d3a565b505050505050505050611a236001600c55565b6126816134fc565b60088054821515600160a81b0260ff60a81b199091161790556040517f6787c7f9a80aa0f5ceddab2c54f1f5169c0b88e75dd5e19d5e858a64144c7dbc906126ce90831515815260200190565b60405180910390a150565b6126e16134fc565b8061271d5760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610f26565b601555565b60245460ff16156127755760405162461bcd60e51b815260206004820181905260248201527f417070726f76616c73206172652063757272656e746c792064697361626c65646044820152606401610f26565b610ff18282613a7c565b6127876134fc565b5f601d54116127cb5760405162461bcd60e51b815260206004820152601060248201526f5365742070726963652066697273742160801b6044820152606401610f26565b60155461280c5760405162461bcd60e51b815260206004820152600f60248201526e53657420726f6f742066697273742160881b6044820152606401610f26565b6014805460ff60b01b1916600160b01b179055565b600d80546121dc90614bfc565b6128366134fc565b806128725760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610f26565b601655565b61287f6134fc565b6001600160a01b038116803b1515901580159061289a575080155b156128b8576040516332483afb60e01b815260040160405180910390fd5b7fcc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac6128e1611114565b604080516001600160a01b03928316815291851660208301520160405180910390a1600880546001600160a01b038416610100026001600160a81b0319909116176001179055610ff182613a87565b6129386134fc565b6014805460ff60a81b19169055565b61294f6136c6565b601454600160c01b900460ff166129a85760405162461bcd60e51b815260206004820181905260248201527f54776f20666f72206f6e65206d696e7420686173206e6f7420737461727465646044820152606401610f26565b80518251146129ed5760405162461bcd60e51b8152602060048201526011602482015270082e4e4c2f2e640daeae6e840dac2e8c6d607b1b6044820152606401610f26565b5f825111612a335760405162461bcd60e51b8152602060048201526013602482015272456d707479207570677261646520617272617960681b6044820152606401610f26565b5f5b8251811015612bb5576013546001600160a01b03166342842e0e3360145485516001600160a01b0390911690869086908110612a7357612a73614ceb565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064015f604051808303815f87803b158015612aca575f5ffd5b505af1158015612adc573d5f5f3e3d5ffd5b50506013546001600160a01b031691506342842e0e90503360145486516001600160a01b0390911690879086908110612b1757612b17614ceb565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064015f604051808303815f87803b158015612b6e575f5ffd5b505af1158015612b80573d5f5f3e3d5ffd5b50505050612bad612b8e3390565b848381518110612ba057612ba0614ceb565b6020026020010151613b05565b600101612a35565b507eae92e6ab53b71163322cdd6ac1cc3d3a76a6a0b4d2c9a670eaf332878871d6338383604051612be893929190614d63565b60405180910390a1610ff16001600c55565b612c026134fc565b5f8111612c475760405162461bcd60e51b815260206004820152601360248201527250726963652063616e2774206265207a65726f60681b6044820152606401610f26565b601d55565b612c59611b396001614c55565b81565b612c646134fc565b6014805460ff60a01b19169055565b612c7d338361378e565b612c995760405162461bcd60e51b8152600401610f2690614c7f565b612ca584848484613b1e565b50505050565b612cb36136c6565b601454600160b01b900460ff16612d185760405162461bcd60e51b8152602060048201526024808201527f54726176656c6572732077686974656c697374206d696e74206e6f74207374616044820152631c9d195960e21b6064820152608401610f26565b5f601d5411612d695760405162461bcd60e51b815260206004820152601760248201527f54726176656c657273207072696365206e6f74207365740000000000000000006044820152606401610f26565b335f908152601e602052604090205415612dc55760405162461bcd60e51b815260206004820152601760248201527f54726176656c657220616c7265616479206d696e7465640000000000000000006044820152606401610f26565b601754601b54612dd6906001614c55565b1115612e245760405162461bcd60e51b815260206004820152601960248201527f54726176656c65727320737570706c79206465706c65746564000000000000006044820152606401610f26565b6040516bffffffffffffffffffffffff193360601b1660208201525f90603401604051602081830303815290604052805190602001209050612e9c8383808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506015549150849050613a67565b612ee25760405162461bcd60e51b815260206004820152601760248201527624b73b30b634b2103bb434ba32b634b9ba10383937b7b360491b6044820152606401610f26565b601d543414612f275760405162461bcd60e51b8152602060048201526011602482015270125b98dbdc9c9958dd081c185e5b595b9d607a1b6044820152606401610f26565b612f303361371f565b335f908152601e60205260408120805460019290612f4f908490614c55565b925050819055506001601b5f828254612f689190614c55565b90915550506001600c55505050565b612f7f6134fc565b600d612f8b8382614ddc565b50600e6116d58282614ddc565b5f818152600260205260409020546060906001600160a01b0316612ff65760405162461bcd60e51b81526020600482015260156024820152742a37b5b2b7103237b2b9903737ba1032bc34b9ba1760591b6044820152606401610f26565b611b39821161303157600d61300a83613b51565b60405160200161301b929190614e96565b6040516020818303038152906040529050919050565b600e61300a83613b51565b919050565b6001600160a01b0381165f9081526022602090815260409182902080548351818402810184019094528084526060939283018282801561309e57602002820191905f5260205f20905b81548152602001906001019080831161308a575b50505050509050919050565b5f80805b6023548110156130d5576130c181611793565b6130cb9083614c55565b91506001016130ae565b50919050565b6001600160a01b038281165f9081526005602090815260408083209385168352929052205460ff1680610ed857600854600160a81b900460ff1615610ed857613122611114565b6001600160a01b0316826001600160a01b031614905092915050565b6131466139bc565b6001600160a01b0381166131ab5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610f26565b6116a181613a16565b5f5b8151811015612ca5576131e384848484815181106131d6576131d6614ceb565b60200260200101516116a4565b6001016131b6565b6131f36134fc565b5f908152601f60205260409020600801805460ff19169055565b6132156136c6565b601454600160a81b900460ff166132785760405162461bcd60e51b815260206004820152602160248201527f4f6e6520666f72206f6e6520636c61696d20686173206e6f74207374617274656044820152601960fa1b6064820152608401610f26565b335f90815260226020526040902054806132c75760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b6044820152606401610f26565b5f821180156132d65750808211155b6133125760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a590818dbdd5b9d609a1b6044820152606401610f26565b5f826001600160401b0381111561332b5761332b6146e5565b604051908082528060200260200182016040528015613354578160200160208202803683370190505b5090505f5b838110156133c357335f90815260226020526040812080548390811061338157613381614ceb565b905f5260205f200154905061339c6133963390565b82613b05565b808383815181106133af576133af614ceb565b602090810291909101015250600101613359565b507f6e95c62c71a9ae70ebfd5db27ca5b352f2a8b7077fe17c8cc0e94b5890e596f133826040516133f5929190614cff565b60405180910390a1825b8281101561346e57335f90815260226020526040902080548290811061342757613427614ceb565b5f9182526020808320909101543383526022909152604090912061344b8684614c42565b8154811061345b5761345b614ceb565b5f918252602090912001556001016133ff565b505f5b838110156134b457335f90815260226020526040902080548061349657613496614f16565b5f8281526020812082015f1990810191909155019055600101613471565b5050506116a16001600c55565b6134c96134fc565b6014805460ff60c01b19169055565b5f6001600160e01b0319821663152a902d60e11b1480610ed85750610ed882613be0565b611a236139bc565b61350e8282613c1f565b6040516001600160601b03821681526001600160a01b038316907f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9060200160405180910390a25050565b5f818152600260205260409020546001600160a01b03166116a15760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610f26565b5f6135c18261192f565b9050806001600160a01b0316836001600160a01b03160361362e5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610f26565b336001600160a01b038216148061364a575061364a81336130db565b6136bc5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610f26565b6116d58383613cd9565b6002600c54036137185760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610f26565b6002600c55565b612710601954111561376b5760405162461bcd60e51b8152602060048201526015602482015274139bc81c1d589b1a58c81cdd5c1c1b1e481b19599d605a1b6044820152606401610f26565b61377781601954613b05565b60198054905f61378683614d22565b919050555050565b5f5f6137998361192f565b9050806001600160a01b0316846001600160a01b031614806137c057506137c081856130db565b806118165750836001600160a01b03166137d984611085565b6001600160a01b031614949350505050565b826001600160a01b03166137fe8261192f565b6001600160a01b0316146138245760405162461bcd60e51b8152600401610f2690614f2a565b6001600160a01b0382166138865760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610f26565b6138938383836001613d46565b826001600160a01b03166138a68261192f565b6001600160a01b0316146138cc5760405162461bcd60e51b8152600401610f2690614f2a565b5f81815260046020908152604080832080546001600160a01b03199081169091556001600160a01b038781168086526003855283862080545f1901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a46116d58383836001613dca565b61396d838383613df0565b6040516001600160601b03821681526001600160a01b0383169084907f7f5b076c952c0ec86e5425963c1326dd0f03a3595c19f81d765e8ff559a6e33c906020015b60405180910390a3505050565b600b546001600160a01b03163314611a235760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f26565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f82613a738584613eba565b14949350505050565b610ff1338383613efc565b6001600160a01b038116156116a157803b8015610ff1576040805163fb2de5d760e01b81523060048201526102d1602482015290516001600160a01b0384169163fb2de5d7916044808301925f92919082900301818387803b158015613aeb575f5ffd5b505af1925050508015613afc575060015b15610ff1575050565b610ff1828260405180602001604052805f815250613fc1565b613b298484846137eb565b613b3584848484613ff3565b612ca55760405162461bcd60e51b8152600401610f2690614f6f565b60605f613b5d836140f0565b60010190505f816001600160401b03811115613b7b57613b7b6146e5565b6040519080825280601f01601f191660200182016040528015613ba5576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084613baf57509392505050565b5f6001600160e01b03198216632b435fdb60e21b1480613c1057506001600160e01b0319821663503e914d60e11b145b80610ed85750610ed8826141c7565b6127106001600160601b0382161115613c4a5760405162461bcd60e51b8152600401610f2690614fc1565b6001600160a01b038216613ca05760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610f26565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600955565b5f81815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190613d0d8261192f565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b613d5284848484614216565b6001600160a01b03841615801590613d7257506001600160a01b03831615155b15612ca55760245460ff1615612ca55760405162461bcd60e51b815260206004820181905260248201527f5472616e7366657273206172652063757272656e746c792064697361626c65646044820152606401610f26565b5f5b8181101561192857613de88585613de38487614c55565b61423c565b600101613dcc565b6127106001600160601b0382161115613e1b5760405162461bcd60e51b8152600401610f2690614fc1565b6001600160a01b038216613e715760405162461bcd60e51b815260206004820152601b60248201527f455243323938313a20496e76616c696420706172616d657465727300000000006044820152606401610f26565b6040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182525f968752600a90529190942093519051909116600160a01b029116179055565b5f81815b8451811015613ef457613eea82868381518110613edd57613edd614ceb565b602002602001015161428a565b9150600101613ebe565b509392505050565b816001600160a01b0316836001600160a01b031603613f5d5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610f26565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3191016139af565b613fcb83836142b9565b613fd75f848484613ff3565b6116d55760405162461bcd60e51b8152600401610f2690614f6f565b5f6001600160a01b0384163b156140e557604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061403690339089908890889060040161500b565b6020604051808303815f875af1925050508015614070575060408051601f3d908101601f1916820190925261406d9181019061503d565b60015b6140cb573d80801561409d576040519150601f19603f3d011682016040523d82523d5f602084013e6140a2565b606091505b5080515f036140c35760405162461bcd60e51b8152600401610f2690614f6f565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611816565b506001949350505050565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061412e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831061415a576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061417857662386f26fc10000830492506010015b6305f5e1008310614190576305f5e100830492506008015b61271083106141a457612710830492506004015b606483106141b6576064830492506002015b600a8310610ed85760010192915050565b5f6001600160e01b031982166380ac58cd60e01b14806141f757506001600160e01b03198216635b5e139f60e01b145b80610ed857506301ffc9a760e01b6001600160e01b0319831614610ed8565b5f5b8181101561192857614234858561422f8487614c55565b614457565b600101614218565b6001600160a01b0383811615908316158180156142565750805b1561427457604051635cbd944160e01b815260040160405180910390fd5b8115614280575b611928565b8061427b57611928565b5f8183106142a4575f8281526020849052604090206142b2565b5f8381526020839052604090205b9392505050565b6001600160a01b03821661430f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610f26565b5f818152600260205260409020546001600160a01b0316156143735760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610f26565b6143805f83836001613d46565b5f818152600260205260409020546001600160a01b0316156143e45760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610f26565b6001600160a01b0382165f81815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4610ff15f83836001613dca565b6001600160a01b0383811615908316158180156144715750805b1561448f57604051635cbd944160e01b815260040160405180910390fd5b8161427b578061427b5761192833868686345f6144aa611114565b90506001600160a01b0381161561453e576001600160a01b03811633036144d15750611928565b60405163657711f560e11b81526001600160a01b038781166004830152868116602483015285811660448301526064820185905282169063caee23ea906084015f6040518083038186803b158015614527575f5ffd5b505afa158015614539573d5f5f3e3d5ffd5b505050505b505050505050565b6001600160e01b0319811681146116a1575f5ffd5b5f6020828403121561456b575f5ffd5b81356142b281614546565b80356001600160a01b038116811461303c575f5ffd5b80356001600160601b038116811461303c575f5ffd5b5f5f604083850312156145b3575f5ffd5b6145bc83614576565b91506145ca6020840161458c565b90509250929050565b5f5f604083850312156145e4575f5ffd5b6145ed83614576565b946020939093013593505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6142b260208301846145fb565b5f6020828403121561464b575f5ffd5b5035919050565b5f5f60408385031215614663575f5ffd5b50508035926020909101359150565b5f5f5f60608486031215614684575f5ffd5b61468d84614576565b925061469b60208501614576565b929592945050506040919091013590565b5f5f5f606084860312156146be575f5ffd5b833592506146ce60208501614576565b91506146dc6040850161458c565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715614721576147216146e5565b604052919050565b5f82601f830112614738575f5ffd5b81356001600160401b03811115614751576147516146e5565b8060051b614761602082016146f9565b9182526020818501810192908101908684111561477c575f5ffd5b6020860192505b8383101561239d578235825260209283019290910190614783565b5f82601f8301126147ad575f5ffd5b8135602083015f5f6001600160401b038411156147cc576147cc6146e5565b50601f8301601f19166020016147e1816146f9565b9150508281528583830111156147f5575f5ffd5b828260208301375f92810160200192909252509392505050565b5f5f5f5f60808587031215614822575f5ffd5b61482b85614576565b935061483960208601614576565b925060408501356001600160401b03811115614853575f5ffd5b61485f87828801614729565b92505060608501356001600160401b0381111561487a575f5ffd5b6148868782880161479e565b91505092959194509250565b5f602082840312156148a2575f5ffd5b6142b282614576565b5f602082840312156148bb575f5ffd5b81356001600160401b038111156148d0575f5ffd5b61181684828501614729565b5f5f83601f8401126148ec575f5ffd5b5081356001600160401b03811115614902575f5ffd5b6020830191508360208260051b850101111561177f575f5ffd5b5f5f5f6040848603121561492e575f5ffd5b8335925060208401356001600160401b0381111561494a575f5ffd5b614956868287016148dc565b9497909650939450505050565b5f5f5f5f5f60a08688031215614977575f5ffd5b505083359560208501359550604085013594606081013594506080013592509050565b8035801515811461303c575f5ffd5b5f602082840312156149b9575f5ffd5b6142b28261499a565b5f5f604083850312156149d3575f5ffd5b6149dc83614576565b91506145ca6020840161499a565b5f5f604083850312156149fb575f5ffd5b82356001600160401b03811115614a10575f5ffd5b614a1c85828601614729565b92505060208301356001600160401b03811115614a37575f5ffd5b614a4385828601614729565b9150509250929050565b5f5f5f5f60808587031215614a60575f5ffd5b614a6985614576565b9350614a7760208601614576565b92506040850135915060608501356001600160401b0381111561487a575f5ffd5b5f5f60208385031215614aa9575f5ffd5b82356001600160401b03811115614abe575f5ffd5b614aca858286016148dc565b90969095509350505050565b5f5f60408385031215614ae7575f5ffd5b82356001600160401b03811115614afc575f5ffd5b614b088582860161479e565b92505060208301356001600160401b03811115614b23575f5ffd5b614a438582860161479e565b5f8151808452602084019350602083015f5b82811015614b5f578151865260209586019590910190600101614b41565b5093949350505050565b602081525f6142b26020830184614b2f565b5f5f60408385031215614b8c575f5ffd5b614b9583614576565b91506145ca60208401614576565b5f5f5f60608486031215614bb5575f5ffd5b614bbe84614576565b9250614bcc60208501614576565b915060408401356001600160401b03811115614be6575f5ffd5b614bf286828701614729565b9150509250925092565b600181811c90821680614c1057607f821691505b6020821081036130d557634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b81810381811115610ed857610ed8614c2e565b80820180821115610ed857610ed8614c2e565b8082028115828204841417610ed857610ed8614c2e565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b5f82614ce657634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b03831681526040602082018190525f9061181690830184614b2f565b5f60018201614d3357614d33614c2e565b5060010190565b6020808252600f908201526e151c985b9cd9995c8819985a5b1959608a1b604082015260600190565b6001600160a01b03841681526060602082018190525f90614d8690830185614b2f565b828103604084015261239d8185614b2f565b601f8211156116d557805f5260205f20601f840160051c81016020851015614dbd5750805b601f840160051c820191505b81811015611928575f8155600101614dc9565b81516001600160401b03811115614df557614df56146e5565b614e0981614e038454614bfc565b84614d98565b6020601f821160018114614e3b575f8315614e245750848201515b5f19600385901b1c1916600184901b178455611928565b5f84815260208120601f198516915b82811015614e6a5787850151825560209485019460019092019101614e4a565b5084821015614e8757868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f5f8454614ea381614bfc565b600182168015614eba5760018114614ecf57614efc565b60ff1983168652811515820286019350614efc565b875f5260205f205f5b83811015614ef457815488820152600190910190602001614ed8565b505081860193505b50505083518060208601835e5f9101908152949350505050565b634e487b7160e01b5f52603160045260245ffd5b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252602a908201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646040820152692073616c65507269636560b01b606082015260800190565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f9061239d908301846145fb565b5f6020828403121561504d575f5ffd5b81516142b28161454656fea2646970667358221220353d36333563b52d9a0ad9616be4f08ad06a9e096a5deeed9f8b5050ec87fb7664736f6c634300081e00330000000000000000000000000000000000000000000000000000000000000040000000000000000000000000d9c036e9eef725e5aca4a22239a23feb47c3f05d000000000000000000000000000000000000000000000000000000000000000b706c616365686f6c646572000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106104a5575f3560e01c806376c2ccc111610262578063a9439c081161014a578063cdf6a11e116100be578063ef533a2211610083578063ef533a2214610e29578063f2fde38b14610e3e578063f3993d1114610e5d578063f510f6ae14610e7c578063f645a95214610e9b578063fa7c01eb14610eba575f5ffd5b8063cdf6a11e14610d95578063d1aa7c5d14610db5578063d2c3dcfc14610dca578063e324353d14610df6578063e985e9c514610e0a575f5ffd5b8063b719b3301161010f578063b719b33014610cfd578063b83094bf14610d11578063b88d4fde14610d25578063bba8a59514610d44578063bf2db4c814610d57578063c87b56dd14610d76575f5ffd5b8063a9439c0814610c6d578063a9fc664e14610c8c578063ac65f10914610cab578063b02f8e5214610cbf578063b3d6e51414610cde575f5ffd5b8063917d009e116101e1578063a02b2b0e116101a6578063a02b2b0e14610bdd578063a22cb46514610bfc578063a2620c8914610c1b578063a3e9b78514610c30578063a82ce4fd14610c44578063a85e2b9d14610c58575f5ffd5b8063917d009e14610b6357806395d89b4114610b8257806396916dd814610b965780639c7aa88e14610baa5780639e05d24014610bbe575f5ffd5b806387607945116102275780638760794514610ae1578063890f3fc514610af45780638a157df314610b135780638c366d8c14610b325780638da5cb5b14610b46575f5ffd5b806376c2ccc114610a5a578063773dcb9814610a855780637adac0e614610a995780637fc7e21a14610aad57806383584aec14610acc575f5ffd5b80632fc1d0f91161039057806353179413116103045780635a4fee30116102c95780635a4fee30146109955780635ffc6575146109b45780636221d13c146109e85780636352211e14610a0857806370a0823114610a27578063715018a614610a46575f5ffd5b8063531794131461088757806353e8f948146108a0578063571a26a0146108b55780635944c7531461096257806359775b6114610981575f5ffd5b80633be2e117116103555780633be2e117146107f75780633fa783bd1461081757806342842e0e1461082b57806342b324b01461084a578063501883011461085f5780635033091f14610873575f5ffd5b80632fc1d0f91461077b57806330e891171461079a57806332cb6b0c146107b9578063342ecb3d146107ce57806337016250146107e2575f5ffd5b8063098144d41161042757806318215aa8116103ec57806318215aa8146106aa5780631d860744146106bf5780631f9f7a1e146106df57806323b872dd146106fe57806324cbaba81461071d5780632a55205a1461073d575f5ffd5b8063098144d41461063357806309d42b30146106475780630b25c9401461065b5780630c96d38e146106705780630d705df614610683575f5ffd5b806304ebe6ba1161046d57806304ebe6ba1461057157806306fdde03146105b5578063081812fc146105d65780630955da0a146105f5578063095ea7b314610614575f5ffd5b80630104ba22146104a957806301463546146104de57806301ffc9a71461051d57806302a373731461053c57806304634d8d14610552575b5f5ffd5b3480156104b4575f5ffd5b506014546104c990600160b01b900460ff1681565b60405190151581526020015b60405180910390f35b3480156104e9575f5ffd5b5061050573721c008fdff27bf06e7e123956e2fe03b63342e381565b6040516001600160a01b0390911681526020016104d5565b348015610528575f5ffd5b506104c961053736600461455b565b610ece565b348015610547575f5ffd5b50610550610ede565b005b34801561055d575f5ffd5b5061055061056c3660046145a2565b610fdf565b34801561057c575f5ffd5b506105a761058b3660046145d3565b602160209081525f928352604080842090915290825290205481565b6040519081526020016104d5565b3480156105c0575f5ffd5b506105c9610ff5565b6040516104d59190614629565b3480156105e1575f5ffd5b506105056105f036600461463b565b611085565b348015610600575f5ffd5b5061055061060f36600461463b565b6110aa565b34801561061f575f5ffd5b5061055061062e3660046145d3565b6110b7565b34801561063e575f5ffd5b50610505611114565b348015610652575f5ffd5b506105a7604581565b348015610666575f5ffd5b506105a7611b3981565b61055061067e366004614652565b61114e565b34801561068e575f5ffd5b506040805163657711f560e11b815260016020820152016104d5565b3480156106b5575f5ffd5b506105a7601a5481565b3480156106ca575f5ffd5b506014546104c990600160b81b900460ff1681565b3480156106ea575f5ffd5b506105506106f936600461463b565b611497565b348015610709575f5ffd5b50610550610718366004614672565b6116a4565b348015610728575f5ffd5b506014546104c990600160c01b900460ff1681565b348015610748575f5ffd5b5061075c610757366004614652565b6116da565b604080516001600160a01b0390931683526020830191909152016104d5565b348015610786575f5ffd5b5061055061079536600461463b565b611786565b3480156107a5575f5ffd5b506105a76107b436600461463b565b611793565b3480156107c4575f5ffd5b506105a761271081565b3480156107d9575f5ffd5b50610550611827565b3480156107ed575f5ffd5b506105a7601c5481565b348015610802575f5ffd5b506014546104c990600160a01b900460ff1681565b348015610822575f5ffd5b50610550611844565b348015610836575f5ffd5b50610550610845366004614672565b61185b565b348015610855575f5ffd5b506105a7601d5481565b34801561086a575f5ffd5b506105a7611875565b34801561087e575f5ffd5b506105506118a3565b348015610892575f5ffd5b506024546104c99060ff1681565b3480156108ab575f5ffd5b506105a760175481565b3480156108c0575f5ffd5b5061091c6108cf36600461463b565b601f6020525f908152604090208054600182015460028301546003840154600485015460058601546006870154600788015460089098015496979596949593949293919290919060ff1689565b60408051998a5260208a0198909852968801959095526060870193909352608086019190915260a085015260c084015260e08301521515610100820152610120016104d5565b34801561096d575f5ffd5b5061055061097c3660046146ac565b6118c0565b34801561098c575f5ffd5b506105506118d3565b3480156109a0575f5ffd5b506105506109af36600461480f565b6118f0565b3480156109bf575f5ffd5b506105a76109ce3660046145d3565b60208080525f928352604080842090915290825290205481565b3480156109f3575f5ffd5b506008546104c990600160a81b900460ff1681565b348015610a13575f5ffd5b50610505610a2236600461463b565b61192f565b348015610a32575f5ffd5b506105a7610a41366004614892565b61198e565b348015610a51575f5ffd5b50610550611a12565b348015610a65575f5ffd5b506105a7610a74366004614892565b601e6020525f908152604090205481565b348015610a90575f5ffd5b50610550611a25565b348015610aa4575f5ffd5b50610550611a39565b348015610ab8575f5ffd5b50610550610ac73660046148ab565b611a50565b348015610ad7575f5ffd5b506105a7601b5481565b610550610aef36600461491c565b611c8d565b348015610aff575f5ffd5b50610550610b0e36600461463b565b611f52565b348015610b1e575f5ffd5b50610550610b2d366004614963565b611fa4565b348015610b3d575f5ffd5b506105c96121cf565b348015610b51575f5ffd5b50600b546001600160a01b0316610505565b348015610b6e575f5ffd5b506105a7610b7d36600461463b565b61225b565b348015610b8d575f5ffd5b506105c96123a7565b348015610ba1575f5ffd5b506105506123b6565b348015610bb5575f5ffd5b506105506123cd565b348015610bc9575f5ffd5b50610550610bd83660046149a9565b612679565b348015610be8575f5ffd5b50610550610bf736600461463b565b6126d9565b348015610c07575f5ffd5b50610550610c163660046149c2565b612722565b348015610c26575f5ffd5b506105a760195481565b348015610c3b575f5ffd5b5061055061277f565b348015610c4f575f5ffd5b506105c9612821565b348015610c63575f5ffd5b506105a760185481565b348015610c78575f5ffd5b50610550610c8736600461463b565b61282e565b348015610c97575f5ffd5b50610550610ca6366004614892565b612877565b348015610cb6575f5ffd5b50610550612930565b348015610cca575f5ffd5b50610550610cd93660046149ea565b612947565b348015610ce9575f5ffd5b50610550610cf836600461463b565b612bfa565b348015610d08575f5ffd5b506105a7612c4c565b348015610d1c575f5ffd5b50610550612c5c565b348015610d30575f5ffd5b50610550610d3f366004614a4d565b612c73565b610550610d52366004614a98565b612cab565b348015610d62575f5ffd5b50610550610d71366004614ad6565b612f77565b348015610d81575f5ffd5b506105c9610d9036600461463b565b612f98565b348015610da0575f5ffd5b506014546104c990600160a81b900460ff1681565b348015610dc0575f5ffd5b506105a760155481565b348015610dd5575f5ffd5b50610de9610de4366004614892565b613041565b6040516104d59190614b69565b348015610e01575f5ffd5b506105a76130aa565b348015610e15575f5ffd5b506104c9610e24366004614b7b565b6130db565b348015610e34575f5ffd5b506105a760165481565b348015610e49575f5ffd5b50610550610e58366004614892565b61313e565b348015610e68575f5ffd5b50610550610e77366004614ba3565b6131b4565b348015610e87575f5ffd5b50610550610e9636600461463b565b6131eb565b348015610ea6575f5ffd5b50610550610eb536600461463b565b61320d565b348015610ec5575f5ffd5b506105506134c1565b5f610ed8826134d8565b92915050565b610ee66134fc565b5f601c5411610f2f5760405162461bcd60e51b815260206004820152601060248201526f5365742070726963652066697273742160801b60448201526064015b60405180910390fd5b601654610f705760405162461bcd60e51b815260206004820152600f60248201526e53657420726f6f742066697273742160881b6044820152606401610f26565b601454600160b01b900460ff1615610fca5760405162461bcd60e51b815260206004820152601860248201527f53746f702074726176656c6572206d696e7420666972737400000000000000006044820152606401610f26565b6014805460ff60b81b1916600160b81b179055565b610fe76134fc565b610ff18282613504565b5050565b60606006805461100490614bfc565b80601f016020809104026020016040519081016040528092919081815260200182805461103090614bfc565b801561107b5780601f106110525761010080835404028352916020019161107b565b820191905f5260205f20905b81548152906001019060200180831161105e57829003601f168201915b5050505050905090565b5f61108f82613559565b505f908152600460205260409020546001600160a01b031690565b6110b26134fc565b601755565b60245460ff161561110a5760405162461bcd60e51b815260206004820181905260248201527f417070726f76616c73206172652063757272656e746c792064697361626c65646044820152606401610f26565b610ff182826135b7565b60085461010090046001600160a01b03168061114b5760085460ff1661114b575073721c008fdff27bf06e7e123956e2fe03b63342e35b90565b6111566136c6565b5f828152601f60205260409020600881015460ff166111ac5760405162461bcd60e51b815260206004820152601260248201527141756374696f6e206e6f742061637469766560701b6044820152606401610f26565b5f821180156111bc575060458211155b6111fe5760405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152606401610f26565b80544310801590611213575080600101544311155b6112585760405162461bcd60e51b8152602060048201526016602482015275125b9d985b1a5908185d58dd1a5bdb881c195c9a5bd960521b6044820152606401610f26565b60185460175461126a90612710614c42565b6112749190614c42565b6001836019546112849190614c55565b61128e9190614c42565b11156112dc5760405162461bcd60e51b815260206004820152601b60248201527f41756374696f6e61626c6520737570706c79206465706c6574656400000000006044820152606401610f26565b5f6112e68461225b565b90505f6112f38483614c68565b90508034101561133c5760405162461bcd60e51b8152602060048201526014602482015273125b9cdd59999a58da595b9d081c185e5b595b9d60621b6044820152606401610f26565b5f5b848110156113575761134f3361371f565b60010161133e565b50335f908152602080805260408083208884529091528120805486929061137f908490614c55565b9091555050335f908152602160209081526040808320888452909152812080548392906113ad908490614c55565b9091555050600583018290556006830180548591905f906113cf908490614c55565b9250508190555080836007015f8282546113e99190614c55565b909155505f90506113fa8234614c42565b90508015611489576040515f90339083908381818185875af1925050503d805f8114611441576040519150601f19603f3d011682016040523d82523d5f602084013e611446565b606091505b50509050806114875760405162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b6044820152606401610f26565b505b50505050610ff16001600c55565b61149f6136c6565b335f908152602160209081526040808320848452909152902054806114f65760405162461bcd60e51b815260206004820152600d60248201526c4e6f20726566756e642064756560981b6044820152606401610f26565b335f908152602080805260408083208584529091529020548061155b5760405162461bcd60e51b815260206004820152601c60248201527f4e6f2061756374696f6e207075726368617365207265636f72646564000000006044820152606401610f26565b5f838152601f6020526040812060050154906115778383614c68565b90508084116115b85760405162461bcd60e51b815260206004820152600d60248201526c4e6f20726566756e642064756560981b6044820152606401610f26565b5f6115c38286614c42565b335f9081526021602090815260408083208a84528252808320869055601f9091528120600701805492935083929091906115fe908490614c42565b90915550506040515f90339083908381818185875af1925050503d805f8114611642576040519150601f19603f3d011682016040523d82523d5f602084013e611647565b606091505b50509050806116915760405162461bcd60e51b81526020600482015260166024820152751499599d5b99081d1c985b9cd9995c8819985a5b195960521b6044820152606401610f26565b5050505050506116a16001600c55565b50565b6116ae338261378e565b6116ca5760405162461bcd60e51b8152600401610f2690614c7f565b6116d58383836137eb565b505050565b5f828152600a602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b031692820192909252829161174e5750604080518082019091526009546001600160a01b0381168252600160a01b90046001600160601b031660208201525b60208101515f906127109061176c906001600160601b031687614c68565b6117769190614ccc565b91519350909150505b9250929050565b61178e6134fc565b601855565b5f818152601f602052604081206008810154829060ff1680156117ba575081600101544311155b80156117c7575081544310155b156117d7575060048101546117de565b5060058101545b60068201546117ed9082614c68565b8260070154111561181e5760068201546118079082614c68565b82600701546118169190614c42565b949350505050565b505f9392505050565b61182f6134fc565b6014805460ff60c01b1916600160c01b179055565b61184c6134fc565b6014805460ff60b81b19169055565b6116d583838360405180602001604052805f815250612c73565b5f47816118806130aa565b90508082111561189b576118948183614c42565b9250505090565b5f9250505090565b6118ab6134fc565b6014805460ff60a01b1916600160a01b179055565b6118c86134fc565b6116d5838383613962565b6118db6134fc565b6014805460ff60a81b1916600160a81b179055565b5f5b825181101561192857611920858585848151811061191257611912614ceb565b602002602001015185612c73565b6001016118f2565b5050505050565b5f818152600260205260408120546001600160a01b031680610ed85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610f26565b5f6001600160a01b0382166119f75760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610f26565b506001600160a01b03165f9081526003602052604090205490565b611a1a6139bc565b611a235f613a16565b565b611a2d6134fc565b6024805460ff19169055565b611a416134fc565b6024805460ff19166001179055565b611a586136c6565b601454600160a01b900460ff16611ab15760405162461bcd60e51b815260206004820181905260248201527f4f6e6520666f72206f6e65206275726e20686173206e6f7420737461727465646044820152606401610f26565b601454600160c01b900460ff1615611b0b5760405162461bcd60e51b815260206004820152601c60248201527f54776f20666f72206f6e65206d696e74206861732073746172746564000000006044820152606401610f26565b5f815111611b4e5760405162461bcd60e51b815260206004820152601060248201526f456d707479206275726e20617272617960801b6044820152606401610f26565b5f5b8151811015611c49576013546001600160a01b03166342842e0e3360145485516001600160a01b0390911690869086908110611b8e57611b8e614ceb565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064015f604051808303815f87803b158015611be5575f5ffd5b505af1158015611bf7573d5f5f3e3d5ffd5b5050335f908152602260205260409020845190925084915083908110611c1f57611c1f614ceb565b6020908102919091018101518254600181810185555f948552929093209092019190915501611b50565b507faa0422371149feb53467e40d00ddab7f792ebba34ad9666d508f23ce8a0d7a1e3382604051611c7b929190614cff565b60405180910390a16116a16001600c55565b611c956136c6565b601454600160b81b900460ff16611cfa5760405162461bcd60e51b8152602060048201526024808201527f4465646963617465642077686974656c697374206d696e74206e6f74207374616044820152631c9d195960e21b6064820152608401610f26565b601454600160b01b900460ff1615611d625760405162461bcd60e51b815260206004820152602560248201527f54726176656c65722077686974656c697374206d696e74207374696c6c206f6e604482015264676f696e6760d81b6064820152608401610f26565b5f601c5411611db35760405162461bcd60e51b815260206004820152601760248201527f446564696361746564207072696365206e6f74207365740000000000000000006044820152606401610f26565b612710600184601954611dc69190614c55565b611dd09190614c42565b1115611e1e5760405162461bcd60e51b815260206004820152601960248201527f44656469636174656420737570706c79206578636565646564000000000000006044820152606401610f26565b6040516bffffffffffffffffffffffff193360601b1660208201525f90603401604051602081830303815290604052805190602001209050611e968383808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506016549150849050613a67565b611edc5760405162461bcd60e51b815260206004820152601760248201527624b73b30b634b2103bb434ba32b634b9ba10383937b7b360491b6044820152606401610f26565b601c54611ee99085614c68565b3414611f2b5760405162461bcd60e51b8152602060048201526011602482015270125b98dbdc9c9958dd081c185e5b595b9d607a1b6044820152606401610f26565b5f5b84811015611f4657611f3e3361371f565b600101611f2d565b50506116d56001600c55565b611f5a6134fc565b5f8111611f9f5760405162461bcd60e51b815260206004820152601360248201527250726963652063616e2774206265207a65726f60681b6044820152606401610f26565b601c55565b611fac6134fc565b5f8111611ffb5760405162461bcd60e51b815260206004820152601a60248201527f4d696e2070726963652063616e2774207265616368207a65726f0000000000006044820152606401610f26565b80821161205c5760405162461bcd60e51b815260206004820152602960248201527f5374617274207072696365206d75737420626520686967686572207468616e206044820152686d696e20707269636560b81b6064820152608401610f26565b438510156120b75760405162461bcd60e51b815260206004820152602260248201527f43616e277420737461727420616e2061756374696f6e20696e207468652070616044820152611cdd60f21b6064820152608401610f26565b8385106121125760405162461bcd60e51b8152602060048201526024808201527f537461727420626c6f636b206d757374206265206265666f726520656e6420626044820152636c6f636b60e01b6064820152608401610f26565b60408051610120810182528681526020808201878152828401878152606084018781526080850187815260a086018981525f60c0880181815260e0890182815260016101008b01818152602380548652601f909b529b84209a518b559751978a0197909755945160028901559251600388015590516004870155516005860155905160068501559051600784015592516008909201805460ff1916921515929092179091558054916121c383614d22565b91905055505050505050565b600e80546121dc90614bfc565b80601f016020809104026020016040519081016040528092919081815260200182805461220890614bfc565b80156122535780601f1061222a57610100808354040283529160200191612253565b820191905f5260205f20905b81548152906001019060200180831161223657829003601f168201915b505050505081565b5f818152601f6020526040812080544310156122af5760405162461bcd60e51b8152602060048201526013602482015272105d58dd1a5bdb881b9bdd081cdd185c9d1959606a1b6044820152606401610f26565b80600101544311156122f35760405162461bcd60e51b815260206004820152600d60248201526c105d58dd1a5bdb88195b991959609a1b6044820152606401610f26565b600881015460ff1661233a5760405162461bcd60e51b815260206004820152601060248201526f105d58dd1a5bdb88191a5cd8589b195960821b6044820152606401610f26565b80545f906123489043614c42565b90505f81836002015461235b9190614c68565b90505f81846003015411612373578360040154612383565b8184600301546123839190614c42565b9050836004015481101561239b57836004015461239d565b805b9695505050505050565b60606007805461100490614bfc565b6123be6134fc565b6014805460ff60b01b19169055565b6123d56136c6565b6123dd6134fc565b5f6123e6611875565b90505f811161242f5760405162461bcd60e51b81526020600482015260156024820152744e6f20776974686472617761626c652066756e647360581b6044820152606401610f26565b5f6103e861243e83604b614c68565b6124489190614ccc565b90505f6103e861245984604b614c68565b6124639190614ccc565b90505f6103e8612474856005614c68565b61247e9190614ccc565b90505f818361248d8688614c42565b6124979190614c42565b6124a19190614c42565b6011546040519192505f916001600160a01b039091169083908381818185875af1925050503d805f81146124f0576040519150601f19603f3d011682016040523d82523d5f602084013e6124f5565b606091505b50509050806125165760405162461bcd60e51b8152600401610f2690614d3a565b600f546040515f916001600160a01b03169087908381818185875af1925050503d805f8114612560576040519150601f19603f3d011682016040523d82523d5f602084013e612565565b606091505b50509050806125865760405162461bcd60e51b8152600401610f2690614d3a565b6010546040515f916001600160a01b03169087908381818185875af1925050503d805f81146125d0576040519150601f19603f3d011682016040523d82523d5f602084013e6125d5565b606091505b50509050806125f65760405162461bcd60e51b8152600401610f2690614d3a565b6012546040515f916001600160a01b03169087908381818185875af1925050503d805f8114612640576040519150601f19603f3d011682016040523d82523d5f602084013e612645565b606091505b50509050806126665760405162461bcd60e51b8152600401610f2690614d3a565b505050505050505050611a236001600c55565b6126816134fc565b60088054821515600160a81b0260ff60a81b199091161790556040517f6787c7f9a80aa0f5ceddab2c54f1f5169c0b88e75dd5e19d5e858a64144c7dbc906126ce90831515815260200190565b60405180910390a150565b6126e16134fc565b8061271d5760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610f26565b601555565b60245460ff16156127755760405162461bcd60e51b815260206004820181905260248201527f417070726f76616c73206172652063757272656e746c792064697361626c65646044820152606401610f26565b610ff18282613a7c565b6127876134fc565b5f601d54116127cb5760405162461bcd60e51b815260206004820152601060248201526f5365742070726963652066697273742160801b6044820152606401610f26565b60155461280c5760405162461bcd60e51b815260206004820152600f60248201526e53657420726f6f742066697273742160881b6044820152606401610f26565b6014805460ff60b01b1916600160b01b179055565b600d80546121dc90614bfc565b6128366134fc565b806128725760405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081c9bdbdd60a21b6044820152606401610f26565b601655565b61287f6134fc565b6001600160a01b038116803b1515901580159061289a575080155b156128b8576040516332483afb60e01b815260040160405180910390fd5b7fcc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac6128e1611114565b604080516001600160a01b03928316815291851660208301520160405180910390a1600880546001600160a01b038416610100026001600160a81b0319909116176001179055610ff182613a87565b6129386134fc565b6014805460ff60a81b19169055565b61294f6136c6565b601454600160c01b900460ff166129a85760405162461bcd60e51b815260206004820181905260248201527f54776f20666f72206f6e65206d696e7420686173206e6f7420737461727465646044820152606401610f26565b80518251146129ed5760405162461bcd60e51b8152602060048201526011602482015270082e4e4c2f2e640daeae6e840dac2e8c6d607b1b6044820152606401610f26565b5f825111612a335760405162461bcd60e51b8152602060048201526013602482015272456d707479207570677261646520617272617960681b6044820152606401610f26565b5f5b8251811015612bb5576013546001600160a01b03166342842e0e3360145485516001600160a01b0390911690869086908110612a7357612a73614ceb565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064015f604051808303815f87803b158015612aca575f5ffd5b505af1158015612adc573d5f5f3e3d5ffd5b50506013546001600160a01b031691506342842e0e90503360145486516001600160a01b0390911690879086908110612b1757612b17614ceb565b60209081029190910101516040516001600160e01b031960e086901b1681526001600160a01b03938416600482015292909116602483015260448201526064015f604051808303815f87803b158015612b6e575f5ffd5b505af1158015612b80573d5f5f3e3d5ffd5b50505050612bad612b8e3390565b848381518110612ba057612ba0614ceb565b6020026020010151613b05565b600101612a35565b507eae92e6ab53b71163322cdd6ac1cc3d3a76a6a0b4d2c9a670eaf332878871d6338383604051612be893929190614d63565b60405180910390a1610ff16001600c55565b612c026134fc565b5f8111612c475760405162461bcd60e51b815260206004820152601360248201527250726963652063616e2774206265207a65726f60681b6044820152606401610f26565b601d55565b612c59611b396001614c55565b81565b612c646134fc565b6014805460ff60a01b19169055565b612c7d338361378e565b612c995760405162461bcd60e51b8152600401610f2690614c7f565b612ca584848484613b1e565b50505050565b612cb36136c6565b601454600160b01b900460ff16612d185760405162461bcd60e51b8152602060048201526024808201527f54726176656c6572732077686974656c697374206d696e74206e6f74207374616044820152631c9d195960e21b6064820152608401610f26565b5f601d5411612d695760405162461bcd60e51b815260206004820152601760248201527f54726176656c657273207072696365206e6f74207365740000000000000000006044820152606401610f26565b335f908152601e602052604090205415612dc55760405162461bcd60e51b815260206004820152601760248201527f54726176656c657220616c7265616479206d696e7465640000000000000000006044820152606401610f26565b601754601b54612dd6906001614c55565b1115612e245760405162461bcd60e51b815260206004820152601960248201527f54726176656c65727320737570706c79206465706c65746564000000000000006044820152606401610f26565b6040516bffffffffffffffffffffffff193360601b1660208201525f90603401604051602081830303815290604052805190602001209050612e9c8383808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506015549150849050613a67565b612ee25760405162461bcd60e51b815260206004820152601760248201527624b73b30b634b2103bb434ba32b634b9ba10383937b7b360491b6044820152606401610f26565b601d543414612f275760405162461bcd60e51b8152602060048201526011602482015270125b98dbdc9c9958dd081c185e5b595b9d607a1b6044820152606401610f26565b612f303361371f565b335f908152601e60205260408120805460019290612f4f908490614c55565b925050819055506001601b5f828254612f689190614c55565b90915550506001600c55505050565b612f7f6134fc565b600d612f8b8382614ddc565b50600e6116d58282614ddc565b5f818152600260205260409020546060906001600160a01b0316612ff65760405162461bcd60e51b81526020600482015260156024820152742a37b5b2b7103237b2b9903737ba1032bc34b9ba1760591b6044820152606401610f26565b611b39821161303157600d61300a83613b51565b60405160200161301b929190614e96565b6040516020818303038152906040529050919050565b600e61300a83613b51565b919050565b6001600160a01b0381165f9081526022602090815260409182902080548351818402810184019094528084526060939283018282801561309e57602002820191905f5260205f20905b81548152602001906001019080831161308a575b50505050509050919050565b5f80805b6023548110156130d5576130c181611793565b6130cb9083614c55565b91506001016130ae565b50919050565b6001600160a01b038281165f9081526005602090815260408083209385168352929052205460ff1680610ed857600854600160a81b900460ff1615610ed857613122611114565b6001600160a01b0316826001600160a01b031614905092915050565b6131466139bc565b6001600160a01b0381166131ab5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610f26565b6116a181613a16565b5f5b8151811015612ca5576131e384848484815181106131d6576131d6614ceb565b60200260200101516116a4565b6001016131b6565b6131f36134fc565b5f908152601f60205260409020600801805460ff19169055565b6132156136c6565b601454600160a81b900460ff166132785760405162461bcd60e51b815260206004820152602160248201527f4f6e6520666f72206f6e6520636c61696d20686173206e6f74207374617274656044820152601960fa1b6064820152608401610f26565b335f90815260226020526040902054806132c75760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b6044820152606401610f26565b5f821180156132d65750808211155b6133125760405162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a590818dbdd5b9d609a1b6044820152606401610f26565b5f826001600160401b0381111561332b5761332b6146e5565b604051908082528060200260200182016040528015613354578160200160208202803683370190505b5090505f5b838110156133c357335f90815260226020526040812080548390811061338157613381614ceb565b905f5260205f200154905061339c6133963390565b82613b05565b808383815181106133af576133af614ceb565b602090810291909101015250600101613359565b507f6e95c62c71a9ae70ebfd5db27ca5b352f2a8b7077fe17c8cc0e94b5890e596f133826040516133f5929190614cff565b60405180910390a1825b8281101561346e57335f90815260226020526040902080548290811061342757613427614ceb565b5f9182526020808320909101543383526022909152604090912061344b8684614c42565b8154811061345b5761345b614ceb565b5f918252602090912001556001016133ff565b505f5b838110156134b457335f90815260226020526040902080548061349657613496614f16565b5f8281526020812082015f1990810191909155019055600101613471565b5050506116a16001600c55565b6134c96134fc565b6014805460ff60c01b19169055565b5f6001600160e01b0319821663152a902d60e11b1480610ed85750610ed882613be0565b611a236139bc565b61350e8282613c1f565b6040516001600160601b03821681526001600160a01b038316907f8a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76ef9060200160405180910390a25050565b5f818152600260205260409020546001600160a01b03166116a15760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610f26565b5f6135c18261192f565b9050806001600160a01b0316836001600160a01b03160361362e5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610f26565b336001600160a01b038216148061364a575061364a81336130db565b6136bc5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610f26565b6116d58383613cd9565b6002600c54036137185760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610f26565b6002600c55565b612710601954111561376b5760405162461bcd60e51b8152602060048201526015602482015274139bc81c1d589b1a58c81cdd5c1c1b1e481b19599d605a1b6044820152606401610f26565b61377781601954613b05565b60198054905f61378683614d22565b919050555050565b5f5f6137998361192f565b9050806001600160a01b0316846001600160a01b031614806137c057506137c081856130db565b806118165750836001600160a01b03166137d984611085565b6001600160a01b031614949350505050565b826001600160a01b03166137fe8261192f565b6001600160a01b0316146138245760405162461bcd60e51b8152600401610f2690614f2a565b6001600160a01b0382166138865760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610f26565b6138938383836001613d46565b826001600160a01b03166138a68261192f565b6001600160a01b0316146138cc5760405162461bcd60e51b8152600401610f2690614f2a565b5f81815260046020908152604080832080546001600160a01b03199081169091556001600160a01b038781168086526003855283862080545f1901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a46116d58383836001613dca565b61396d838383613df0565b6040516001600160601b03821681526001600160a01b0383169084907f7f5b076c952c0ec86e5425963c1326dd0f03a3595c19f81d765e8ff559a6e33c906020015b60405180910390a3505050565b600b546001600160a01b03163314611a235760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f26565b600b80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f82613a738584613eba565b14949350505050565b610ff1338383613efc565b6001600160a01b038116156116a157803b8015610ff1576040805163fb2de5d760e01b81523060048201526102d1602482015290516001600160a01b0384169163fb2de5d7916044808301925f92919082900301818387803b158015613aeb575f5ffd5b505af1925050508015613afc575060015b15610ff1575050565b610ff1828260405180602001604052805f815250613fc1565b613b298484846137eb565b613b3584848484613ff3565b612ca55760405162461bcd60e51b8152600401610f2690614f6f565b60605f613b5d836140f0565b60010190505f816001600160401b03811115613b7b57613b7b6146e5565b6040519080825280601f01601f191660200182016040528015613ba5576020820181803683370190505b5090508181016020015b5f19016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084613baf57509392505050565b5f6001600160e01b03198216632b435fdb60e21b1480613c1057506001600160e01b0319821663503e914d60e11b145b80610ed85750610ed8826141c7565b6127106001600160601b0382161115613c4a5760405162461bcd60e51b8152600401610f2690614fc1565b6001600160a01b038216613ca05760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401610f26565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600955565b5f81815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190613d0d8261192f565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b613d5284848484614216565b6001600160a01b03841615801590613d7257506001600160a01b03831615155b15612ca55760245460ff1615612ca55760405162461bcd60e51b815260206004820181905260248201527f5472616e7366657273206172652063757272656e746c792064697361626c65646044820152606401610f26565b5f5b8181101561192857613de88585613de38487614c55565b61423c565b600101613dcc565b6127106001600160601b0382161115613e1b5760405162461bcd60e51b8152600401610f2690614fc1565b6001600160a01b038216613e715760405162461bcd60e51b815260206004820152601b60248201527f455243323938313a20496e76616c696420706172616d657465727300000000006044820152606401610f26565b6040805180820182526001600160a01b0393841681526001600160601b0392831660208083019182525f968752600a90529190942093519051909116600160a01b029116179055565b5f81815b8451811015613ef457613eea82868381518110613edd57613edd614ceb565b602002602001015161428a565b9150600101613ebe565b509392505050565b816001600160a01b0316836001600160a01b031603613f5d5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610f26565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3191016139af565b613fcb83836142b9565b613fd75f848484613ff3565b6116d55760405162461bcd60e51b8152600401610f2690614f6f565b5f6001600160a01b0384163b156140e557604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061403690339089908890889060040161500b565b6020604051808303815f875af1925050508015614070575060408051601f3d908101601f1916820190925261406d9181019061503d565b60015b6140cb573d80801561409d576040519150601f19603f3d011682016040523d82523d5f602084013e6140a2565b606091505b5080515f036140c35760405162461bcd60e51b8152600401610f2690614f6f565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611816565b506001949350505050565b5f8072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061412e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831061415a576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061417857662386f26fc10000830492506010015b6305f5e1008310614190576305f5e100830492506008015b61271083106141a457612710830492506004015b606483106141b6576064830492506002015b600a8310610ed85760010192915050565b5f6001600160e01b031982166380ac58cd60e01b14806141f757506001600160e01b03198216635b5e139f60e01b145b80610ed857506301ffc9a760e01b6001600160e01b0319831614610ed8565b5f5b8181101561192857614234858561422f8487614c55565b614457565b600101614218565b6001600160a01b0383811615908316158180156142565750805b1561427457604051635cbd944160e01b815260040160405180910390fd5b8115614280575b611928565b8061427b57611928565b5f8183106142a4575f8281526020849052604090206142b2565b5f8381526020839052604090205b9392505050565b6001600160a01b03821661430f5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610f26565b5f818152600260205260409020546001600160a01b0316156143735760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610f26565b6143805f83836001613d46565b5f818152600260205260409020546001600160a01b0316156143e45760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610f26565b6001600160a01b0382165f81815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4610ff15f83836001613dca565b6001600160a01b0383811615908316158180156144715750805b1561448f57604051635cbd944160e01b815260040160405180910390fd5b8161427b578061427b5761192833868686345f6144aa611114565b90506001600160a01b0381161561453e576001600160a01b03811633036144d15750611928565b60405163657711f560e11b81526001600160a01b038781166004830152868116602483015285811660448301526064820185905282169063caee23ea906084015f6040518083038186803b158015614527575f5ffd5b505afa158015614539573d5f5f3e3d5ffd5b505050505b505050505050565b6001600160e01b0319811681146116a1575f5ffd5b5f6020828403121561456b575f5ffd5b81356142b281614546565b80356001600160a01b038116811461303c575f5ffd5b80356001600160601b038116811461303c575f5ffd5b5f5f604083850312156145b3575f5ffd5b6145bc83614576565b91506145ca6020840161458c565b90509250929050565b5f5f604083850312156145e4575f5ffd5b6145ed83614576565b946020939093013593505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6142b260208301846145fb565b5f6020828403121561464b575f5ffd5b5035919050565b5f5f60408385031215614663575f5ffd5b50508035926020909101359150565b5f5f5f60608486031215614684575f5ffd5b61468d84614576565b925061469b60208501614576565b929592945050506040919091013590565b5f5f5f606084860312156146be575f5ffd5b833592506146ce60208501614576565b91506146dc6040850161458c565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715614721576147216146e5565b604052919050565b5f82601f830112614738575f5ffd5b81356001600160401b03811115614751576147516146e5565b8060051b614761602082016146f9565b9182526020818501810192908101908684111561477c575f5ffd5b6020860192505b8383101561239d578235825260209283019290910190614783565b5f82601f8301126147ad575f5ffd5b8135602083015f5f6001600160401b038411156147cc576147cc6146e5565b50601f8301601f19166020016147e1816146f9565b9150508281528583830111156147f5575f5ffd5b828260208301375f92810160200192909252509392505050565b5f5f5f5f60808587031215614822575f5ffd5b61482b85614576565b935061483960208601614576565b925060408501356001600160401b03811115614853575f5ffd5b61485f87828801614729565b92505060608501356001600160401b0381111561487a575f5ffd5b6148868782880161479e565b91505092959194509250565b5f602082840312156148a2575f5ffd5b6142b282614576565b5f602082840312156148bb575f5ffd5b81356001600160401b038111156148d0575f5ffd5b61181684828501614729565b5f5f83601f8401126148ec575f5ffd5b5081356001600160401b03811115614902575f5ffd5b6020830191508360208260051b850101111561177f575f5ffd5b5f5f5f6040848603121561492e575f5ffd5b8335925060208401356001600160401b0381111561494a575f5ffd5b614956868287016148dc565b9497909650939450505050565b5f5f5f5f5f60a08688031215614977575f5ffd5b505083359560208501359550604085013594606081013594506080013592509050565b8035801515811461303c575f5ffd5b5f602082840312156149b9575f5ffd5b6142b28261499a565b5f5f604083850312156149d3575f5ffd5b6149dc83614576565b91506145ca6020840161499a565b5f5f604083850312156149fb575f5ffd5b82356001600160401b03811115614a10575f5ffd5b614a1c85828601614729565b92505060208301356001600160401b03811115614a37575f5ffd5b614a4385828601614729565b9150509250929050565b5f5f5f5f60808587031215614a60575f5ffd5b614a6985614576565b9350614a7760208601614576565b92506040850135915060608501356001600160401b0381111561487a575f5ffd5b5f5f60208385031215614aa9575f5ffd5b82356001600160401b03811115614abe575f5ffd5b614aca858286016148dc565b90969095509350505050565b5f5f60408385031215614ae7575f5ffd5b82356001600160401b03811115614afc575f5ffd5b614b088582860161479e565b92505060208301356001600160401b03811115614b23575f5ffd5b614a438582860161479e565b5f8151808452602084019350602083015f5b82811015614b5f578151865260209586019590910190600101614b41565b5093949350505050565b602081525f6142b26020830184614b2f565b5f5f60408385031215614b8c575f5ffd5b614b9583614576565b91506145ca60208401614576565b5f5f5f60608486031215614bb5575f5ffd5b614bbe84614576565b9250614bcc60208501614576565b915060408401356001600160401b03811115614be6575f5ffd5b614bf286828701614729565b9150509250925092565b600181811c90821680614c1057607f821691505b6020821081036130d557634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b81810381811115610ed857610ed8614c2e565b80820180821115610ed857610ed8614c2e565b8082028115828204841417610ed857610ed8614c2e565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b5f82614ce657634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b03831681526040602082018190525f9061181690830184614b2f565b5f60018201614d3357614d33614c2e565b5060010190565b6020808252600f908201526e151c985b9cd9995c8819985a5b1959608a1b604082015260600190565b6001600160a01b03841681526060602082018190525f90614d8690830185614b2f565b828103604084015261239d8185614b2f565b601f8211156116d557805f5260205f20601f840160051c81016020851015614dbd5750805b601f840160051c820191505b81811015611928575f8155600101614dc9565b81516001600160401b03811115614df557614df56146e5565b614e0981614e038454614bfc565b84614d98565b6020601f821160018114614e3b575f8315614e245750848201515b5f19600385901b1c1916600184901b178455611928565b5f84815260208120601f198516915b82811015614e6a5787850151825560209485019460019092019101614e4a565b5084821015614e8757868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f5f8454614ea381614bfc565b600182168015614eba5760018114614ecf57614efc565b60ff1983168652811515820286019350614efc565b875f5260205f205f5b83811015614ef457815488820152600190910190602001614ed8565b505081860193505b50505083518060208601835e5f9101908152949350505050565b634e487b7160e01b5f52603160045260245ffd5b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252602a908201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646040820152692073616c65507269636560b01b606082015260800190565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f9061239d908301846145fb565b5f6020828403121561504d575f5ffd5b81516142b28161454656fea2646970667358221220353d36333563b52d9a0ad9616be4f08ad06a9e096a5deeed9f8b5050ec87fb7664736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000d9c036e9eef725e5aca4a22239a23feb47c3f05d000000000000000000000000000000000000000000000000000000000000000b706c616365686f6c646572000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : baseURI (string): placeholder
Arg [1] : _V1Address (address): 0xD9c036e9EEF725E5AcA4a22239A23feb47c3f05d
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 000000000000000000000000d9c036e9eef725e5aca4a22239a23feb47c3f05d
Arg [2] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [3] : 706c616365686f6c646572000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Net Worth in USD
$1,794.84
Net Worth in ETH
0.927342
Token Allocations
ETH
100.00%
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $1,935.46 | 0.9273 | $1,794.84 |
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.