Source Code
Overview
ETH Balance
0.349672813285902215 ETH
Eth Value
$652.79 (@ $1,866.85/ETH)More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 249 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw | 24478503 | 5 days ago | IN | 0 ETH | 0.0000053 | ||||
| Transfer From | 24466585 | 6 days ago | IN | 0 ETH | 0.00018161 | ||||
| Mint | 24463546 | 7 days ago | IN | 0.01007426 ETH | 0.00073041 | ||||
| Mint | 24463543 | 7 days ago | IN | 0.01007426 ETH | 0.00072292 | ||||
| Mint | 24432401 | 11 days ago | IN | 0.01036647 ETH | 0.00081564 | ||||
| Mint | 24428935 | 12 days ago | IN | 0.0100267 ETH | 0.00077521 | ||||
| Mint | 24428888 | 12 days ago | IN | 0.0100508 ETH | 0.00077819 | ||||
| Mint | 24419610 | 13 days ago | IN | 0.00990817 ETH | 0.00073132 | ||||
| Mint With Tip | 24412800 | 14 days ago | IN | 0.01187256 ETH | 0.00073132 | ||||
| Mint | 24408078 | 15 days ago | IN | 0.00966868 ETH | 0.00073538 | ||||
| Mint With Tip | 24408041 | 15 days ago | IN | 0.04795566 ETH | 0.00074776 | ||||
| Mint | 24403079 | 15 days ago | IN | 0.00967368 ETH | 0.00075669 | ||||
| Mint | 24402224 | 15 days ago | IN | 0.00975214 ETH | 0.00078626 | ||||
| Mint | 24400899 | 16 days ago | IN | 0.00973353 ETH | 0.00078666 | ||||
| Mint | 24397163 | 16 days ago | IN | 0.01049759 ETH | 0.00084837 | ||||
| Mint | 24397128 | 16 days ago | IN | 0.01057453 ETH | 0.00085806 | ||||
| Mint With Tip | 24396545 | 16 days ago | IN | 0.01333037 ETH | 0.00078567 | ||||
| Mint | 24396043 | 16 days ago | IN | 0.0104244 ETH | 0.00092319 | ||||
| Mint | 24396040 | 16 days ago | IN | 0.0104244 ETH | 0.00090363 | ||||
| Mint | 24396035 | 16 days ago | IN | 0.0104244 ETH | 0.00092451 | ||||
| Mint | 24395424 | 16 days ago | IN | 0.01058228 ETH | 0.00088177 | ||||
| Mint | 24393954 | 17 days ago | IN | 0.01081903 ETH | 0.00122588 | ||||
| Mint With Tip | 24377487 | 19 days ago | IN | 0.01775838 ETH | 0.00095754 | ||||
| Mint | 24372398 | 20 days ago | IN | 0.00859424 ETH | 0.00074912 | ||||
| Mint With Tip | 24360636 | 21 days ago | IN | 0.01039942 ETH | 0.00074415 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 24478503 | 5 days ago | 0.11182491 ETH | ||||
| Transfer | 24432401 | 11 days ago | 0.0102628 ETH | ||||
| Transfer | 24432401 | 11 days ago | 0.00010366 ETH | ||||
| Transfer | 24428935 | 12 days ago | 0.00992643 ETH | ||||
| Transfer | 24428935 | 12 days ago | 0.00010026 ETH | ||||
| Transfer | 24428888 | 12 days ago | 0.00995029 ETH | ||||
| Transfer | 24428888 | 12 days ago | 0.0001005 ETH | ||||
| Transfer | 24349567 | 23 days ago | 0.00738637 ETH | ||||
| Transfer | 24296833 | 30 days ago | 1.01750405 ETH | ||||
| Transfer | 24296754 | 30 days ago | 0.40295599 ETH | ||||
| Transfer | 24296753 | 30 days ago | 0.77419354 ETH | ||||
| Transfer | 24260455 | 35 days ago | 0.0063839 ETH | ||||
| Transfer | 24260455 | 35 days ago | 0.00006448 ETH | ||||
| Transfer | 24260452 | 35 days ago | 0.0063839 ETH | ||||
| Transfer | 24260452 | 35 days ago | 0.00006448 ETH | ||||
| Transfer | 24260449 | 35 days ago | 0.0063839 ETH | ||||
| Transfer | 24260449 | 35 days ago | 0.00006448 ETH | ||||
| Transfer | 24260446 | 35 days ago | 0.0063839 ETH | ||||
| Transfer | 24260446 | 35 days ago | 0.00006448 ETH | ||||
| Transfer | 24260443 | 35 days ago | 0.0063839 ETH | ||||
| Transfer | 24260443 | 35 days ago | 0.00006448 ETH | ||||
| Transfer | 24260440 | 35 days ago | 0.0063839 ETH | ||||
| Transfer | 24260440 | 35 days ago | 0.00006448 ETH | ||||
| Transfer | 24260437 | 35 days ago | 0.0063839 ETH | ||||
| Transfer | 24260437 | 35 days ago | 0.00006448 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
PatriotPledgeNFTV8
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Royalty.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
/**
* @title PatriotPledgeNFTV8
* @author PatriotPledge Team
* @notice Multi-chain production NFT with improved ABI clarity and chain-agnostic naming
* @dev Complete NFT management system designed for Ethereum Mainnet and multi-chain deployment
*
* V8 IMPROVEMENTS (from V7 audit):
* - Struct-based getCampaign() to prevent ABI field mismatches
* - Chain-agnostic function names (no more "BDAG" references)
* - USD price storage alongside native price for accurate reporting
* - Per-campaign pause functionality
* - Simplified immediate payout (single flag per campaign)
* - All mint functions have onlyThisChain modifier
* - Enhanced events for better frontend tracking
*
* INHERITED FROM V7:
* - Immediate fund distribution on mint
* - Configurable fee splitting
* - Chain-aware deployment with replay protection
* - Bug bounty pool
* - EIP-2981 Royalties
* - Pausable, Token freezing, Blacklisting
* - Soulbound tokens, ERC-4906 metadata refresh
*/
contract PatriotPledgeNFTV8 is
ERC721,
ERC721Enumerable,
ERC721URIStorage,
ERC721Royalty,
Ownable,
Pausable,
ReentrancyGuard
{
// ============ Constants ============
uint256 public constant VERSION = 8;
uint256 public constant MAX_FEE_BPS = 3000; // Maximum 30% total fees
uint256 public constant BPS_DENOMINATOR = 10000;
uint256 public constant MAX_BATCH_SIZE = 50;
// Chain ID at deployment (for replay protection)
uint256 public immutable deploymentChainId;
// ============ State Variables ============
uint256 private _nextTokenId;
uint256 private _nextCampaignId;
// Treasury addresses
address public platformTreasury;
// Bug bounty pool
uint256 public bugBountyPool;
// Default royalty (can be overridden per-token)
uint96 public defaultRoyaltyBps = 250; // 2.5%
// Platform fee in basis points (e.g., 100 = 1%)
uint16 public platformFeeBps;
// Token freezing (prevents transfers)
mapping(uint256 => bool) public frozenTokens;
// Address blacklist (prevents minting/transfers)
mapping(address => bool) public blacklisted;
// Soulbound tokens (non-transferable)
mapping(uint256 => bool) public soulbound;
// ============ Campaign Structure (V8 Enhanced) ============
struct Campaign {
string category;
string baseURI;
uint256 goalNative; // Goal in native currency (wei)
uint256 goalUsd; // Goal in USD cents (for reporting)
uint256 grossRaised;
uint256 netRaised;
uint256 tipsReceived;
uint256 editionsMinted;
uint256 maxEditions;
uint256 priceNative; // Price in native currency (wei)
uint256 priceUsd; // Price in USD cents (for reporting)
address nonprofit;
address submitter;
bool active;
bool paused; // V8 NEW: Per-campaign pause
bool closed;
bool refunded;
bool immediatePayoutEnabled;
}
// V8: Struct for view function (prevents ABI mismatch)
struct CampaignView {
uint256 id;
string category;
string baseURI;
uint256 goalNative;
uint256 goalUsd;
uint256 grossRaised;
uint256 netRaised;
uint256 tipsReceived;
uint256 editionsMinted;
uint256 maxEditions;
uint256 priceNative;
uint256 priceUsd;
address nonprofit;
address submitter;
bool active;
bool paused;
bool closed;
bool refunded;
bool immediatePayoutEnabled;
}
mapping(uint256 => Campaign) public campaigns;
mapping(uint256 => uint256) public tokenToCampaign;
mapping(uint256 => uint256) public tokenEditionNumber;
mapping(uint256 => uint256[]) public campaignEditions;
// Track total distributed per campaign
mapping(uint256 => uint256) public campaignDistributed;
// ============ Events ============
// Campaign events
event CampaignCreated(
uint256 indexed campaignId,
address indexed nonprofit,
address indexed submitter,
string category,
uint256 goalNative,
uint256 goalUsd,
uint256 maxEditions,
uint256 priceNative,
uint256 priceUsd,
bool immediatePayoutEnabled
);
event CampaignUpdated(uint256 indexed campaignId, string field);
event CampaignMetadataUpdated(uint256 indexed campaignId, string newBaseURI);
event CampaignClosed(uint256 indexed campaignId);
event CampaignReopened(uint256 indexed campaignId);
event CampaignPaused(uint256 indexed campaignId);
event CampaignUnpaused(uint256 indexed campaignId);
event CampaignRefunded(uint256 indexed campaignId);
event ContributionRecorded(uint256 indexed campaignId, uint256 gross, uint256 net, uint256 tip, bool isOnchain);
event PriceUpdated(uint256 indexed campaignId, uint256 oldPriceNative, uint256 newPriceNative, uint256 newPriceUsd);
// Token events
event EditionMinted(
uint256 indexed campaignId,
uint256 indexed tokenId,
address indexed donor,
uint256 editionNumber,
uint256 amountPaid
);
event TokenURIFixed(uint256 indexed tokenId, string newURI);
event TokenBurned(uint256 indexed tokenId, address indexed burner);
event TokenFrozen(uint256 indexed tokenId, bool frozen);
event TokenSoulbound(uint256 indexed tokenId, bool soulbound);
// Fund distribution events
event FundsDistributed(
uint256 indexed campaignId,
address indexed submitter,
uint256 submitterAmount,
uint256 platformFee,
uint256 tipAmount
);
event ImmediatePayoutSent(
uint256 indexed campaignId,
address indexed recipient,
uint256 amount,
string recipientType
);
// Bug bounty events
event BugBountyFunded(address indexed funder, uint256 amount);
event BugBountyPaid(address indexed recipient, uint256 amount, string reportId);
// Admin events
event AddressBlacklisted(address indexed addr, bool blacklisted);
event TreasuryUpdated(address indexed oldTreasury, address indexed newTreasury);
event DefaultRoyaltyUpdated(uint96 newRoyaltyBps);
event PlatformFeeUpdated(uint16 oldFeeBps, uint16 newFeeBps);
event EmergencyWithdraw(address indexed to, uint256 amount);
// ============ Modifiers ============
modifier notBlacklisted(address addr) {
require(!blacklisted[addr], "Address is blacklisted");
_;
}
modifier tokenNotFrozen(uint256 tokenId) {
require(!frozenTokens[tokenId], "Token is frozen");
_;
}
modifier onlyThisChain() {
require(block.chainid == deploymentChainId, "Wrong chain");
_;
}
modifier campaignMintable(uint256 campaignId) {
Campaign storage c = campaigns[campaignId];
require(c.active, "Campaign not active");
require(!c.paused, "Campaign is paused");
require(!c.closed, "Campaign closed");
require(!c.refunded, "Campaign refunded");
require(c.maxEditions == 0 || c.editionsMinted < c.maxEditions, "Max editions reached");
_;
}
// ============ Constructor ============
constructor(
address _platformTreasury,
uint16 _platformFeeBps
) ERC721("PatriotPledge Edition", "PPE") Ownable(msg.sender) {
require(_platformTreasury != address(0), "Invalid treasury");
require(_platformFeeBps <= MAX_FEE_BPS, "Fee too high");
platformTreasury = _platformTreasury;
platformFeeBps = _platformFeeBps;
deploymentChainId = block.chainid;
_setDefaultRoyalty(_platformTreasury, defaultRoyaltyBps);
}
// ============ Pausable Functions ============
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
// ============ Platform Configuration ============
function setPlatformFee(uint16 _newFeeBps) external onlyOwner {
require(_newFeeBps <= MAX_FEE_BPS, "Fee too high");
uint16 oldFee = platformFeeBps;
platformFeeBps = _newFeeBps;
emit PlatformFeeUpdated(oldFee, _newFeeBps);
}
function setPlatformTreasury(address newTreasury) external onlyOwner {
require(newTreasury != address(0), "Invalid treasury");
address oldTreasury = platformTreasury;
platformTreasury = newTreasury;
emit TreasuryUpdated(oldTreasury, newTreasury);
}
// ============ Bug Bounty Pool ============
function fundBugBounty() external payable {
require(msg.value > 0, "Must send funds");
bugBountyPool += msg.value;
emit BugBountyFunded(msg.sender, msg.value);
}
function payBugBounty(address payable recipient, uint256 amount, string calldata reportId) external onlyOwner nonReentrant {
require(amount <= bugBountyPool, "Insufficient bounty pool");
require(recipient != address(0), "Invalid recipient");
bugBountyPool -= amount;
(bool success, ) = recipient.call{value: amount}("");
require(success, "Transfer failed");
emit BugBountyPaid(recipient, amount, reportId);
}
// ============ Blacklist Management ============
function setBlacklisted(address addr, bool status) external onlyOwner {
blacklisted[addr] = status;
emit AddressBlacklisted(addr, status);
}
// ============ Token Freezing ============
function setTokenFrozen(uint256 tokenId, bool frozen) external onlyOwner {
require(_ownerOf(tokenId) != address(0), "Token does not exist");
frozenTokens[tokenId] = frozen;
emit TokenFrozen(tokenId, frozen);
}
// ============ Soulbound Tokens ============
function setTokenSoulbound(uint256 tokenId, bool _soulbound) external onlyOwner {
require(_ownerOf(tokenId) != address(0), "Token does not exist");
soulbound[tokenId] = _soulbound;
emit TokenSoulbound(tokenId, _soulbound);
}
// ============ Campaign Creation (V8 Enhanced) ============
/**
* @notice Create a new campaign with both native and USD pricing
* @param category Campaign category
* @param baseURI IPFS metadata URI
* @param goalNative Goal in native currency (wei)
* @param goalUsd Goal in USD cents (e.g., 100000 = $1000.00)
* @param maxEditions Maximum editions (0 = unlimited)
* @param priceNative Price per edition in native currency (wei)
* @param priceUsd Price per edition in USD cents (e.g., 1000 = $10.00)
* @param nonprofit Nonprofit address
* @param submitter Submitter address for fund distribution
* @param immediatePayoutEnabled Whether to enable immediate payout
*/
function createCampaign(
string calldata category,
string calldata baseURI,
uint256 goalNative,
uint256 goalUsd,
uint256 maxEditions,
uint256 priceNative,
uint256 priceUsd,
address nonprofit,
address submitter,
bool immediatePayoutEnabled
) external onlyOwner returns (uint256) {
require(submitter != address(0), "Invalid submitter");
require(nonprofit != address(0), "Invalid nonprofit");
uint256 campaignId = _nextCampaignId++;
campaigns[campaignId] = Campaign({
category: category,
baseURI: baseURI,
goalNative: goalNative,
goalUsd: goalUsd,
grossRaised: 0,
netRaised: 0,
tipsReceived: 0,
editionsMinted: 0,
maxEditions: maxEditions,
priceNative: priceNative,
priceUsd: priceUsd,
nonprofit: nonprofit,
submitter: submitter,
active: true,
paused: false,
closed: false,
refunded: false,
immediatePayoutEnabled: immediatePayoutEnabled
});
emit CampaignCreated(
campaignId,
nonprofit,
submitter,
category,
goalNative,
goalUsd,
maxEditions,
priceNative,
priceUsd,
immediatePayoutEnabled
);
return campaignId;
}
// ============ Per-Campaign Pause (V8 NEW) ============
function pauseCampaign(uint256 campaignId) external onlyOwner {
campaigns[campaignId].paused = true;
emit CampaignPaused(campaignId);
}
function unpauseCampaign(uint256 campaignId) external onlyOwner {
campaigns[campaignId].paused = false;
emit CampaignUnpaused(campaignId);
}
// ============ Minting Functions (V8 Chain-Agnostic Names) ============
/**
* @notice Mint a single NFT (chain-agnostic name)
*/
function mint(uint256 campaignId)
external payable
whenNotPaused
notBlacklisted(msg.sender)
nonReentrant
onlyThisChain
campaignMintable(campaignId)
returns (uint256)
{
return _mintInternal(campaignId, 0);
}
/**
* @notice Mint a single NFT with tip
*/
function mintWithTip(uint256 campaignId, uint256 tipAmount)
external payable
whenNotPaused
notBlacklisted(msg.sender)
nonReentrant
onlyThisChain
campaignMintable(campaignId)
returns (uint256)
{
return _mintInternal(campaignId, tipAmount);
}
/**
* @notice Batch mint multiple NFTs
*/
function batchMint(uint256 campaignId, uint256 quantity)
external payable
whenNotPaused
notBlacklisted(msg.sender)
nonReentrant
onlyThisChain
returns (uint256[] memory)
{
return _batchMintInternal(campaignId, quantity, 0);
}
/**
* @notice Batch mint multiple NFTs with tip
*/
function batchMintWithTip(uint256 campaignId, uint256 quantity, uint256 tipAmount)
external payable
whenNotPaused
notBlacklisted(msg.sender)
nonReentrant
onlyThisChain
returns (uint256[] memory)
{
return _batchMintInternal(campaignId, quantity, tipAmount);
}
// ============ Legacy Function Aliases (for V7 compatibility) ============
function mintWithBDAG(uint256 campaignId) external payable whenNotPaused notBlacklisted(msg.sender) nonReentrant onlyThisChain returns (uint256) {
Campaign storage c = campaigns[campaignId];
require(c.active && !c.paused && !c.closed && !c.refunded, "Campaign not mintable");
require(c.maxEditions == 0 || c.editionsMinted < c.maxEditions, "Max editions reached");
return _mintInternal(campaignId, 0);
}
function mintWithBDAGAndTip(uint256 campaignId, uint256 tipAmount) external payable whenNotPaused notBlacklisted(msg.sender) nonReentrant onlyThisChain returns (uint256) {
Campaign storage c = campaigns[campaignId];
require(c.active && !c.paused && !c.closed && !c.refunded, "Campaign not mintable");
require(c.maxEditions == 0 || c.editionsMinted < c.maxEditions, "Max editions reached");
return _mintInternal(campaignId, tipAmount);
}
// ============ Internal Minting ============
function _mintInternal(uint256 campaignId, uint256 tipAmount) internal returns (uint256) {
Campaign storage c = campaigns[campaignId];
require(msg.value >= c.priceNative + tipAmount, "Insufficient payment");
uint256 tokenId = _nextTokenId++;
uint256 editionNumber = ++c.editionsMinted;
uint256 contribution = msg.value - tipAmount;
_safeMint(msg.sender, tokenId);
_setTokenURI(tokenId, c.baseURI);
tokenToCampaign[tokenId] = campaignId;
tokenEditionNumber[tokenId] = editionNumber;
campaignEditions[campaignId].push(tokenId);
c.grossRaised += msg.value;
c.tipsReceived += tipAmount;
// V8: Simplified - only check per-campaign flag
if (c.immediatePayoutEnabled) {
_distributeFunds(campaignId, contribution, tipAmount);
} else {
c.netRaised += contribution;
}
emit EditionMinted(campaignId, tokenId, msg.sender, editionNumber, msg.value);
emit ContributionRecorded(campaignId, msg.value, contribution, tipAmount, true);
return tokenId;
}
function _batchMintInternal(uint256 campaignId, uint256 quantity, uint256 tipAmount) internal returns (uint256[] memory tokenIds) {
Campaign storage c = campaigns[campaignId];
require(c.active && !c.paused && !c.closed && !c.refunded, "Campaign not mintable");
require(quantity > 0 && quantity <= MAX_BATCH_SIZE, "Invalid quantity");
require(c.maxEditions == 0 || c.editionsMinted + quantity <= c.maxEditions, "Exceeds max editions");
require(msg.value >= (c.priceNative * quantity) + tipAmount, "Insufficient payment");
tokenIds = new uint256[](quantity);
uint256 totalPaid = msg.value;
uint256 contribution = totalPaid - tipAmount;
uint256 perNFT = totalPaid / quantity;
for (uint256 i = 0; i < quantity; i++) {
uint256 tokenId = _nextTokenId++;
uint256 editionNumber = ++c.editionsMinted;
_safeMint(msg.sender, tokenId);
_setTokenURI(tokenId, c.baseURI);
tokenToCampaign[tokenId] = campaignId;
tokenEditionNumber[tokenId] = editionNumber;
campaignEditions[campaignId].push(tokenId);
tokenIds[i] = tokenId;
emit EditionMinted(campaignId, tokenId, msg.sender, editionNumber, perNFT);
}
c.grossRaised += totalPaid;
c.tipsReceived += tipAmount;
if (c.immediatePayoutEnabled) {
_distributeFunds(campaignId, contribution, tipAmount);
} else {
c.netRaised += contribution;
}
emit ContributionRecorded(campaignId, totalPaid, contribution, tipAmount, true);
return tokenIds;
}
// ============ Fund Distribution ============
function _distributeFunds(uint256 campaignId, uint256 contribution, uint256 tipAmount) internal {
Campaign storage c = campaigns[campaignId];
uint256 platformFee = (contribution * platformFeeBps) / BPS_DENOMINATOR;
uint256 submitterAmount = contribution - platformFee + tipAmount;
campaignDistributed[campaignId] += contribution + tipAmount;
c.netRaised += (contribution - platformFee);
if (platformFee > 0) {
(bool success1, ) = platformTreasury.call{value: platformFee}("");
require(success1, "Platform fee transfer failed");
emit ImmediatePayoutSent(campaignId, platformTreasury, platformFee, "platform");
}
if (submitterAmount > 0) {
(bool success2, ) = c.submitter.call{value: submitterAmount}("");
require(success2, "Submitter transfer failed");
emit ImmediatePayoutSent(campaignId, c.submitter, submitterAmount, "submitter");
}
emit FundsDistributed(campaignId, c.submitter, submitterAmount, platformFee, tipAmount);
}
function distributePendingFunds(uint256 campaignId) external onlyOwner nonReentrant {
Campaign storage c = campaigns[campaignId];
uint256 pendingAmount = c.netRaised;
require(pendingAmount > 0, "No pending funds");
require(address(this).balance >= pendingAmount, "Insufficient contract balance");
c.netRaised = 0;
_distributeFunds(campaignId, pendingAmount, 0);
}
// ============ Admin Minting ============
function mintEditionToDonor(uint256 campaignId, address donor, uint256 amountPaid) external onlyOwner returns (uint256) {
Campaign storage c = campaigns[campaignId];
require(c.active, "Campaign not active");
require(!c.closed, "Campaign closed");
require(c.maxEditions == 0 || c.editionsMinted < c.maxEditions, "Max editions reached");
uint256 tokenId = _nextTokenId++;
uint256 editionNumber = ++c.editionsMinted;
_safeMint(donor, tokenId);
_setTokenURI(tokenId, c.baseURI);
tokenToCampaign[tokenId] = campaignId;
tokenEditionNumber[tokenId] = editionNumber;
campaignEditions[campaignId].push(tokenId);
emit EditionMinted(campaignId, tokenId, donor, editionNumber, amountPaid);
return tokenId;
}
// ============ Campaign Updates ============
function updateCampaignMetadata(uint256 campaignId, string calldata newBaseURI) external onlyOwner {
Campaign storage c = campaigns[campaignId];
require(!c.closed, "Campaign closed");
c.baseURI = newBaseURI;
uint256[] storage editions = campaignEditions[campaignId];
for (uint256 i = 0; i < editions.length; i++) {
_setTokenURI(editions[i], newBaseURI);
}
emit CampaignMetadataUpdated(campaignId, newBaseURI);
}
function recordContribution(uint256 campaignId, uint256 gross, uint256 net, uint256 tip, bool isOnchain) external onlyOwner {
Campaign storage c = campaigns[campaignId];
require(!c.closed, "Campaign closed");
c.grossRaised += gross + tip;
c.netRaised += net;
c.tipsReceived += tip;
emit ContributionRecorded(campaignId, gross, net, tip, isOnchain);
}
function updateCampaignGoal(uint256 campaignId, uint256 newGoalNative, uint256 newGoalUsd) external onlyOwner {
Campaign storage c = campaigns[campaignId];
require(!c.closed, "Campaign closed");
c.goalNative = newGoalNative;
c.goalUsd = newGoalUsd;
emit CampaignUpdated(campaignId, "goal");
}
function updateCampaignPrice(uint256 campaignId, uint256 newPriceNative, uint256 newPriceUsd) external onlyOwner {
Campaign storage c = campaigns[campaignId];
require(!c.closed, "Campaign closed");
uint256 oldPrice = c.priceNative;
c.priceNative = newPriceNative;
c.priceUsd = newPriceUsd;
emit PriceUpdated(campaignId, oldPrice, newPriceNative, newPriceUsd);
}
function updateCampaignMaxEditions(uint256 campaignId, uint256 newMax) external onlyOwner {
Campaign storage c = campaigns[campaignId];
require(!c.closed, "Campaign closed");
require(newMax == 0 || newMax >= c.editionsMinted, "Cannot reduce below minted");
c.maxEditions = newMax;
emit CampaignUpdated(campaignId, "maxEditions");
}
function updateCampaignSubmitter(uint256 campaignId, address newSubmitter) external onlyOwner {
Campaign storage c = campaigns[campaignId];
require(!c.closed, "Campaign closed");
require(newSubmitter != address(0), "Invalid submitter");
c.submitter = newSubmitter;
emit CampaignUpdated(campaignId, "submitter");
}
function updateCampaignNonprofit(uint256 campaignId, address newNonprofit) external onlyOwner {
Campaign storage c = campaigns[campaignId];
require(!c.closed, "Campaign closed");
require(newNonprofit != address(0), "Invalid nonprofit");
c.nonprofit = newNonprofit;
emit CampaignUpdated(campaignId, "nonprofit");
}
function setCampaignImmediatePayout(uint256 campaignId, bool enabled) external onlyOwner {
Campaign storage c = campaigns[campaignId];
require(!c.closed, "Campaign closed");
c.immediatePayoutEnabled = enabled;
emit CampaignUpdated(campaignId, "immediatePayoutEnabled");
}
// ============ Campaign Lifecycle ============
function deactivateCampaign(uint256 campaignId) external onlyOwner {
campaigns[campaignId].active = false;
emit CampaignUpdated(campaignId, "active");
}
function reactivateCampaign(uint256 campaignId) external onlyOwner {
Campaign storage c = campaigns[campaignId];
require(!c.closed, "Campaign permanently closed");
require(!c.refunded, "Campaign was refunded");
c.active = true;
emit CampaignUpdated(campaignId, "active");
}
function closeCampaign(uint256 campaignId) external onlyOwner {
Campaign storage c = campaigns[campaignId];
c.active = false;
c.closed = true;
emit CampaignClosed(campaignId);
}
function reopenCampaign(uint256 campaignId) external onlyOwner {
Campaign storage c = campaigns[campaignId];
require(c.closed, "Campaign not closed");
require(!c.refunded, "Campaign was refunded");
c.closed = false;
c.active = true;
emit CampaignReopened(campaignId);
}
function markCampaignRefunded(uint256 campaignId) external onlyOwner {
Campaign storage c = campaigns[campaignId];
c.refunded = true;
c.active = false;
emit CampaignRefunded(campaignId);
}
// ============ URI Management ============
function setTokenURI(uint256 tokenId, string calldata uri) external onlyOwner {
require(_ownerOf(tokenId) != address(0), "Token does not exist");
_setTokenURI(tokenId, uri);
emit TokenURIFixed(tokenId, uri);
}
function batchSetTokenURI(uint256[] calldata tokenIds, string calldata uri) external onlyOwner {
for (uint256 i = 0; i < tokenIds.length; i++) {
if (_ownerOf(tokenIds[i]) != address(0)) {
_setTokenURI(tokenIds[i], uri);
emit TokenURIFixed(tokenIds[i], uri);
}
}
}
// ============ View Functions (V8 Struct-Based) ============
/**
* @notice Get campaign data as a struct (prevents ABI mismatch issues)
*/
function getCampaign(uint256 campaignId) external view returns (CampaignView memory) {
Campaign storage c = campaigns[campaignId];
return CampaignView({
id: campaignId,
category: c.category,
baseURI: c.baseURI,
goalNative: c.goalNative,
goalUsd: c.goalUsd,
grossRaised: c.grossRaised,
netRaised: c.netRaised,
tipsReceived: c.tipsReceived,
editionsMinted: c.editionsMinted,
maxEditions: c.maxEditions,
priceNative: c.priceNative,
priceUsd: c.priceUsd,
nonprofit: c.nonprofit,
submitter: c.submitter,
active: c.active,
paused: c.paused,
closed: c.closed,
refunded: c.refunded,
immediatePayoutEnabled: c.immediatePayoutEnabled
});
}
function getEditionInfo(uint256 tokenId) external view returns (uint256 campaignId, uint256 editionNumber, uint256 totalEditions) {
campaignId = tokenToCampaign[tokenId];
editionNumber = tokenEditionNumber[tokenId];
totalEditions = campaigns[campaignId].editionsMinted;
}
function getCampaignEditions(uint256 campaignId) external view returns (uint256[] memory) {
return campaignEditions[campaignId];
}
function totalCampaigns() external view returns (uint256) {
return _nextCampaignId;
}
// ============ Withdraw ============
function withdraw(address payable to, uint256 amount) external onlyOwner nonReentrant {
require(address(this).balance >= amount, "Insufficient balance");
(bool success, ) = to.call{value: amount}("");
require(success, "Transfer failed");
}
function emergencyWithdraw() external onlyOwner nonReentrant {
uint256 balance = address(this).balance;
require(balance > 0, "No balance");
(bool success, ) = platformTreasury.call{value: balance}("");
require(success, "Transfer failed");
emit EmergencyWithdraw(platformTreasury, balance);
}
receive() external payable {}
fallback() external payable {}
// ============ Royalty Management ============
function setDefaultRoyalty(address receiver, uint96 feeNumerator) external onlyOwner {
_setDefaultRoyalty(receiver, feeNumerator);
defaultRoyaltyBps = feeNumerator;
emit DefaultRoyaltyUpdated(feeNumerator);
}
function setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) external onlyOwner {
_setTokenRoyalty(tokenId, receiver, feeNumerator);
}
function deleteDefaultRoyalty() external onlyOwner {
_deleteDefaultRoyalty();
}
// ============ Metadata Refresh (ERC-4906) ============
function emitMetadataUpdate(uint256 tokenId) external onlyOwner {
emit MetadataUpdate(tokenId);
}
function emitBatchMetadataUpdate(uint256 fromTokenId, uint256 toTokenId) external onlyOwner {
emit BatchMetadataUpdate(fromTokenId, toTokenId);
}
// ============ Required Overrides ============
function _update(address to, uint256 tokenId, address auth) internal override(ERC721, ERC721Enumerable) returns (address) {
address from = _ownerOf(tokenId);
if (from != address(0) && to != address(0)) {
require(!frozenTokens[tokenId], "Token is frozen");
require(!soulbound[tokenId], "Token is soulbound");
require(!blacklisted[from], "Sender is blacklisted");
require(!blacklisted[to], "Recipient is blacklisted");
}
return super._update(to, tokenId, auth);
}
function _increaseBalance(address account, uint128 value) internal override(ERC721, ERC721Enumerable) {
super._increaseBalance(account, value);
}
function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) {
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable, ERC721URIStorage, ERC721Royalty) returns (bool) {
return super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2981.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../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.
*/
interface IERC2981 is IERC165 {
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
*/
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) external view returns (address receiver, uint256 royaltyAmount);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC4906.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
import {IERC721} from "./IERC721.sol";
/// @title EIP-721 Metadata Update Extension
interface IERC4906 is IERC165, IERC721 {
/// @dev This event emits when the metadata of a token is changed.
/// So that the third-party platforms such as NFT market could
/// timely update the images and related attributes of the NFT.
event MetadataUpdate(uint256 _tokenId);
/// @dev This event emits when the metadata of a range of tokens is changed.
/// So that the third-party platforms such as NFT market could
/// timely update the images and related attributes of the NFTs.
event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC721} from "../token/ERC721/IERC721.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/common/ERC2981.sol)
pragma solidity ^0.8.20;
import {IERC2981} from "../../interfaces/IERC2981.sol";
import {IERC165, ERC165} from "../../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.
*/
abstract contract ERC2981 is IERC2981, ERC165 {
struct RoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo;
/**
* @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).
*/
error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);
/**
* @dev The default royalty receiver is invalid.
*/
error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);
/**
* @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).
*/
error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);
/**
* @dev The royalty receiver for `tokenId` is invalid.
*/
error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);
/**
* @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 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 {
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale price
revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);
}
if (receiver == address(0)) {
revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));
}
_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 {
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale price
revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);
}
if (receiver == address(0)) {
revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));
}
_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
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.20;
import {IERC721} from "./IERC721.sol";
import {IERC721Receiver} from "./IERC721Receiver.sol";
import {IERC721Metadata} from "./extensions/IERC721Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {Strings} from "../../utils/Strings.sol";
import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
import {IERC721Errors} from "../../interfaces/draft-IERC6093.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}.
*/
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
mapping(uint256 tokenId => address) private _owners;
mapping(address owner => uint256) private _balances;
mapping(uint256 tokenId => address) private _tokenApprovals;
mapping(address owner => mapping(address operator => 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 returns (uint256) {
if (owner == address(0)) {
revert ERC721InvalidOwner(address(0));
}
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual returns (address) {
return _requireOwned(tokenId);
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
_requireOwned(tokenId);
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string.concat(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 {
_approve(to, tokenId, _msgSender());
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual returns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
// Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists
// (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
address previousOwner = _update(to, tokenId, _msgSender());
if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
transferFrom(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*
* IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
* core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances
* consistent with ownership. The invariant to preserve is 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`.
*/
function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
return _owners[tokenId];
}
/**
* @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
*/
function _getApproved(uint256 tokenId) internal view virtual returns (address) {
return _tokenApprovals[tokenId];
}
/**
* @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
* particular (ignoring whether it is owned by `owner`).
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
return
spender != address(0) &&
(owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
}
/**
* @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
* Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets
* the `spender` for the specific `tokenId`.
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/
function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
if (!_isAuthorized(owner, spender, tokenId)) {
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else {
revert ERC721InsufficientApproval(spender, tokenId);
}
}
}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
* a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
*
* WARNING: Increasing an account's balance using this function tends to be paired with an override of the
* {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
* remain consistent with one another.
*/
function _increaseBalance(address account, uint128 value) internal virtual {
unchecked {
_balances[account] += value;
}
}
/**
* @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
* (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that
* `auth` is either the owner of the token, or approved to operate on the token (by the owner).
*
* Emits a {Transfer} event.
*
* NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
address from = _ownerOf(tokenId);
// Perform (optional) operator check
if (auth != address(0)) {
_checkAuthorized(from, auth, tokenId);
}
// Execute the update
if (from != address(0)) {
// Clear approval. No need to re-authorize or emit the Approval event
_approve(address(0), tokenId, address(0), false);
unchecked {
_balances[from] -= 1;
}
}
if (to != address(0)) {
unchecked {
_balances[to] += 1;
}
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
return from;
}
/**
* @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 {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner != address(0)) {
revert ERC721InvalidSender(address(0));
}
}
/**
* @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
*
* 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 {
_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);
_checkOnERC721Received(address(0), to, tokenId, data);
}
/**
* @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 {
address previousOwner = _update(address(0), tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
}
/**
* @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 {
if (to == address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner == address(0)) {
revert ERC721NonexistentToken(tokenId);
} else if (previousOwner != from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
* are aware of the ERC721 standard 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 like {safeTransferFrom} in the sense that it invokes
* {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `tokenId` token must exist and be owned by `from`.
* - `to` cannot be the zero address.
* - `from` cannot be the zero address.
* - 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) internal {
_safeTransfer(from, to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
_transfer(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
* either the owner of the token, or approved to operate on all tokens held by this owner.
*
* Emits an {Approval} event.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address to, uint256 tokenId, address auth) internal {
_approve(to, tokenId, auth, true);
}
/**
* @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
* emitted in the context of transfers.
*/
function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
// Avoid reading the owner unless necessary
if (emitEvent || auth != address(0)) {
address owner = _requireOwned(tokenId);
// We do not use _isAuthorized because single-token approvals should not be able to call approve
if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
revert ERC721InvalidApprover(auth);
}
if (emitEvent) {
emit Approval(owner, to, tokenId);
}
}
_tokenApprovals[tokenId] = to;
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Requirements:
* - operator can't be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
if (operator == address(0)) {
revert ERC721InvalidOperator(operator);
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
* Returns the owner.
*
* Overrides to ownership logic should be done to {_ownerOf}.
*/
function _requireOwned(uint256 tokenId) internal view returns (address) {
address owner = _ownerOf(tokenId);
if (owner == address(0)) {
revert ERC721NonexistentToken(tokenId);
}
return owner;
}
/**
* @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the
* recipient doesn't accept the token transfer. 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
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private {
if (to.code.length > 0) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
if (retval != IERC721Receiver.onERC721Received.selector) {
revert ERC721InvalidReceiver(to);
}
} catch (bytes memory reason) {
if (reason.length == 0) {
revert ERC721InvalidReceiver(to);
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Enumerable.sol)
pragma solidity ^0.8.20;
import {ERC721} from "../ERC721.sol";
import {IERC721Enumerable} from "./IERC721Enumerable.sol";
import {IERC165} from "../../../utils/introspection/ERC165.sol";
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds enumerability
* of all the token ids in the contract as well as all token ids owned by each account.
*
* CAUTION: `ERC721` extensions that implement custom `balanceOf` logic, such as `ERC721Consecutive`,
* interfere with enumerability and should not be used together with `ERC721Enumerable`.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
mapping(address owner => mapping(uint256 index => uint256)) private _ownedTokens;
mapping(uint256 tokenId => uint256) private _ownedTokensIndex;
uint256[] private _allTokens;
mapping(uint256 tokenId => uint256) private _allTokensIndex;
/**
* @dev An `owner`'s token query was out of bounds for `index`.
*
* NOTE: The owner being `address(0)` indicates a global out of bounds index.
*/
error ERC721OutOfBoundsIndex(address owner, uint256 index);
/**
* @dev Batch mint is not allowed.
*/
error ERC721EnumerableForbiddenBatchMint();
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256) {
if (index >= balanceOf(owner)) {
revert ERC721OutOfBoundsIndex(owner, index);
}
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual returns (uint256) {
if (index >= totalSupply()) {
revert ERC721OutOfBoundsIndex(address(0), index);
}
return _allTokens[index];
}
/**
* @dev See {ERC721-_update}.
*/
function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
address previousOwner = super._update(to, tokenId, auth);
if (previousOwner == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_removeTokenFromOwnerEnumeration(previousOwner, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (previousOwner != to) {
_addTokenToOwnerEnumeration(to, tokenId);
}
return previousOwner;
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = balanceOf(to) - 1;
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = balanceOf(from);
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
/**
* See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch
*/
function _increaseBalance(address account, uint128 amount) internal virtual override {
if (amount > 0) {
revert ERC721EnumerableForbiddenBatchMint();
}
super._increaseBalance(account, amount);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Royalty.sol)
pragma solidity ^0.8.20;
import {ERC721} from "../ERC721.sol";
import {ERC2981} from "../../common/ERC2981.sol";
/**
* @dev Extension of ERC721 with the ERC2981 NFT Royalty Standard, a standardized way to retrieve royalty payment
* information.
*
* Royalty information can be specified globally for all token ids via {ERC2981-_setDefaultRoyalty}, and/or individually
* for specific token ids via {ERC2981-_setTokenRoyalty}. The latter takes precedence over the first.
*
* 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.
*/
abstract contract ERC721Royalty is ERC2981, ERC721 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) {
return super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721URIStorage.sol)
pragma solidity ^0.8.20;
import {ERC721} from "../ERC721.sol";
import {Strings} from "../../../utils/Strings.sol";
import {IERC4906} from "../../../interfaces/IERC4906.sol";
import {IERC165} from "../../../interfaces/IERC165.sol";
/**
* @dev ERC721 token with storage based token URI management.
*/
abstract contract ERC721URIStorage is IERC4906, ERC721 {
using Strings for uint256;
// Interface ID as defined in ERC-4906. This does not correspond to a traditional interface ID as ERC-4906 only
// defines events and does not include any external function.
bytes4 private constant ERC4906_INTERFACE_ID = bytes4(0x49064906);
// Optional mapping for token URIs
mapping(uint256 tokenId => string) private _tokenURIs;
/**
* @dev See {IERC165-supportsInterface}
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, IERC165) returns (bool) {
return interfaceId == ERC4906_INTERFACE_ID || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
_requireOwned(tokenId);
string memory _tokenURI = _tokenURIs[tokenId];
string memory base = _baseURI();
// If there is no base URI, return the token URI.
if (bytes(base).length == 0) {
return _tokenURI;
}
// If both are set, concatenate the baseURI and tokenURI (via string.concat).
if (bytes(_tokenURI).length > 0) {
return string.concat(base, _tokenURI);
}
return super.tokenURI(tokenId);
}
/**
* @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
*
* Emits {MetadataUpdate}.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
_tokenURIs[tokenId] = _tokenURI;
emit MetadataUpdate(tokenId);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.20;
import {IERC721} from "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.20;
import {IERC721} from "../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 v5.0.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.20;
/**
* @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 v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./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);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @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 towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (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 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 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.
uint256 twos = denominator & (0 - denominator);
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 (unsignedRoundsUp(rounding) && 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
* towards zero.
*
* 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 + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* 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 + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* 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 + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* 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 256, 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 + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
bool private _paused;
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @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), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @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) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
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);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_platformTreasury","type":"address"},{"internalType":"uint16","name":"_platformFeeBps","type":"uint16"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidDefaultRoyalty","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidDefaultRoyaltyReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"name":"ERC2981InvalidTokenRoyalty","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC2981InvalidTokenRoyaltyReceiver","type":"error"},{"inputs":[],"name":"ERC721EnumerableForbiddenBatchMint","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ERC721OutOfBoundsIndex","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"bool","name":"blacklisted","type":"bool"}],"name":"AddressBlacklisted","type":"event"},{"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":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"funder","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BugBountyFunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"string","name":"reportId","type":"string"}],"name":"BugBountyPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"CampaignClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"},{"indexed":true,"internalType":"address","name":"nonprofit","type":"address"},{"indexed":true,"internalType":"address","name":"submitter","type":"address"},{"indexed":false,"internalType":"string","name":"category","type":"string"},{"indexed":false,"internalType":"uint256","name":"goalNative","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"goalUsd","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxEditions","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceNative","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceUsd","type":"uint256"},{"indexed":false,"internalType":"bool","name":"immediatePayoutEnabled","type":"bool"}],"name":"CampaignCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"},{"indexed":false,"internalType":"string","name":"newBaseURI","type":"string"}],"name":"CampaignMetadataUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"CampaignPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"CampaignRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"CampaignReopened","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"CampaignUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"},{"indexed":false,"internalType":"string","name":"field","type":"string"}],"name":"CampaignUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gross","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"net","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tip","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isOnchain","type":"bool"}],"name":"ContributionRecorded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"newRoyaltyBps","type":"uint96"}],"name":"DefaultRoyaltyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"donor","type":"address"},{"indexed":false,"internalType":"uint256","name":"editionNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountPaid","type":"uint256"}],"name":"EditionMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"},{"indexed":true,"internalType":"address","name":"submitter","type":"address"},{"indexed":false,"internalType":"uint256","name":"submitterAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"platformFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tipAmount","type":"uint256"}],"name":"FundsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"string","name":"recipientType","type":"string"}],"name":"ImmediatePayoutSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"oldFeeBps","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"newFeeBps","type":"uint16"}],"name":"PlatformFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"oldPriceNative","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPriceNative","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPriceUsd","type":"uint256"}],"name":"PriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"burner","type":"address"}],"name":"TokenBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"frozen","type":"bool"}],"name":"TokenFrozen","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"soulbound","type":"bool"}],"name":"TokenSoulbound","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"newURI","type":"string"}],"name":"TokenURIFixed","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":true,"internalType":"address","name":"oldTreasury","type":"address"},{"indexed":true,"internalType":"address","name":"newTreasury","type":"address"}],"name":"TreasuryUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BATCH_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","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":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"batchMint","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"tipAmount","type":"uint256"}],"name":"batchMintWithTip","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"string","name":"uri","type":"string"}],"name":"batchSetTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"blacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bugBountyPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"campaignDistributed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"campaignEditions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"campaigns","outputs":[{"internalType":"string","name":"category","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"uint256","name":"goalNative","type":"uint256"},{"internalType":"uint256","name":"goalUsd","type":"uint256"},{"internalType":"uint256","name":"grossRaised","type":"uint256"},{"internalType":"uint256","name":"netRaised","type":"uint256"},{"internalType":"uint256","name":"tipsReceived","type":"uint256"},{"internalType":"uint256","name":"editionsMinted","type":"uint256"},{"internalType":"uint256","name":"maxEditions","type":"uint256"},{"internalType":"uint256","name":"priceNative","type":"uint256"},{"internalType":"uint256","name":"priceUsd","type":"uint256"},{"internalType":"address","name":"nonprofit","type":"address"},{"internalType":"address","name":"submitter","type":"address"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"closed","type":"bool"},{"internalType":"bool","name":"refunded","type":"bool"},{"internalType":"bool","name":"immediatePayoutEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"closeCampaign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"category","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"uint256","name":"goalNative","type":"uint256"},{"internalType":"uint256","name":"goalUsd","type":"uint256"},{"internalType":"uint256","name":"maxEditions","type":"uint256"},{"internalType":"uint256","name":"priceNative","type":"uint256"},{"internalType":"uint256","name":"priceUsd","type":"uint256"},{"internalType":"address","name":"nonprofit","type":"address"},{"internalType":"address","name":"submitter","type":"address"},{"internalType":"bool","name":"immediatePayoutEnabled","type":"bool"}],"name":"createCampaign","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"deactivateCampaign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultRoyaltyBps","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deleteDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deploymentChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"distributePendingFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"internalType":"uint256","name":"toTokenId","type":"uint256"}],"name":"emitBatchMetadataUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"emitMetadataUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"frozenTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fundBugBounty","outputs":[],"stateMutability":"payable","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":"campaignId","type":"uint256"}],"name":"getCampaign","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"category","type":"string"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"uint256","name":"goalNative","type":"uint256"},{"internalType":"uint256","name":"goalUsd","type":"uint256"},{"internalType":"uint256","name":"grossRaised","type":"uint256"},{"internalType":"uint256","name":"netRaised","type":"uint256"},{"internalType":"uint256","name":"tipsReceived","type":"uint256"},{"internalType":"uint256","name":"editionsMinted","type":"uint256"},{"internalType":"uint256","name":"maxEditions","type":"uint256"},{"internalType":"uint256","name":"priceNative","type":"uint256"},{"internalType":"uint256","name":"priceUsd","type":"uint256"},{"internalType":"address","name":"nonprofit","type":"address"},{"internalType":"address","name":"submitter","type":"address"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"closed","type":"bool"},{"internalType":"bool","name":"refunded","type":"bool"},{"internalType":"bool","name":"immediatePayoutEnabled","type":"bool"}],"internalType":"struct PatriotPledgeNFTV8.CampaignView","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"getCampaignEditions","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getEditionInfo","outputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"uint256","name":"editionNumber","type":"uint256"},{"internalType":"uint256","name":"totalEditions","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"markCampaignRefunded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"address","name":"donor","type":"address"},{"internalType":"uint256","name":"amountPaid","type":"uint256"}],"name":"mintEditionToDonor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"mintWithBDAG","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"uint256","name":"tipAmount","type":"uint256"}],"name":"mintWithBDAGAndTip","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"uint256","name":"tipAmount","type":"uint256"}],"name":"mintWithTip","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"pauseCampaign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"reportId","type":"string"}],"name":"payBugBounty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"platformFeeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformTreasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"reactivateCampaign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"uint256","name":"gross","type":"uint256"},{"internalType":"uint256","name":"net","type":"uint256"},{"internalType":"uint256","name":"tip","type":"uint256"},{"internalType":"bool","name":"isOnchain","type":"bool"}],"name":"recordContribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"reopenCampaign","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":"address","name":"addr","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setBlacklisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setCampaignImmediatePayout","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":"uint16","name":"_newFeeBps","type":"uint16"}],"name":"setPlatformFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newTreasury","type":"address"}],"name":"setPlatformTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"frozen","type":"bool"}],"name":"setTokenFrozen","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":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"_soulbound","type":"bool"}],"name":"setTokenSoulbound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"uri","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"soulbound","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenEditionNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenToCampaign","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"totalCampaigns","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","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":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"unpauseCampaign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"uint256","name":"newGoalNative","type":"uint256"},{"internalType":"uint256","name":"newGoalUsd","type":"uint256"}],"name":"updateCampaignGoal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"uint256","name":"newMax","type":"uint256"}],"name":"updateCampaignMaxEditions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"string","name":"newBaseURI","type":"string"}],"name":"updateCampaignMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"address","name":"newNonprofit","type":"address"}],"name":"updateCampaignNonprofit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"uint256","name":"newPriceNative","type":"uint256"},{"internalType":"uint256","name":"newPriceUsd","type":"uint256"}],"name":"updateCampaignPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"address","name":"newSubmitter","type":"address"}],"name":"updateCampaignSubmitter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a034620004e05762005b6290601f19906001600160401b0390601f38859003818101851683019084821184831017620002875780849160409889948552833981010312620004e05781516001600160a01b038082169590929091869003620004e0576020809401519161ffff831691828403620004e05762000081620004e5565b91601583527f50617472696f74506c656467652045646974696f6e000000000000000000000087840152620000b5620004e5565b906003928383526250504560e81b8984015284518a811162000287576002546001968782811c92168015620004d5575b8c831014620003e7578b82858594116200047b575b50508b90848311600114620004145760009262000408575b505060001982871b1c191690861b176002555b8251928a841162000287578454928684811c94168015620003fd575b8b851014620003e75783838695116200038d575b508a9284116001146200032957506000926200031d575b505060001982841b1c191690831b1790555b33156200030557600d54885194339082167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a36001600160a81b0319163360ff60a01b191617600d55600e55601354928615620002d05750610bb8106200029d57601180546001600160a01b031916861790556001600160701b031990911660609190911b6dffff000000000000000000000000161760fa1760135546608052835180850192831181841017620002875791845282825260fa910152607d60a11b176000555161565c908162000506823960805181818161076b01528181610e5401528181611114015281816115c30152818161283d0152818161319301526135350152f35b634e487b7160e01b600052604160045260246000fd5b855162461bcd60e51b815260048101849052600c60248201526b08ccaca40e8dede40d0d2ced60a31b6044820152606490fd5b62461bcd60e51b815260048101859052601060248201526f496e76616c696420747265617375727960801b6044820152606490fd5b8751631e4fbdf760e01b815260006004820152602490fd5b0151905038806200016c565b86949291921691856000528a6000209260005b8c8282106200037657505084116200035d575b505050811b0190556200017e565b015160001983861b60f8161c191690553880806200034f565b83850151865589979095019493840193016200033c565b9091929350856000528a6000208480870160051c8201928d8810620003dd575b9187968a92969594930160051c01915b828110620003cd57505062000155565b60008155879650899101620003bd565b92508192620003ad565b634e487b7160e01b600052602260045260246000fd5b93607f169362000141565b01519050388062000112565b908c91868a9516600260005283600020936000905b8282106200046357505084116200044a575b505050811b0160025562000125565b015160001983891b60f8161c191690553880806200043b565b8385015186558c979095019493840193018f62000429565b90919250600260005284826000209181860160051c8301938610620004cb575b918a91869594930160051c01915b828110620004bb57508d9150620000fa565b600081558594508a9101620004a9565b925081926200049b565b91607f1691620000e5565b600080fd5b60408051919082016001600160401b03811183821017620002875760405256fe608080604052600436101561001a575b50361561001857005b005b60003560e01c90816301ffc9a714613a6b5750806302932f5614613a4d57806304634d8d1461395c57806306fdde03146138ae578063081812fc14613870578063095ea7b3146137895780630ed64eff146134fb5780630f8321ab14613487578063141961bc1461334e57806315e5b793146132a7578063162094c41461321f5780631797c8f21461315557806318160ddd1461313757806318d33e41146131105780631c4d8bc7146130845780631cc76d7514612fb15780631dda279b14612e205780631fdc217c14612d4857806322dcd13e14612d2357806323b872dd14612d0c57806325532ecd14612c505780632a55205a14612b9e5780632a76d55314612a825780632f745c59146129fe5780633190b9ea146129b75780633705f2a81461293e57806337e7b0ee146128b35780633b080a96146127ff5780633f4ba83a1461278d578063407de9df1461275c57806342842e0e1461272e57806343a19a65146126d057806347aa0dd01461264a5780634f6ccce7146125f45780635049e52f146125d65780635598f8cc146122e1578063573a2427146122b557806357487aa514611fe95780635944c75314611f145780635c975abb14611eee5780635cbc742c14611e355780636352211e14611e0557806364094ced14611d605780636fb8696c14611cd057806370a0823114611ca5578063715018a614611c4857806378e652b514611bbd5780637a18159714611b8c5780637cd86d6014611ae45780637eca30fe14611a6f5780638079ca0c14611a0f5780638456cb59146119ad5780638583d7c01461185e5780638da5cb5b146118355780638f52d21a1461171c57806395d89b4114611639578063a0712d6814611580578063a0a441bb14611519578063a22cb4651461146e578063a483011414611428578063a575008a146110d9578063aa1b103f146110ba578063b0e1c1e114611054578063b6358d9914611028578063b88d4fde14610fbe578063c169221314610f92578063c87b56dd14610f35578063c9d5084c14610e77578063cd0d009614610e3c578063cfdbf25414610e20578063d01dd6d214610da1578063d55be8c614610d84578063d696c0911461082e578063d88d6ef314610728578063db2e21bc14610679578063dbac26e91461063a578063de99347a146105d6578063e138818c146105ad578063e1a4521814610590578063e985e9c51461053a578063f2fde38b146104b1578063f3fef3a314610415578063f401f8a0146103e45763ffa1ad74146103c3573861000f565b346103df5760003660031901126103df57602060405160088152f35b600080fd5b346103df5760203660031901126103df576004356000526014602052602060ff604060002054166040519015158152f35b346103df5760403660031901126103df5761042e613b24565b6024356104396147a0565b610441614828565b8047106104755761046e916000918291829182916001600160a01b03165af1610468614722565b50614752565b6001600e55005b60405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606490fd5b346103df5760203660031901126103df576104ca613b24565b6104d26147a0565b6001600160a01b0390811690811561052157600d54826001600160601b0360a01b821617600d55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b604051631e4fbdf760e01b815260006004820152602490fd5b346103df5760403660031901126103df57610553613b24565b61055b613b3a565b9060018060a01b03809116600052600760205260406000209116600052602052602060ff604060002054166040519015158152f35b346103df5760003660031901126103df5760206040516127108152f35b346103df5760003660031901126103df576011546040516001600160a01b039091168152602090f35b346103df5760203660031901126103df576004356105f26147a0565b6000818152601760205260408120600c01805460ff60a81b1916600160a81b1790557fab1902ee37c92d1a78dda53814d64b815e7e3ee287d60843a3dbd6954e3206b49080a2005b346103df5760203660031901126103df576001600160a01b0361065b613b24565b166000526015602052602060ff604060002054166040519015158152f35b346103df5760003660031901126103df576106926147a0565b61069a614828565b4780156106f6577f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd9695602060018060a01b036106e360008080808886601154165af1610468614722565b6011541692604051908152a26001600e55005b60405162461bcd60e51b815260206004820152600a6024820152694e6f2062616c616e636560b01b6044820152606490fd5b60203660031901126103df5760206107e4600435610744614807565b336000526015835261075e60ff6040600020541615613e93565b610766614828565b6107917f00000000000000000000000000000000000000000000000000000000000000004614613ed8565b80600052601783526107df60406000206107c9600c82015460ff8160a01c16908161081e575b8161080e575b816107ff575b50613fb4565b600881015480159182156107f1575b5050613ff8565b6149d4565b6001600e55604051908152f35b6007015410905085806107d8565b60ff915060b81c1615876107c3565b905060ff8160b01c1615906107bd565b905060ff8160a81c1615906107b7565b346103df576101403660031901126103df576004356001600160401b0381116103df5761085f903690600401613d5d565b6024356001600160401b0381116103df5761087e903690600401613d5d565b9160e435916001600160a01b03831683036103df57610104356001600160a01b03811690036103df57610124359182151583036103df576108bd6147a0565b6108d4610104356001600160a01b03161515614680565b6108e86001600160a01b0385161515614640565b601054946108f586614551565b60105560405192836102408101106001600160401b0361024086011117610cf75761093691610240850160405261092d36858b613e5c565b85523691613e5c565b60208301526044356040830152606435606083015260006080830152600060a0830152600060c0830152600060e083015260843561010083015260a43561012083015260c43561014083015260018060a01b03841661016083015260018060a01b03610104351661018083015260016101a083015260006101c083015260006101e0830152600061020083015282151561022083015284600052601760205260406000209582518051906001600160401b038211610cf757610a02826109fc8b54613bfc565b8b61403b565b602090601f8311600114610d1857610a33929160009183610d0d575b50508160011b916000199060031b1c19161790565b87555b6020830151928351976001600160401b038911610cf757888895610a6c60209b610a636001860154613bfc565b6001860161403b565b8a90601f8311600114610c5057600c7f2ab86ea50b72d4284fda128c06ded7fa727600fb09348d670d9fb391a375f8b7979694610acc85610be696610bf8999661022096600092610c455750508160011b916000199060031b1c19161790565b60018201555b60408401516002820155606084015160038201556080840151600482015560a080850151600583015560c080860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a840155610160860151600b840180546001600160a01b0319166001600160a01b039283161790556101808701519490930180546101a08801516101c08901516101e08a01516102008b015199909a01516001600160c81b0319909316979096169690961795151590931b60ff60a01b169490941792151560a81b60ff60a81b169290921794151560b01b60ff60b01b169490941792151560b81b60ff60b81b169290921792151590911b60ff60c01b16919091179055565b6040519260e0845260e0840191613f93565b604435888301526064356040830152608435606083015260a435608083015260c43560a083015293151560c08201526001600160a01b0361010435811695169381900390a4604051908152f35b015190503880610a1e565b60018493929897969594016000528b6000209060005b601f1984168110610cdd5750610be693600184610220947f2ab86ea50b72d4284fda128c06ded7fa727600fb09348d670d9fb391a375f8b79b9c600c95610bf89b9a98601f19811610610cc4575b505050811b016001820155610ad2565b015160001960f88460031b161c19169055388080610cb4565b818a01518355988d01988c98506001909201918d01610c66565b634e487b7160e01b600052604160045260246000fd5b015190508a80610a1e565b9190896000526020600020906000935b601f1984168510610d69576001945083601f19811610610d50575b505050811b018755610a36565b015160001960f88460031b161c19169055898080610d43565b81810151835560209485019460019093019290910190610d28565b346103df5760003660031901126103df576020604051610bb88152f35b346103df5760403660031901126103df57610dba613b24565b7f97b7af35c8c05eca90f543eb78b16fdf2664d3e6c9a907286f310647d9813b716020610de5613d4e565b92610dee6147a0565b6001600160a01b031660008181526015835260409020805460ff191660ff86151516179055925b6040519015158152a2005b346103df5760003660031901126103df57602060405160328152f35b346103df5760003660031901126103df5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b346103df5760203660031901126103df57600435610e936147a0565b806000526017602052600c604060002001805460ff8160b01c1615610efa57610ec260ff8260b81c1615614091565b62ff00ff60a01b1916600160a01b1790557fc939ebb08504f6f162e423778b5c8dc66880bd30e8ce585de4c0612b2c5a238e600080a2005b60405162461bcd60e51b815260206004820152601360248201527210d85b5c185a59db881b9bdd0818db1bdcd959606a1b6044820152606490fd5b346103df5760203660031901126103df57600435610f52816147cc565b50600052600c602052610f8e610f6b6040600020613ca9565b6000604051610f7981613c6d565b52604051918291602083526020830190613b50565b0390f35b346103df5760203660031901126103df5760043560005260186020526020604060002054604051908152f35b346103df5760803660031901126103df57610fd7613b24565b610fdf613b3a565b90604435606435926001600160401b0384116103df57366023850112156103df57611017610018943690602481600401359101613e5c565b926110238383836140d5565b61546d565b346103df5760203660031901126103df5760043560005260196020526020604060002054604051908152f35b346103df5760203660031901126103df576004356110706147a0565b6000818152601760205260408120600c01805462ff00ff60a01b1916600160b01b1790557f5e6eb33a418de5dbbc17f989f7ae362cdfbb1748c5d603137c767027a354edbc9080a2005b346103df5760003660031901126103df576110d36147a0565b60008055005b6110e236613be2565b90916110ec614807565b33600052601560205261110760ff6040600020541615613e93565b61110f614828565b61113a7f00000000000000000000000000000000000000000000000000000000000000004614613ed8565b806000526017602052604060002091611170600c84015460ff8160a01c169081611418575b81611408575b816113f95750613fb4565b831515806113ee575b156113b6576008830154801590811561139e575b5015611362576111b56111ad826111a88760098801546144dc565b6144b9565b34101561484b565b6111be8461488e565b926111cc6040519485613c88565b848452601f196111db8661488e565b013660208601376111ec8234614715565b946111f781346144ef565b60005b82811061129857505050610f8e94600080516020615607833981519152928260046080940161122a3482546144b9565b90556006810161123b8382546144b9565b9055600c81015460c01c60ff16156112835750611259818387615259565b604051913483526020830152604082015260016060820152a26001600e5560405191829182613ba6565b6005016112918382546144b9565b9055611259565b600f908154916112a783614551565b90556112b66007860154614551565b8060078701556112c68333614c15565b6112db6112d560018801613ca9565b846148a5565b8260005260186020528760406000205560196020528060406000205587600052601a60205261130e83604060002061459c565b885182101561134c578260019360208460051b8c010152604051918252846020830152886000805160206155a783398151915260403394a4016111fa565b634e487b7160e01b600052603260045260246000fd5b60405162461bcd60e51b815260206004820152601460248201527345786365656473206d61782065646974696f6e7360601b6044820152606490fd5b90506113ae8560078601546144b9565b11158561118d565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c6964207175616e7469747960801b6044820152606490fd5b506032841115611179565b60ff915060b81c1615866107c3565b905060ff8160b01c161590611165565b905060ff8160a81c16159061115f565b346103df577f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c604061145936613b90565b6114616147a0565b82519182526020820152a1005b346103df5760403660031901126103df57611487613b24565b61148f613d4e565b6001600160a01b03909116908115611500573360005260076020526040600020826000526020526114d08160406000209060ff801983541691151516179055565b60405190151581527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b604051630b61174360e31b815260048101839052602490fd5b346103df5760203660031901126103df576004356115356147a0565b6000818152601760205260408120600c01805463ff0000ff60a01b1916600160b81b1790557f4825b022b52da7a8de8063d9ea8fd654176315fff40077d4c0374f8e1d8a245b9080a2005b60203660031901126103df5760206107e460043561159c614807565b33600052601583526115b660ff6040600020541615613e93565b6115be614828565b6115e97f00000000000000000000000000000000000000000000000000000000000000004614613ed8565b80600052601783526107df60406000206107c960ff600c830154611611828260a01c1661450f565b611620828260a81c16156145bf565b61162f828260b01c1615613f12565b60b81c1615614600565b346103df5760003660031901126103df5760405160035460008261165c83613bfc565b91828252602093600190856001821691826000146116fc57505060011461169f575b5061168b92500383613c88565b610f8e604051928284938452830190613b50565b84915060036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b906000915b8583106116e457505061168b93508201018561167e565b805483890185015287945086939092019181016116cd565b60ff19168582015261168b95151560051b850101925087915061167e9050565b346103df5760403660031901126103df576004356001600160401b038082116103df57366023830112156103df578160040135908082116103df576024830192602436918460051b0101116103df576024359081116103df57611783903690600401613d5d565b9161178c6147a0565b60005b81811061179857005b806117a66001928488614790565b35600052602060048152828060a01b03604060002054166117c9575b500161178f565b6117e96117d783868a614790565b356117e3368989613e5c565b906148a5565b7fac6d62cb5d30a7fff578060cd3dcf46ff2df7991a71c2d2aabca7e558f130f7861182c61181884878b614790565b359260405191818392835282018a8a613f93565b0390a2866117c2565b346103df5760003660031901126103df57600d546040516001600160a01b039091168152602090f35b346103df5760603660031901126103df57611877613b24565b6024356044356001600160401b0381116103df57611899903690600401613d5d565b90916118a36147a0565b6118ab614828565b60125493848211611968576001600160a01b031693841561192f577fd24fd04b4a509fac28aab0419d3841217c53a8b375b372060993dc15c350ef7f936118f58361192593614715565b60125561190c6000808080878b5af1610468614722565b6040519384938452604060208501526040840191613f93565b0390a26001600e55005b60405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f496e73756666696369656e7420626f756e747920706f6f6c00000000000000006044820152606490fd5b346103df5760003660031901126103df576119c66147a0565b6119ce614807565b600d805460ff60a01b1916600160a01b1790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602090a1005b346103df5760203660031901126103df576004356000526018602052604060002054601960205260406000205490806000526017602052610f8e600760406000200154604051938493846040919493926060820195825260208201520152565b346103df5760203660031901126103df57600435611a8b6147a0565b806000526017602052600c60406000200160ff60a01b1981541690556000805160206155e783398151915260405180611adf8160609060208152600660208201526561637469766560d01b60408201520190565b0390a2005b346103df5760203660031901126103df57611afd613b24565b611b056147a0565b6001600160a01b03908116908115611b5457601154826001600160601b0360a01b821617601155167f4ab5be82436d353e61ca18726e984e561f5c1cc7c6d38b29d2553c790434705a600080a3005b60405162461bcd60e51b815260206004820152601060248201526f496e76616c696420747265617375727960801b6044820152606490fd5b346103df5760203660031901126103df576004356000526016602052602060ff604060002054166040519015158152f35b346103df5760403660031901126103df576004357fbf025f2b09b91dc81d2b137bed7b878fb0bd75a3bfe4708d69989fda3c63485a6020611bfc613d4e565b611c046147a0565b6000848152600483526040902054611c26906001600160a01b03161515613f50565b8360005260148252610e158160406000209060ff801983541691151516179055565b346103df5760003660031901126103df57611c616147a0565b600d80546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346103df5760203660031901126103df576020611cc8611cc3613b24565b6146dc565b604051908152f35b346103df5760403660031901126103df57600435611cec613b3a565b611cf46147a0565b816000526017602052600c60406000200190815490611d1960ff8360b01c1615613f12565b6001600160a01b031690611d2e821515614680565b6001600160601b0360a01b161790556000805160206155e78339815191526040516020815280611adf602082016146c0565b346103df5760403660031901126103df57600435611d7c613b3a565b611d846147a0565b816000526017602052600b604060002091611da960ff600c85015460b01c1615613f12565b6001600160a01b031691611dbe831515614640565b01906001600160601b0360a01b8254161790556000805160206155e783398151915260606040516020815260096020820152681b9bdb9c1c9bd99a5d60ba1b6040820152a2005b346103df5760203660031901126103df576020611e236004356147cc565b6040516001600160a01b039091168152f35b346103df5760203660031901126103df5760043561ffff808216918281036103df57611e5f6147a0565b610bb88311611eba577f84e4fe32bf74c4011a7e1fde79c63acdffaf92a0112cde153e7b0abee665bc6b926040926013549261ffff60601b9060601b1661ffff60601b1984161760135583519260601c1682526020820152a1005b60405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b6044820152606490fd5b346103df5760003660031901126103df57602060ff600d5460a01c166040519015158152f35b346103df5760603660031901126103df57600435611f30613b3a565b604435906001600160601b0382168092036103df57611f4d6147a0565b612710808311611fc557506001600160a01b03908116928315611fa65760405193611f7785613c36565b84526020808501938452600091825260019052604090209251915160a01b6001600160a01b0319169116179055005b60449060405190634b4f842960e11b8252600482015260006024820152fd5b83606491846040519263dfd1fc1b60e01b8452600484015260248301526044820152fd5b346103df576020806003193601126103df576004356120066147a0565b61200e614828565b80600052601782526005604060002001805490811561227d5781471061223857600090558160005260178352604060002061271061205561ffff60135460601c16846144dc565b0490612085826120658186614715565b9486600052601b8852604060002061207e8282546144b9565b9055614715565b612094600583019182546144b9565b905581612191575b826120dc575b916060916000805160206155c783398151915293600c60018060a01b03910154169560405192835282015260006040820152a36001600e55005b600c810160018060a01b0390600080808088868654165af16120fc614722565b50156121505791606093916000805160206155c7833981519152959354168660008051602061558783398151915260405186815260408b82015280612143604082016146c0565b0390a391935091506120a2565b60405162461bcd60e51b815260048101889052601960248201527814dd589b5a5d1d195c881d1c985b9cd9995c8819985a5b1959603a1b6044820152606490fd5b60018060a01b0360008080808685601154165af16121ad614722565b50156121f3576011541684600080516020615587833981519152608060405186815260408a8201526008604082015267706c6174666f726d60c01b6060820152a361209c565b60405162461bcd60e51b815260048101879052601c60248201527f506c6174666f726d20666565207472616e73666572206661696c6564000000006044820152606490fd5b60405162461bcd60e51b815260048101859052601d60248201527f496e73756666696369656e7420636f6e74726163742062616c616e63650000006044820152606490fd5b60405162461bcd60e51b815260048101859052601060248201526f4e6f2070656e64696e672066756e647360801b6044820152606490fd5b346103df5760203660031901126103df57600435600052601b6020526020604060002054604051908152f35b346103df5760203660031901126103df576040516122fe81613c51565b60008152602081016060905260408101606090526060810160009052608081016000905260a081016000905260c081016000905260e08101600090526101008101600090526101208101600090526101408101600090526101608101600090526101808101600090526101a08101600090526101c08101600090526101e0810160009052610200810160009052610220810160009052610240016000905260043560005260176020526040600020600281015460038201546004830154600584015460068501546007860154600887015491600988015493600a89015495600160a01b60019003600b8b01541697600c8b0154996040519b6123ff8d613c51565b6004358d528c61240e82613ca9565b906020015260010161241f90613ca9565b60408d015260608c015260808b015260a08a015260c089015260e0880152610100870152610120860152610140850152610160840152610180830152600160a01b6001900381166101a08301528060a01c60ff1615156101c08301528060a81c60ff1615156101e08301528060b01c60ff1615156102008301528060b81c60ff16151561022083015260c01c60ff16151561024082015260405180916020825280516020830152602081015160408301610260905261028083016124e291613b50565b6040820151838203601f190160608501526124fd9190613b50565b9060608101516080840152608081015160a084015260a081015160c084015260c081015160e084015260e0810151610100840152610100810151610120840152610120810151610140840152610140810151610160840152610160810151610180840152600160a01b60019003610180820151166101a0840152600160a01b600190036101a0820151166101c08401526101c081015115156101e08401526101e0810151151561020084015261020081015115156102208401526102208101511515610240840152610240015115156102608301520390f35b346103df5760003660031901126103df576020601254604051908152f35b346103df5760203660031901126103df57600435600a5481101561262b5761261d602091613df2565b90546040519160031b1c8152f35b6044906040519063295f44f760e21b8252600060048301526024820152fd5b60003660031901126103df57341561269957612668346012546144b9565b6012556040513481527f1da5cc6515d0bf0b6fb40cedcd4ef3eb9a5b820440278efc9321a4491b5dd1ef60203392a2005b60405162461bcd60e51b815260206004820152600f60248201526e4d7573742073656e642066756e647360881b6044820152606490fd5b346103df5760203660031901126103df576004356126ec6147a0565b6000818152601760205260408120600c01805460ff60a81b191690557f11aa0bd3fb4d9c5622c703f91610a74140a4f88a7ebc7b4faaeaf52e3cb7aa949080a2005b346103df5761001861273f36613dbd565b906040519261274d84613c6d565b600084526110238383836140d5565b346103df5761276a36613b90565b90600052601a602052604060002080548210156103df5760209161261d91613e29565b346103df5760003660031901126103df576127a66147a0565b600d5460ff8160a01c16156127ed5760ff60a01b1916600d556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602090a1005b604051638dfc202b60e01b8152600490fd5b60206107e461280d36613b90565b90612816614807565b336000526015845261283060ff6040600020541615613e93565b612838614828565b6128637f00000000000000000000000000000000000000000000000000000000000000004614613ed8565b80600052601784526128a0604060002061288b60ff600c830154611611828260a01c1661450f565b600881015480159182156128a5575050613ff8565b614aea565b6007015410905086806107d8565b346103df5760403660031901126103df576004357f7fba17392135b4084a7d689c1f6d77139e1f1c18ee4651bf32dc35ae29ce930160206128f2613d4e565b6128fa6147a0565b600084815260048352604090205461291c906001600160a01b03161515613f50565b8360005260168252610e158160406000209060ff801983541691151516179055565b346103df576020806003193601126103df57600435600052601a6020526040600020906040519081602084549182815201936000526020600020916000905b8282106129a057610f8e8561299481890382613c88565b60405191829182613ba6565b83548652948501946001938401939091019061297d565b346103df5760203660031901126103df576129d06147a0565b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce760206040516004358152a1005b346103df5760403660031901126103df57612a17613b24565b60243590612a24816146dc565b821015612a575760018060a01b031660005260086020526040600020906000526020526020604060002054604051908152f35b60405163295f44f760e21b81526001600160a01b039190911660048201526024810191909152604490fd5b346103df5760603660031901126103df576004356040612aa0613b3a565b91612aa96147a0565b80600052602092601784528260002091612adb60ff600c850154612ad1828260a01c1661450f565b60b01c1615613f12565b612af360088401548015908115612b90575b50613ff8565b6000805160206155a7833981519152600f54948593612b1185614551565b600f55612b44612b3e60016007890198612b2b8a54614551565b809a55612b388986614c15565b01613ca9565b866148a5565b84600052601888528382600020556019885285826000205583600052601a8852612b71858360002061459c565b8151958652604435888701526001600160a01b031694a4604051908152f35b905060078501541087612aed565b346103df57612bac36613b90565b906000526001602052604060002060405190612bc782613c36565b546001600160a01b0380821680845260a09290921c602084015291929015612c23575b612c05612710916001600160601b03602086015116906144dc565b925160408051939091166001600160a01b0316835292046020820152f35b9150612710612c05604051612c3781613c36565b600054848116825260a01c602082015293915050612bea565b346103df5760a03660031901126103df57600435602435604435606435916084358015158091036103df5760008051602061560783398151915293608093612c966147a0565b86600052601760205260066040600020612cba60ff600c83015460b01c1615613f12565b612cc484876144b9565b612cd3600483019182546144b9565b905560058101612ce48482546144b9565b905501612cf28382546144b9565b9055604051938452602084015260408301526060820152a2005b346103df57610018612d1d36613dbd565b916140d5565b346103df5760003660031901126103df57602061ffff60135460601c16604051908152f35b346103df5760203660031901126103df57600435612d646147a0565b806000526017602052600c604060002001805460ff8160b01c16612ddb57612d9260ff8260b81c1615614091565b60ff60a01b1916600160a01b1790556040805160208082526006908201526561637469766560d01b918101919091526000805160206155e7833981519152908060608101611adf565b60405162461bcd60e51b815260206004820152601b60248201527f43616d706169676e207065726d616e656e746c7920636c6f73656400000000006044820152606490fd5b346103df57612e2e36613d8a565b90612e376147a0565b82600052602090601782526040600020612e5b60ff600c83015460b01c1615613f12565b60018091016001600160401b038511610cf757612e8285612e7c8354613bfc565b8361403b565b600085601f8111600114612f4c5780612eb192600091612f41575b508160011b916000199060031b1c19161790565b90555b84600052601a83526040600020816000905b612f03575b60405185815287907fd0ed2732da48175aaae07fd675a2a78b1700515722f6675d7ff5f0e09f22f3099080611adf818a018b8a613f93565b8154811015612f3c57908282612f34612f1d839585613e29565b9054612f2a368c8b613e5c565b9160031b1c6148a5565b019091612ec6565b612ecb565b905085013589612e9d565b50601f198616908260005286866000209260005b8887838310612f9a5750505010612f80575b50508185811b019055612eb4565b840135600019600388901b60f8161c191690558680612f72565b858a0135875590950194938401938a935001612f60565b346103df57612fbf36613b90565b612fc76147a0565b8160005260176020526040600020612fe960ff600c83015460b01c1615613f12565b81158015613076575b1561303157600801556000805160206155e7833981519152606060405160208152600b60208201526a6d617845646974696f6e7360a81b6040820152a2005b60405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f74207265647563652062656c6f77206d696e7465640000000000006044820152606490fd5b506007810154821015612ff2565b346103df577fc6d3da45896ce1bca9d198309a2dbeea3c73a991748f8d88d796ffa06029de936130b336613be2565b6130be9392936147a0565b836000526017602052611adf6040600020916130e460ff600c85015460b01c1615613f12565b80600a600985019486865496550155604051938493846040919493926060820195825260208201520152565b346103df5760003660031901126103df5760206001600160601b0360135416604051908152f35b346103df5760003660031901126103df576020600a54604051908152f35b60206107e461316336613b90565b9061316c614807565b336000526015845261318660ff6040600020541615613e93565b61318e614828565b6131b97f00000000000000000000000000000000000000000000000000000000000000004614613ed8565b80600052601784526128a0604060002061288b600c82015460ff8160a01c16908161320f575b816131ff575b816131f05750613fb4565b60ff915060b81c1615886107c3565b905060ff8160b01c1615906131e5565b905060ff8160a81c1615906131df565b346103df577fac6d62cb5d30a7fff578060cd3dcf46ff2df7991a71c2d2aabca7e558f130f7861324e36613d8a565b6132599392936147a0565b60008481526004602052604090205461327c906001600160a01b03161515613f50565b61329061328a368385613e5c565b856148a5565b611adf604051928392602084526020840191613f93565b346103df5760403660031901126103df5760043561330d6132c6613d4e565b6132ce6147a0565b826000526017602052600c6040600020016132f060ff825460b01c1615613f12565b805460ff60c01b191691151560c01b60ff60c01b16919091179055565b6000805160206155e783398151915260606040516020815260166020820152751a5b5b59591a585d1954185e5bdd5d115b98589b195960521b6040820152a2005b346103df5760203660031901126103df576004356000526017602052604060002061337881613ca9565b61338460018301613ca9565b90600283015492600381015490600481015490600581015460068201546007830154600884015490600985015492600a86015494600160a01b600190039788600b8901541697600c0154996040519d8e9d8e809e61024080835282016133e991613b50565b9080820390602001526133fb91613b50565b9c6040015260608d015260808c015260a08b015260c08a015260e089015261010088015261012087015261014086015261016085015281166101808401528060a01c60ff1615156101a08401528060a81c60ff1615156101c08401528060b01c60ff1615156101e08401528060b81c60ff16151561020084015260c01c60ff1615156102208301520390f35b346103df57600361349736613be2565b9192906134a26147a0565b8360005260176020526040600020906134c560ff600c84015460b01c1615613f12565b600282015501556000805160206155e7833981519152606060405160208152600460208201526319dbd85b60e21b6040820152a2005b61350436613b90565b9061350d614807565b33600052601560205261352860ff6040600020541615613e93565b613530614828565b61355b7f00000000000000000000000000000000000000000000000000000000000000004614613ed8565b8060005260176020526040600020613590600c82015460ff8160a01c169081613779575b81613769575b8161375a5750613fb4565b8215158061374f575b156113b65760088101548015908115613737575b5015611362576135c46111ad8460098401546144dc565b6135cd8361488e565b926135db6040519485613c88565b808452601f196135ea8261488e565b013660208601376135fb81346144ef565b60005b82811061368957610f8e8686866004810161361a3482546144b9565b9055600c81015460c01c60ff161561367457506136373482615066565b60008051602061560783398151915260806040513481523460208201526000604082015260016060820152a26001600e5560405191829182613ba6565b6005016136823482546144b9565b9055613637565b600f9081549161369883614551565b90556136a76007860154614551565b8060078701556136b78333614c15565b6136c66112d560018801613ca9565b8260005260186020528660406000205560196020528060406000205586600052601a6020526136f983604060002061459c565b875182101561134c578260019360208460051b8b010152604051918252846020830152876000805160206155a783398151915260403394a4016135fe565b90506137478460078401546144b9565b1115846135ad565b506032831115613599565b60ff915060b81c1615856107c3565b905060ff8160b01c161590613585565b905060ff8160a81c16159061357f565b346103df5760403660031901126103df576137a2613b24565b6024356137ae816147cc565b3315158061385d575b80613830575b613818576001600160a01b039283169282918491167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4600090815260066020526040902080546001600160a01b0319169091179055005b60405163a9fbf51f60e01b8152336004820152602490fd5b5060018060a01b038116600052600760205260406000203360005260205260ff60406000205416156137bd565b506001600160a01b0381163314156137b7565b346103df5760203660031901126103df5760043561388d816147cc565b506000526006602052602060018060a01b0360406000205416604051908152f35b346103df5760003660031901126103df576040516002546000826138d183613bfc565b91828252602093600190856001821691826000146116fc5750506001146138ff575061168b92500383613c88565b84915060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace906000915b85831061394457505061168b93508201018561167e565b8054838901850152879450869390920191810161392d565b346103df5760403660031901126103df57613975613b24565b6024356001600160601b038116918282036103df576139926147a0565b612710808411613a2f57506001600160a01b0316918215613a16577f35804d3532228d15c4fe3fa7a4fb8100c86dc285216e9c806f5d6f2cef5528399260209282846040516139e081613c36565b848152015260a01b6001600160a01b03191617600055601380546bffffffffffffffffffffffff191682179055604051908152a1005b604051635b6cc80560e11b815260006004820152602490fd5b8360449160405191636f483d0960e01b835260048301526024820152fd5b346103df5760003660031901126103df576020601054604051908152f35b346103df5760203660031901126103df576004359063ffffffff60e01b82168092036103df57602091632483248360e11b8114908115613aad575b5015158152f35b63780e9d6360e01b811491508115613ac7575b5083613aa6565b6380ac58cd60e01b811491508115613b13575b8115613ae8575b5083613ac0565b63152a902d60e11b811491508115613b02575b5083613ae1565b6301ffc9a760e01b14905083613afb565b635b5e139f60e01b81149150613ada565b600435906001600160a01b03821682036103df57565b602435906001600160a01b03821682036103df57565b919082519283825260005b848110613b7c575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201613b5b565b60409060031901126103df576004359060243590565b602090602060408183019282815285518094520193019160005b828110613bce575050505090565b835185529381019392810192600101613bc0565b60609060031901126103df57600435906024359060443590565b90600182811c92168015613c2c575b6020831014613c1657565b634e487b7160e01b600052602260045260246000fd5b91607f1691613c0b565b604081019081106001600160401b03821117610cf757604052565b61026081019081106001600160401b03821117610cf757604052565b602081019081106001600160401b03821117610cf757604052565b90601f801991011681019081106001600160401b03821117610cf757604052565b90604051918260008254613cbc81613bfc565b90818452602094600191600181169081600014613d2c5750600114613ced575b505050613ceb92500383613c88565b565b600090815285812095935091905b818310613d14575050613ceb9350820101388080613cdc565b85548884018501529485019487945091830191613cfb565b92505050613ceb94925060ff191682840152151560051b820101388080613cdc565b6024359081151582036103df57565b9181601f840112156103df578235916001600160401b0383116103df57602083818601950101116103df57565b9060406003198301126103df5760043591602435906001600160401b0382116103df57613db991600401613d5d565b9091565b60609060031901126103df576001600160a01b039060043582811681036103df579160243590811681036103df579060443590565b600a5481101561134c57600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80190600090565b805482101561134c5760005260206000200190600090565b6001600160401b038111610cf757601f01601f191660200190565b929192613e6882613e41565b91613e766040519384613c88565b8294818452818301116103df578281602093846000960137010152565b15613e9a57565b60405162461bcd60e51b81526020600482015260166024820152751059191c995cdcc81a5cc8189b1858dadb1a5cdd195960521b6044820152606490fd5b15613edf57565b60405162461bcd60e51b815260206004820152600b60248201526a2bb937b7339031b430b4b760a91b6044820152606490fd5b15613f1957565b60405162461bcd60e51b815260206004820152600f60248201526e10d85b5c185a59db8818db1bdcd959608a1b6044820152606490fd5b15613f5757565b60405162461bcd60e51b8152602060048201526014602482015273151bdad95b88191bd95cc81b9bdd08195e1a5cdd60621b6044820152606490fd5b908060209392818452848401376000828201840152601f01601f1916010190565b15613fbb57565b60405162461bcd60e51b815260206004820152601560248201527443616d706169676e206e6f74206d696e7461626c6560581b6044820152606490fd5b15613fff57565b60405162461bcd60e51b815260206004820152601460248201527313585e0819591a5d1a5bdb9cc81c995858da195960621b6044820152606490fd5b90601f811161404957505050565b6000916000526020600020906020601f850160051c83019410614087575b601f0160051c01915b82811061407c57505050565b818155600101614070565b9092508290614067565b1561409857565b60405162461bcd60e51b815260206004820152601560248201527410d85b5c185a59db881dd85cc81c99599d5b991959605a1b6044820152606490fd5b6001600160a01b0382811693919084156144a05760009183835260049560209387855260409484868320541680151580614498575b61436a575b5086825288815284868320541697331515806142d8575b50881580156142a5575b84845260058352878420805460010190558884528a835287842080546001600160a01b0319168617905588858b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8780a41561422957600a54888452600b83528784205561419d88614560565b8389036141d8575b5050505016908184036141b9575050505050565b516364283d7b60e01b8152938401526024830152604482015260649150fd5b6141e1906146dc565b6000198101939084116142165782916009918894526008815283832085845281528884842055888352522055388080806141a5565b634e487b7160e01b835260118a52602483fd5b88841461419d57614239896146dc565b888452600983528784205481810361426e575b508884528388812055898452600883528784209084528252828781205561419d565b8a8552600884528885208286528452888520548b8652600885528986208287528552808a872055855260098452888520553861424c565b600089815260066020526040902080546001600160a01b0319169055898452600583528784208054600019019055614130565b80614329575b156142e95738614126565b878a888b61430657916024925191637e27328960e01b8352820152fd5b5163177e802f60e01b815233918101918252602082019290925281906040010390fd5b50338914801561434e575b806142de57508783526006825233868885205416146142de565b5088835260078252868320338452825260ff8784205416614334565b6014825260ff8784205416614463578783526016825260ff878420541661442b5782526015815260ff86832054166143f1578282526015815260ff86832054166143b4573861410f565b8860649187519162461bcd60e51b83528201526018602482015277149958da5c1a595b9d081a5cc8189b1858dadb1a5cdd195960421b6044820152fd5b8860649187519162461bcd60e51b8352820152601560248201527414d95b99195c881a5cc8189b1858dadb1a5cdd1959605a1b6044820152fd5b865162461bcd60e51b8152808b018390526012602482015271151bdad95b881a5cc81cdbdd5b189bdd5b9960721b6044820152606490fd5b865162461bcd60e51b8152808b01839052600f60248201526e2a37b5b2b71034b990333937bd32b760891b6044820152606490fd5b50600161410a565b604051633250574960e11b815260006004820152602490fd5b919082018092116144c657565b634e487b7160e01b600052601160045260246000fd5b818102929181159184041417156144c657565b81156144f9570490565b634e487b7160e01b600052601260045260246000fd5b1561451657565b60405162461bcd60e51b815260206004820152601360248201527243616d706169676e206e6f742061637469766560681b6044820152606490fd5b60001981146144c65760010190565b600a5490600160401b821015610cf757614583826001613ceb9401600a55613df2565b90919082549060031b91821b91600019901b1916179055565b90815491600160401b831015610cf75782614583916001613ceb95018155613e29565b156145c657565b60405162461bcd60e51b815260206004820152601260248201527110d85b5c185a59db881a5cc81c185d5cd95960721b6044820152606490fd5b1561460757565b60405162461bcd60e51b815260206004820152601160248201527010d85b5c185a59db881c99599d5b991959607a1b6044820152606490fd5b1561464757565b60405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081b9bdb9c1c9bd99a5d607a1b6044820152606490fd5b1561468757565b60405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21039bab136b4ba3a32b960791b6044820152606490fd5b600981526839bab136b4ba3a32b960b91b602082015260400190565b6001600160a01b031680156146fc57600052600560205260406000205490565b6040516322718ad960e21b815260006004820152602490fd5b919082039182116144c657565b3d1561474d573d9061473382613e41565b916147416040519384613c88565b82523d6000602084013e565b606090565b1561475957565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b919081101561134c5760051b0190565b600d546001600160a01b031633036147b457565b60405163118cdaa760e01b8152336004820152602490fd5b6000818152600460205260409020546001600160a01b03169081156147ef575090565b60249060405190637e27328960e01b82526004820152fd5b60ff600d5460a01c1661481657565b60405163d93c066560e01b8152600490fd5b6002600e5414614839576002600e55565b604051633ee5aeb560e01b8152600490fd5b1561485257565b60405162461bcd60e51b8152602060048201526014602482015273125b9cdd59999a58da595b9d081c185e5b595b9d60621b6044820152606490fd5b6001600160401b038111610cf75760051b60200190565b919091600090808252602091600c835260408120908551956001600160401b0387116149c0576148df876148d98554613bfc565b8561403b565b8491601f881160011461493c57966149309281927ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7989992610c455750508160011b916000199060031b1c19161790565b90555b604051908152a1565b9190601f198816848452868420935b8181106149a957509160019391897ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7999a9410614990575b505050811b019055614933565b015160001960f88460031b161c19169055388080614983565b92938760018192878601518155019501930161494b565b634e487b7160e01b82526041600452602482fd5b600090808252600080516020615607833981519152608060206017815260409485812095614a08600988015434101561484b565b600f5496614a1588614551565b600f556007810190614a278254614551565b809255614a348933614c15565b614a49614a4360018301613ca9565b8a6148a5565b888452601885528783852055601985528183852055878452601a8552614a718984862061459c565b60048101614a803482546144b9565b9055600c81015460c01c60ff1615614ad55750614a9d3488615066565b8151908152348482015287876000805160206155a7833981519152843394a4805192348452349084015282015260016060820152a290565b600501614ae33482546144b9565b9055614a9d565b600080516020615607833981519152608060009383855260209060178252604080872096614b1f6111ad8460098b01546144b9565b600f5497614b2c89614551565b600f556007810190614b3e8254614551565b809255614b8c8a85614b508834614715565b95614b5b8333614c15565b614b6a6112d560018701613ca9565b82815260188a528c8282205560198a5285828220558c8152601a8a522061459c565b60048101614b9b3482546144b9565b905560068101614bac8682546144b9565b9055600c81015460c01c60ff1615614c005750614bca84838a615259565b8251908152348582015288886000805160206155a7833981519152853394a481519334855284015282015260016060820152a290565b600501614c0e8382546144b9565b9055614bca565b6040805190614c2382613c6d565b60008083526001600160a01b039484861693909190841561504e5782825260049560209787895280868520541680151580615046575b614f16575b5084845287895285842054168681159182159283614ee3575b82875260058c52888720805460010190558787528a8c5288872080546001600160a01b031916841790558783837fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8a80a415614e6557600a54878752600b8c5288872055614ce487614560565b03614e19575b614e02573b614cfd575b50505050505050565b86614d3a918596979899955180938192630a85bd0160e11b97888452338d8501528760248501526044840152608060648401526084830190613b50565b0381858a5af190829082614db7575b5050614d7f57505050614d5a614722565b80519485614d7957505051633250574960e11b81529182015260249150fd5b85925001fd5b9195506001600160e01b031990911603614da25750505038808080808080614cf4565b51633250574960e11b81529182015260249150fd5b909192508881813d8311614dfb575b614dd08183613c88565b81010312614df75751906001600160e01b031982168203614df45750903880614d49565b80fd5b5080fd5b503d614dc6565b84516339e3563760e11b8152808801849052602490fd5b614e22826146dc565b6000198101908111614e525787855260088a528685208186528a52858786205585855260098a5286852055614cea565b634e487b7160e01b855260118952602485fd5b808214614ce457614e75816146dc565b87875260098c5288872054818103614eaa575b50878752868981205581875260088c528887209087528b528588812055614ce4565b82885260088d528988208289528d528c60088b8a205491858b52528d8b8a2090838b5252808b8a2055885260098d528988205538614e88565b600088815260066020526040902080546001600160a01b031916905581875260058c528887208054600019019055614c77565b60148a5260ff87862054166150115785855260168a5260ff8786205416614fd95784526015895260ff8685205416614f9e578684526015895260ff8685205416614f605738614c5e565b855162461bcd60e51b81528089018a90526018602482015277149958da5c1a595b9d081a5cc8189b1858dadb1a5cdd195960421b6044820152606490fd5b855162461bcd60e51b81528089018a9052601560248201527414d95b99195c881a5cc8189b1858dadb1a5cdd1959605a1b6044820152606490fd5b865162461bcd60e51b8152808a018b90526012602482015271151bdad95b881a5cc81cdbdd5b189bdd5b9960721b6044820152606490fd5b865162461bcd60e51b8152808a018b9052600f60248201526e2a37b5b2b71034b990333937bd32b760891b6044820152606490fd5b506001614c59565b8351633250574960e11b815260048101839052602490fd5b60009181835260209260178452604080822061271061508e61ffff60135460601c16866144dc565b04906150b48261509e8188614715565b96888752601b8a5285872061207e8282546144b9565b6150c3600583019182546144b9565b9055816151b7575b84615103575b600c01548251948552958401528201526001600160a01b03909216916000805160206155c783398151915290606090a3565b600c810160018060a01b0390858080808a868654165af1615122614722565b5015615177579160609593916000805160206155c78339815191529795935416886000805160206155878339815191528551888152868d820152806151688882016146c0565b0390a3919395509193506150d1565b845162461bcd60e51b8152600481018a9052601960248201527814dd589b5a5d1d195c881d1c985b9cd9995c8819985a5b1959603a1b6044820152606490fd5b60018060a01b03848080808685601154165af16151d2614722565b501561521557601154168660008051602061558783398151915260808651868152878c82015260088882015267706c6174666f726d60c01b6060820152a36150cb565b835162461bcd60e51b815260048101899052601c60248201527f506c6174666f726d20666565207472616e73666572206661696c6564000000006044820152606490fd5b90600090828252602093601785526040948584209061271061528461ffff60135460601c16866144dc565b04946152b886615298866111a8838a614715565b966152a387826144b9565b8a8552601b865261207e8c86209182546144b9565b6152c7600585019182546144b9565b9055856153cb575b84615317575b5050600c01549451918252602082019290925260408101919091526001600160a01b03909216916000805160206155c78339815191529080606081015b0390a3565b600c830160018060a01b039180808089868654165af1615335614722565b501561538b57918760008051602061558783398151915261531295936000805160206155c7833981519152999897955416928b8051918983528201528061537d8d82016146c0565b0390a39181939495506152d5565b885162461bcd60e51b815260048101849052601960248201527814dd589b5a5d1d195c881d1c985b9cd9995c8819985a5b1959603a1b6044820152606490fd5b60018060a01b03818080808a85601154165af16153e6614722565b501561542957601154168760008051602061558783398151915260808b518a81528c8782015260088d82015267706c6174666f726d60c01b6060820152a36152cf565b885162461bcd60e51b815260048101849052601c60248201527f506c6174666f726d20666565207472616e73666572206661696c6564000000006044820152606490fd5b9190803b61547c575b50505050565b6154be60018060a01b0380921694604051938493630a85bd0160e11b968786523360048701521660248501526044840152608060648401526084830190613b50565b03906020816000938185885af19082908261553d575b505061550c57826154e3614722565b805191908261550557604051633250574960e11b815260048101839052602490fd5b9050602001fd5b6001600160e01b03191603615525575038808080615476565b60249060405190633250574960e11b82526004820152fd5b909192506020813d60201161557e575b8161555a60209383613c88565b81010312614df75751906001600160e01b031982168203614df457509038806154d4565b3d915061554d56fec5116d0bff033daa6db9b6cf401237ef4f85a0a6cbe32bfb53d189b3e6c4bad644a73422883fd5aac8dde6ef3688c62f25a4fb22e7a395bafb411ec4803ab1bde6bf69167ad8e0c635fcc1b7beeafcc578b34e3c24b18668a3a118279345414a7a9a4f151cc0b6349bd7062416b8f68d1d73c3f457efc221520eb5547595d2d8f1a038a86c47446d2a26b7852348eee74e6d63d5a71792df01e40c2e6d0e1ca2a264697066735822122031d96c1bbb8c35253141d0decb6a04fc7fcf7086be1bcdf45a7368afb129068c64736f6c634300081800330000000000000000000000004e8e445a9957cd251059cd52a00777a25f8cd53e0000000000000000000000000000000000000000000000000000000000000064
Deployed Bytecode
0x608080604052600436101561001a575b50361561001857005b005b60003560e01c90816301ffc9a714613a6b5750806302932f5614613a4d57806304634d8d1461395c57806306fdde03146138ae578063081812fc14613870578063095ea7b3146137895780630ed64eff146134fb5780630f8321ab14613487578063141961bc1461334e57806315e5b793146132a7578063162094c41461321f5780631797c8f21461315557806318160ddd1461313757806318d33e41146131105780631c4d8bc7146130845780631cc76d7514612fb15780631dda279b14612e205780631fdc217c14612d4857806322dcd13e14612d2357806323b872dd14612d0c57806325532ecd14612c505780632a55205a14612b9e5780632a76d55314612a825780632f745c59146129fe5780633190b9ea146129b75780633705f2a81461293e57806337e7b0ee146128b35780633b080a96146127ff5780633f4ba83a1461278d578063407de9df1461275c57806342842e0e1461272e57806343a19a65146126d057806347aa0dd01461264a5780634f6ccce7146125f45780635049e52f146125d65780635598f8cc146122e1578063573a2427146122b557806357487aa514611fe95780635944c75314611f145780635c975abb14611eee5780635cbc742c14611e355780636352211e14611e0557806364094ced14611d605780636fb8696c14611cd057806370a0823114611ca5578063715018a614611c4857806378e652b514611bbd5780637a18159714611b8c5780637cd86d6014611ae45780637eca30fe14611a6f5780638079ca0c14611a0f5780638456cb59146119ad5780638583d7c01461185e5780638da5cb5b146118355780638f52d21a1461171c57806395d89b4114611639578063a0712d6814611580578063a0a441bb14611519578063a22cb4651461146e578063a483011414611428578063a575008a146110d9578063aa1b103f146110ba578063b0e1c1e114611054578063b6358d9914611028578063b88d4fde14610fbe578063c169221314610f92578063c87b56dd14610f35578063c9d5084c14610e77578063cd0d009614610e3c578063cfdbf25414610e20578063d01dd6d214610da1578063d55be8c614610d84578063d696c0911461082e578063d88d6ef314610728578063db2e21bc14610679578063dbac26e91461063a578063de99347a146105d6578063e138818c146105ad578063e1a4521814610590578063e985e9c51461053a578063f2fde38b146104b1578063f3fef3a314610415578063f401f8a0146103e45763ffa1ad74146103c3573861000f565b346103df5760003660031901126103df57602060405160088152f35b600080fd5b346103df5760203660031901126103df576004356000526014602052602060ff604060002054166040519015158152f35b346103df5760403660031901126103df5761042e613b24565b6024356104396147a0565b610441614828565b8047106104755761046e916000918291829182916001600160a01b03165af1610468614722565b50614752565b6001600e55005b60405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606490fd5b346103df5760203660031901126103df576104ca613b24565b6104d26147a0565b6001600160a01b0390811690811561052157600d54826001600160601b0360a01b821617600d55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b604051631e4fbdf760e01b815260006004820152602490fd5b346103df5760403660031901126103df57610553613b24565b61055b613b3a565b9060018060a01b03809116600052600760205260406000209116600052602052602060ff604060002054166040519015158152f35b346103df5760003660031901126103df5760206040516127108152f35b346103df5760003660031901126103df576011546040516001600160a01b039091168152602090f35b346103df5760203660031901126103df576004356105f26147a0565b6000818152601760205260408120600c01805460ff60a81b1916600160a81b1790557fab1902ee37c92d1a78dda53814d64b815e7e3ee287d60843a3dbd6954e3206b49080a2005b346103df5760203660031901126103df576001600160a01b0361065b613b24565b166000526015602052602060ff604060002054166040519015158152f35b346103df5760003660031901126103df576106926147a0565b61069a614828565b4780156106f6577f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd9695602060018060a01b036106e360008080808886601154165af1610468614722565b6011541692604051908152a26001600e55005b60405162461bcd60e51b815260206004820152600a6024820152694e6f2062616c616e636560b01b6044820152606490fd5b60203660031901126103df5760206107e4600435610744614807565b336000526015835261075e60ff6040600020541615613e93565b610766614828565b6107917f00000000000000000000000000000000000000000000000000000000000000014614613ed8565b80600052601783526107df60406000206107c9600c82015460ff8160a01c16908161081e575b8161080e575b816107ff575b50613fb4565b600881015480159182156107f1575b5050613ff8565b6149d4565b6001600e55604051908152f35b6007015410905085806107d8565b60ff915060b81c1615876107c3565b905060ff8160b01c1615906107bd565b905060ff8160a81c1615906107b7565b346103df576101403660031901126103df576004356001600160401b0381116103df5761085f903690600401613d5d565b6024356001600160401b0381116103df5761087e903690600401613d5d565b9160e435916001600160a01b03831683036103df57610104356001600160a01b03811690036103df57610124359182151583036103df576108bd6147a0565b6108d4610104356001600160a01b03161515614680565b6108e86001600160a01b0385161515614640565b601054946108f586614551565b60105560405192836102408101106001600160401b0361024086011117610cf75761093691610240850160405261092d36858b613e5c565b85523691613e5c565b60208301526044356040830152606435606083015260006080830152600060a0830152600060c0830152600060e083015260843561010083015260a43561012083015260c43561014083015260018060a01b03841661016083015260018060a01b03610104351661018083015260016101a083015260006101c083015260006101e0830152600061020083015282151561022083015284600052601760205260406000209582518051906001600160401b038211610cf757610a02826109fc8b54613bfc565b8b61403b565b602090601f8311600114610d1857610a33929160009183610d0d575b50508160011b916000199060031b1c19161790565b87555b6020830151928351976001600160401b038911610cf757888895610a6c60209b610a636001860154613bfc565b6001860161403b565b8a90601f8311600114610c5057600c7f2ab86ea50b72d4284fda128c06ded7fa727600fb09348d670d9fb391a375f8b7979694610acc85610be696610bf8999661022096600092610c455750508160011b916000199060031b1c19161790565b60018201555b60408401516002820155606084015160038201556080840151600482015560a080850151600583015560c080860151600684015560e0860151600784015561010086015160088401556101208601516009840155610140860151600a840155610160860151600b840180546001600160a01b0319166001600160a01b039283161790556101808701519490930180546101a08801516101c08901516101e08a01516102008b015199909a01516001600160c81b0319909316979096169690961795151590931b60ff60a01b169490941792151560a81b60ff60a81b169290921794151560b01b60ff60b01b169490941792151560b81b60ff60b81b169290921792151590911b60ff60c01b16919091179055565b6040519260e0845260e0840191613f93565b604435888301526064356040830152608435606083015260a435608083015260c43560a083015293151560c08201526001600160a01b0361010435811695169381900390a4604051908152f35b015190503880610a1e565b60018493929897969594016000528b6000209060005b601f1984168110610cdd5750610be693600184610220947f2ab86ea50b72d4284fda128c06ded7fa727600fb09348d670d9fb391a375f8b79b9c600c95610bf89b9a98601f19811610610cc4575b505050811b016001820155610ad2565b015160001960f88460031b161c19169055388080610cb4565b818a01518355988d01988c98506001909201918d01610c66565b634e487b7160e01b600052604160045260246000fd5b015190508a80610a1e565b9190896000526020600020906000935b601f1984168510610d69576001945083601f19811610610d50575b505050811b018755610a36565b015160001960f88460031b161c19169055898080610d43565b81810151835560209485019460019093019290910190610d28565b346103df5760003660031901126103df576020604051610bb88152f35b346103df5760403660031901126103df57610dba613b24565b7f97b7af35c8c05eca90f543eb78b16fdf2664d3e6c9a907286f310647d9813b716020610de5613d4e565b92610dee6147a0565b6001600160a01b031660008181526015835260409020805460ff191660ff86151516179055925b6040519015158152a2005b346103df5760003660031901126103df57602060405160328152f35b346103df5760003660031901126103df5760206040517f00000000000000000000000000000000000000000000000000000000000000018152f35b346103df5760203660031901126103df57600435610e936147a0565b806000526017602052600c604060002001805460ff8160b01c1615610efa57610ec260ff8260b81c1615614091565b62ff00ff60a01b1916600160a01b1790557fc939ebb08504f6f162e423778b5c8dc66880bd30e8ce585de4c0612b2c5a238e600080a2005b60405162461bcd60e51b815260206004820152601360248201527210d85b5c185a59db881b9bdd0818db1bdcd959606a1b6044820152606490fd5b346103df5760203660031901126103df57600435610f52816147cc565b50600052600c602052610f8e610f6b6040600020613ca9565b6000604051610f7981613c6d565b52604051918291602083526020830190613b50565b0390f35b346103df5760203660031901126103df5760043560005260186020526020604060002054604051908152f35b346103df5760803660031901126103df57610fd7613b24565b610fdf613b3a565b90604435606435926001600160401b0384116103df57366023850112156103df57611017610018943690602481600401359101613e5c565b926110238383836140d5565b61546d565b346103df5760203660031901126103df5760043560005260196020526020604060002054604051908152f35b346103df5760203660031901126103df576004356110706147a0565b6000818152601760205260408120600c01805462ff00ff60a01b1916600160b01b1790557f5e6eb33a418de5dbbc17f989f7ae362cdfbb1748c5d603137c767027a354edbc9080a2005b346103df5760003660031901126103df576110d36147a0565b60008055005b6110e236613be2565b90916110ec614807565b33600052601560205261110760ff6040600020541615613e93565b61110f614828565b61113a7f00000000000000000000000000000000000000000000000000000000000000014614613ed8565b806000526017602052604060002091611170600c84015460ff8160a01c169081611418575b81611408575b816113f95750613fb4565b831515806113ee575b156113b6576008830154801590811561139e575b5015611362576111b56111ad826111a88760098801546144dc565b6144b9565b34101561484b565b6111be8461488e565b926111cc6040519485613c88565b848452601f196111db8661488e565b013660208601376111ec8234614715565b946111f781346144ef565b60005b82811061129857505050610f8e94600080516020615607833981519152928260046080940161122a3482546144b9565b90556006810161123b8382546144b9565b9055600c81015460c01c60ff16156112835750611259818387615259565b604051913483526020830152604082015260016060820152a26001600e5560405191829182613ba6565b6005016112918382546144b9565b9055611259565b600f908154916112a783614551565b90556112b66007860154614551565b8060078701556112c68333614c15565b6112db6112d560018801613ca9565b846148a5565b8260005260186020528760406000205560196020528060406000205587600052601a60205261130e83604060002061459c565b885182101561134c578260019360208460051b8c010152604051918252846020830152886000805160206155a783398151915260403394a4016111fa565b634e487b7160e01b600052603260045260246000fd5b60405162461bcd60e51b815260206004820152601460248201527345786365656473206d61782065646974696f6e7360601b6044820152606490fd5b90506113ae8560078601546144b9565b11158561118d565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c6964207175616e7469747960801b6044820152606490fd5b506032841115611179565b60ff915060b81c1615866107c3565b905060ff8160b01c161590611165565b905060ff8160a81c16159061115f565b346103df577f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c604061145936613b90565b6114616147a0565b82519182526020820152a1005b346103df5760403660031901126103df57611487613b24565b61148f613d4e565b6001600160a01b03909116908115611500573360005260076020526040600020826000526020526114d08160406000209060ff801983541691151516179055565b60405190151581527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b604051630b61174360e31b815260048101839052602490fd5b346103df5760203660031901126103df576004356115356147a0565b6000818152601760205260408120600c01805463ff0000ff60a01b1916600160b81b1790557f4825b022b52da7a8de8063d9ea8fd654176315fff40077d4c0374f8e1d8a245b9080a2005b60203660031901126103df5760206107e460043561159c614807565b33600052601583526115b660ff6040600020541615613e93565b6115be614828565b6115e97f00000000000000000000000000000000000000000000000000000000000000014614613ed8565b80600052601783526107df60406000206107c960ff600c830154611611828260a01c1661450f565b611620828260a81c16156145bf565b61162f828260b01c1615613f12565b60b81c1615614600565b346103df5760003660031901126103df5760405160035460008261165c83613bfc565b91828252602093600190856001821691826000146116fc57505060011461169f575b5061168b92500383613c88565b610f8e604051928284938452830190613b50565b84915060036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b906000915b8583106116e457505061168b93508201018561167e565b805483890185015287945086939092019181016116cd565b60ff19168582015261168b95151560051b850101925087915061167e9050565b346103df5760403660031901126103df576004356001600160401b038082116103df57366023830112156103df578160040135908082116103df576024830192602436918460051b0101116103df576024359081116103df57611783903690600401613d5d565b9161178c6147a0565b60005b81811061179857005b806117a66001928488614790565b35600052602060048152828060a01b03604060002054166117c9575b500161178f565b6117e96117d783868a614790565b356117e3368989613e5c565b906148a5565b7fac6d62cb5d30a7fff578060cd3dcf46ff2df7991a71c2d2aabca7e558f130f7861182c61181884878b614790565b359260405191818392835282018a8a613f93565b0390a2866117c2565b346103df5760003660031901126103df57600d546040516001600160a01b039091168152602090f35b346103df5760603660031901126103df57611877613b24565b6024356044356001600160401b0381116103df57611899903690600401613d5d565b90916118a36147a0565b6118ab614828565b60125493848211611968576001600160a01b031693841561192f577fd24fd04b4a509fac28aab0419d3841217c53a8b375b372060993dc15c350ef7f936118f58361192593614715565b60125561190c6000808080878b5af1610468614722565b6040519384938452604060208501526040840191613f93565b0390a26001600e55005b60405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606490fd5b60405162461bcd60e51b815260206004820152601860248201527f496e73756666696369656e7420626f756e747920706f6f6c00000000000000006044820152606490fd5b346103df5760003660031901126103df576119c66147a0565b6119ce614807565b600d805460ff60a01b1916600160a01b1790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25890602090a1005b346103df5760203660031901126103df576004356000526018602052604060002054601960205260406000205490806000526017602052610f8e600760406000200154604051938493846040919493926060820195825260208201520152565b346103df5760203660031901126103df57600435611a8b6147a0565b806000526017602052600c60406000200160ff60a01b1981541690556000805160206155e783398151915260405180611adf8160609060208152600660208201526561637469766560d01b60408201520190565b0390a2005b346103df5760203660031901126103df57611afd613b24565b611b056147a0565b6001600160a01b03908116908115611b5457601154826001600160601b0360a01b821617601155167f4ab5be82436d353e61ca18726e984e561f5c1cc7c6d38b29d2553c790434705a600080a3005b60405162461bcd60e51b815260206004820152601060248201526f496e76616c696420747265617375727960801b6044820152606490fd5b346103df5760203660031901126103df576004356000526016602052602060ff604060002054166040519015158152f35b346103df5760403660031901126103df576004357fbf025f2b09b91dc81d2b137bed7b878fb0bd75a3bfe4708d69989fda3c63485a6020611bfc613d4e565b611c046147a0565b6000848152600483526040902054611c26906001600160a01b03161515613f50565b8360005260148252610e158160406000209060ff801983541691151516179055565b346103df5760003660031901126103df57611c616147a0565b600d80546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346103df5760203660031901126103df576020611cc8611cc3613b24565b6146dc565b604051908152f35b346103df5760403660031901126103df57600435611cec613b3a565b611cf46147a0565b816000526017602052600c60406000200190815490611d1960ff8360b01c1615613f12565b6001600160a01b031690611d2e821515614680565b6001600160601b0360a01b161790556000805160206155e78339815191526040516020815280611adf602082016146c0565b346103df5760403660031901126103df57600435611d7c613b3a565b611d846147a0565b816000526017602052600b604060002091611da960ff600c85015460b01c1615613f12565b6001600160a01b031691611dbe831515614640565b01906001600160601b0360a01b8254161790556000805160206155e783398151915260606040516020815260096020820152681b9bdb9c1c9bd99a5d60ba1b6040820152a2005b346103df5760203660031901126103df576020611e236004356147cc565b6040516001600160a01b039091168152f35b346103df5760203660031901126103df5760043561ffff808216918281036103df57611e5f6147a0565b610bb88311611eba577f84e4fe32bf74c4011a7e1fde79c63acdffaf92a0112cde153e7b0abee665bc6b926040926013549261ffff60601b9060601b1661ffff60601b1984161760135583519260601c1682526020820152a1005b60405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b6044820152606490fd5b346103df5760003660031901126103df57602060ff600d5460a01c166040519015158152f35b346103df5760603660031901126103df57600435611f30613b3a565b604435906001600160601b0382168092036103df57611f4d6147a0565b612710808311611fc557506001600160a01b03908116928315611fa65760405193611f7785613c36565b84526020808501938452600091825260019052604090209251915160a01b6001600160a01b0319169116179055005b60449060405190634b4f842960e11b8252600482015260006024820152fd5b83606491846040519263dfd1fc1b60e01b8452600484015260248301526044820152fd5b346103df576020806003193601126103df576004356120066147a0565b61200e614828565b80600052601782526005604060002001805490811561227d5781471061223857600090558160005260178352604060002061271061205561ffff60135460601c16846144dc565b0490612085826120658186614715565b9486600052601b8852604060002061207e8282546144b9565b9055614715565b612094600583019182546144b9565b905581612191575b826120dc575b916060916000805160206155c783398151915293600c60018060a01b03910154169560405192835282015260006040820152a36001600e55005b600c810160018060a01b0390600080808088868654165af16120fc614722565b50156121505791606093916000805160206155c7833981519152959354168660008051602061558783398151915260405186815260408b82015280612143604082016146c0565b0390a391935091506120a2565b60405162461bcd60e51b815260048101889052601960248201527814dd589b5a5d1d195c881d1c985b9cd9995c8819985a5b1959603a1b6044820152606490fd5b60018060a01b0360008080808685601154165af16121ad614722565b50156121f3576011541684600080516020615587833981519152608060405186815260408a8201526008604082015267706c6174666f726d60c01b6060820152a361209c565b60405162461bcd60e51b815260048101879052601c60248201527f506c6174666f726d20666565207472616e73666572206661696c6564000000006044820152606490fd5b60405162461bcd60e51b815260048101859052601d60248201527f496e73756666696369656e7420636f6e74726163742062616c616e63650000006044820152606490fd5b60405162461bcd60e51b815260048101859052601060248201526f4e6f2070656e64696e672066756e647360801b6044820152606490fd5b346103df5760203660031901126103df57600435600052601b6020526020604060002054604051908152f35b346103df5760203660031901126103df576040516122fe81613c51565b60008152602081016060905260408101606090526060810160009052608081016000905260a081016000905260c081016000905260e08101600090526101008101600090526101208101600090526101408101600090526101608101600090526101808101600090526101a08101600090526101c08101600090526101e0810160009052610200810160009052610220810160009052610240016000905260043560005260176020526040600020600281015460038201546004830154600584015460068501546007860154600887015491600988015493600a89015495600160a01b60019003600b8b01541697600c8b0154996040519b6123ff8d613c51565b6004358d528c61240e82613ca9565b906020015260010161241f90613ca9565b60408d015260608c015260808b015260a08a015260c089015260e0880152610100870152610120860152610140850152610160840152610180830152600160a01b6001900381166101a08301528060a01c60ff1615156101c08301528060a81c60ff1615156101e08301528060b01c60ff1615156102008301528060b81c60ff16151561022083015260c01c60ff16151561024082015260405180916020825280516020830152602081015160408301610260905261028083016124e291613b50565b6040820151838203601f190160608501526124fd9190613b50565b9060608101516080840152608081015160a084015260a081015160c084015260c081015160e084015260e0810151610100840152610100810151610120840152610120810151610140840152610140810151610160840152610160810151610180840152600160a01b60019003610180820151166101a0840152600160a01b600190036101a0820151166101c08401526101c081015115156101e08401526101e0810151151561020084015261020081015115156102208401526102208101511515610240840152610240015115156102608301520390f35b346103df5760003660031901126103df576020601254604051908152f35b346103df5760203660031901126103df57600435600a5481101561262b5761261d602091613df2565b90546040519160031b1c8152f35b6044906040519063295f44f760e21b8252600060048301526024820152fd5b60003660031901126103df57341561269957612668346012546144b9565b6012556040513481527f1da5cc6515d0bf0b6fb40cedcd4ef3eb9a5b820440278efc9321a4491b5dd1ef60203392a2005b60405162461bcd60e51b815260206004820152600f60248201526e4d7573742073656e642066756e647360881b6044820152606490fd5b346103df5760203660031901126103df576004356126ec6147a0565b6000818152601760205260408120600c01805460ff60a81b191690557f11aa0bd3fb4d9c5622c703f91610a74140a4f88a7ebc7b4faaeaf52e3cb7aa949080a2005b346103df5761001861273f36613dbd565b906040519261274d84613c6d565b600084526110238383836140d5565b346103df5761276a36613b90565b90600052601a602052604060002080548210156103df5760209161261d91613e29565b346103df5760003660031901126103df576127a66147a0565b600d5460ff8160a01c16156127ed5760ff60a01b1916600d556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602090a1005b604051638dfc202b60e01b8152600490fd5b60206107e461280d36613b90565b90612816614807565b336000526015845261283060ff6040600020541615613e93565b612838614828565b6128637f00000000000000000000000000000000000000000000000000000000000000014614613ed8565b80600052601784526128a0604060002061288b60ff600c830154611611828260a01c1661450f565b600881015480159182156128a5575050613ff8565b614aea565b6007015410905086806107d8565b346103df5760403660031901126103df576004357f7fba17392135b4084a7d689c1f6d77139e1f1c18ee4651bf32dc35ae29ce930160206128f2613d4e565b6128fa6147a0565b600084815260048352604090205461291c906001600160a01b03161515613f50565b8360005260168252610e158160406000209060ff801983541691151516179055565b346103df576020806003193601126103df57600435600052601a6020526040600020906040519081602084549182815201936000526020600020916000905b8282106129a057610f8e8561299481890382613c88565b60405191829182613ba6565b83548652948501946001938401939091019061297d565b346103df5760203660031901126103df576129d06147a0565b7ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce760206040516004358152a1005b346103df5760403660031901126103df57612a17613b24565b60243590612a24816146dc565b821015612a575760018060a01b031660005260086020526040600020906000526020526020604060002054604051908152f35b60405163295f44f760e21b81526001600160a01b039190911660048201526024810191909152604490fd5b346103df5760603660031901126103df576004356040612aa0613b3a565b91612aa96147a0565b80600052602092601784528260002091612adb60ff600c850154612ad1828260a01c1661450f565b60b01c1615613f12565b612af360088401548015908115612b90575b50613ff8565b6000805160206155a7833981519152600f54948593612b1185614551565b600f55612b44612b3e60016007890198612b2b8a54614551565b809a55612b388986614c15565b01613ca9565b866148a5565b84600052601888528382600020556019885285826000205583600052601a8852612b71858360002061459c565b8151958652604435888701526001600160a01b031694a4604051908152f35b905060078501541087612aed565b346103df57612bac36613b90565b906000526001602052604060002060405190612bc782613c36565b546001600160a01b0380821680845260a09290921c602084015291929015612c23575b612c05612710916001600160601b03602086015116906144dc565b925160408051939091166001600160a01b0316835292046020820152f35b9150612710612c05604051612c3781613c36565b600054848116825260a01c602082015293915050612bea565b346103df5760a03660031901126103df57600435602435604435606435916084358015158091036103df5760008051602061560783398151915293608093612c966147a0565b86600052601760205260066040600020612cba60ff600c83015460b01c1615613f12565b612cc484876144b9565b612cd3600483019182546144b9565b905560058101612ce48482546144b9565b905501612cf28382546144b9565b9055604051938452602084015260408301526060820152a2005b346103df57610018612d1d36613dbd565b916140d5565b346103df5760003660031901126103df57602061ffff60135460601c16604051908152f35b346103df5760203660031901126103df57600435612d646147a0565b806000526017602052600c604060002001805460ff8160b01c16612ddb57612d9260ff8260b81c1615614091565b60ff60a01b1916600160a01b1790556040805160208082526006908201526561637469766560d01b918101919091526000805160206155e7833981519152908060608101611adf565b60405162461bcd60e51b815260206004820152601b60248201527f43616d706169676e207065726d616e656e746c7920636c6f73656400000000006044820152606490fd5b346103df57612e2e36613d8a565b90612e376147a0565b82600052602090601782526040600020612e5b60ff600c83015460b01c1615613f12565b60018091016001600160401b038511610cf757612e8285612e7c8354613bfc565b8361403b565b600085601f8111600114612f4c5780612eb192600091612f41575b508160011b916000199060031b1c19161790565b90555b84600052601a83526040600020816000905b612f03575b60405185815287907fd0ed2732da48175aaae07fd675a2a78b1700515722f6675d7ff5f0e09f22f3099080611adf818a018b8a613f93565b8154811015612f3c57908282612f34612f1d839585613e29565b9054612f2a368c8b613e5c565b9160031b1c6148a5565b019091612ec6565b612ecb565b905085013589612e9d565b50601f198616908260005286866000209260005b8887838310612f9a5750505010612f80575b50508185811b019055612eb4565b840135600019600388901b60f8161c191690558680612f72565b858a0135875590950194938401938a935001612f60565b346103df57612fbf36613b90565b612fc76147a0565b8160005260176020526040600020612fe960ff600c83015460b01c1615613f12565b81158015613076575b1561303157600801556000805160206155e7833981519152606060405160208152600b60208201526a6d617845646974696f6e7360a81b6040820152a2005b60405162461bcd60e51b815260206004820152601a60248201527f43616e6e6f74207265647563652062656c6f77206d696e7465640000000000006044820152606490fd5b506007810154821015612ff2565b346103df577fc6d3da45896ce1bca9d198309a2dbeea3c73a991748f8d88d796ffa06029de936130b336613be2565b6130be9392936147a0565b836000526017602052611adf6040600020916130e460ff600c85015460b01c1615613f12565b80600a600985019486865496550155604051938493846040919493926060820195825260208201520152565b346103df5760003660031901126103df5760206001600160601b0360135416604051908152f35b346103df5760003660031901126103df576020600a54604051908152f35b60206107e461316336613b90565b9061316c614807565b336000526015845261318660ff6040600020541615613e93565b61318e614828565b6131b97f00000000000000000000000000000000000000000000000000000000000000014614613ed8565b80600052601784526128a0604060002061288b600c82015460ff8160a01c16908161320f575b816131ff575b816131f05750613fb4565b60ff915060b81c1615886107c3565b905060ff8160b01c1615906131e5565b905060ff8160a81c1615906131df565b346103df577fac6d62cb5d30a7fff578060cd3dcf46ff2df7991a71c2d2aabca7e558f130f7861324e36613d8a565b6132599392936147a0565b60008481526004602052604090205461327c906001600160a01b03161515613f50565b61329061328a368385613e5c565b856148a5565b611adf604051928392602084526020840191613f93565b346103df5760403660031901126103df5760043561330d6132c6613d4e565b6132ce6147a0565b826000526017602052600c6040600020016132f060ff825460b01c1615613f12565b805460ff60c01b191691151560c01b60ff60c01b16919091179055565b6000805160206155e783398151915260606040516020815260166020820152751a5b5b59591a585d1954185e5bdd5d115b98589b195960521b6040820152a2005b346103df5760203660031901126103df576004356000526017602052604060002061337881613ca9565b61338460018301613ca9565b90600283015492600381015490600481015490600581015460068201546007830154600884015490600985015492600a86015494600160a01b600190039788600b8901541697600c0154996040519d8e9d8e809e61024080835282016133e991613b50565b9080820390602001526133fb91613b50565b9c6040015260608d015260808c015260a08b015260c08a015260e089015261010088015261012087015261014086015261016085015281166101808401528060a01c60ff1615156101a08401528060a81c60ff1615156101c08401528060b01c60ff1615156101e08401528060b81c60ff16151561020084015260c01c60ff1615156102208301520390f35b346103df57600361349736613be2565b9192906134a26147a0565b8360005260176020526040600020906134c560ff600c84015460b01c1615613f12565b600282015501556000805160206155e7833981519152606060405160208152600460208201526319dbd85b60e21b6040820152a2005b61350436613b90565b9061350d614807565b33600052601560205261352860ff6040600020541615613e93565b613530614828565b61355b7f00000000000000000000000000000000000000000000000000000000000000014614613ed8565b8060005260176020526040600020613590600c82015460ff8160a01c169081613779575b81613769575b8161375a5750613fb4565b8215158061374f575b156113b65760088101548015908115613737575b5015611362576135c46111ad8460098401546144dc565b6135cd8361488e565b926135db6040519485613c88565b808452601f196135ea8261488e565b013660208601376135fb81346144ef565b60005b82811061368957610f8e8686866004810161361a3482546144b9565b9055600c81015460c01c60ff161561367457506136373482615066565b60008051602061560783398151915260806040513481523460208201526000604082015260016060820152a26001600e5560405191829182613ba6565b6005016136823482546144b9565b9055613637565b600f9081549161369883614551565b90556136a76007860154614551565b8060078701556136b78333614c15565b6136c66112d560018801613ca9565b8260005260186020528660406000205560196020528060406000205586600052601a6020526136f983604060002061459c565b875182101561134c578260019360208460051b8b010152604051918252846020830152876000805160206155a783398151915260403394a4016135fe565b90506137478460078401546144b9565b1115846135ad565b506032831115613599565b60ff915060b81c1615856107c3565b905060ff8160b01c161590613585565b905060ff8160a81c16159061357f565b346103df5760403660031901126103df576137a2613b24565b6024356137ae816147cc565b3315158061385d575b80613830575b613818576001600160a01b039283169282918491167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4600090815260066020526040902080546001600160a01b0319169091179055005b60405163a9fbf51f60e01b8152336004820152602490fd5b5060018060a01b038116600052600760205260406000203360005260205260ff60406000205416156137bd565b506001600160a01b0381163314156137b7565b346103df5760203660031901126103df5760043561388d816147cc565b506000526006602052602060018060a01b0360406000205416604051908152f35b346103df5760003660031901126103df576040516002546000826138d183613bfc565b91828252602093600190856001821691826000146116fc5750506001146138ff575061168b92500383613c88565b84915060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace906000915b85831061394457505061168b93508201018561167e565b8054838901850152879450869390920191810161392d565b346103df5760403660031901126103df57613975613b24565b6024356001600160601b038116918282036103df576139926147a0565b612710808411613a2f57506001600160a01b0316918215613a16577f35804d3532228d15c4fe3fa7a4fb8100c86dc285216e9c806f5d6f2cef5528399260209282846040516139e081613c36565b848152015260a01b6001600160a01b03191617600055601380546bffffffffffffffffffffffff191682179055604051908152a1005b604051635b6cc80560e11b815260006004820152602490fd5b8360449160405191636f483d0960e01b835260048301526024820152fd5b346103df5760003660031901126103df576020601054604051908152f35b346103df5760203660031901126103df576004359063ffffffff60e01b82168092036103df57602091632483248360e11b8114908115613aad575b5015158152f35b63780e9d6360e01b811491508115613ac7575b5083613aa6565b6380ac58cd60e01b811491508115613b13575b8115613ae8575b5083613ac0565b63152a902d60e11b811491508115613b02575b5083613ae1565b6301ffc9a760e01b14905083613afb565b635b5e139f60e01b81149150613ada565b600435906001600160a01b03821682036103df57565b602435906001600160a01b03821682036103df57565b919082519283825260005b848110613b7c575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201613b5b565b60409060031901126103df576004359060243590565b602090602060408183019282815285518094520193019160005b828110613bce575050505090565b835185529381019392810192600101613bc0565b60609060031901126103df57600435906024359060443590565b90600182811c92168015613c2c575b6020831014613c1657565b634e487b7160e01b600052602260045260246000fd5b91607f1691613c0b565b604081019081106001600160401b03821117610cf757604052565b61026081019081106001600160401b03821117610cf757604052565b602081019081106001600160401b03821117610cf757604052565b90601f801991011681019081106001600160401b03821117610cf757604052565b90604051918260008254613cbc81613bfc565b90818452602094600191600181169081600014613d2c5750600114613ced575b505050613ceb92500383613c88565b565b600090815285812095935091905b818310613d14575050613ceb9350820101388080613cdc565b85548884018501529485019487945091830191613cfb565b92505050613ceb94925060ff191682840152151560051b820101388080613cdc565b6024359081151582036103df57565b9181601f840112156103df578235916001600160401b0383116103df57602083818601950101116103df57565b9060406003198301126103df5760043591602435906001600160401b0382116103df57613db991600401613d5d565b9091565b60609060031901126103df576001600160a01b039060043582811681036103df579160243590811681036103df579060443590565b600a5481101561134c57600a6000527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80190600090565b805482101561134c5760005260206000200190600090565b6001600160401b038111610cf757601f01601f191660200190565b929192613e6882613e41565b91613e766040519384613c88565b8294818452818301116103df578281602093846000960137010152565b15613e9a57565b60405162461bcd60e51b81526020600482015260166024820152751059191c995cdcc81a5cc8189b1858dadb1a5cdd195960521b6044820152606490fd5b15613edf57565b60405162461bcd60e51b815260206004820152600b60248201526a2bb937b7339031b430b4b760a91b6044820152606490fd5b15613f1957565b60405162461bcd60e51b815260206004820152600f60248201526e10d85b5c185a59db8818db1bdcd959608a1b6044820152606490fd5b15613f5757565b60405162461bcd60e51b8152602060048201526014602482015273151bdad95b88191bd95cc81b9bdd08195e1a5cdd60621b6044820152606490fd5b908060209392818452848401376000828201840152601f01601f1916010190565b15613fbb57565b60405162461bcd60e51b815260206004820152601560248201527443616d706169676e206e6f74206d696e7461626c6560581b6044820152606490fd5b15613fff57565b60405162461bcd60e51b815260206004820152601460248201527313585e0819591a5d1a5bdb9cc81c995858da195960621b6044820152606490fd5b90601f811161404957505050565b6000916000526020600020906020601f850160051c83019410614087575b601f0160051c01915b82811061407c57505050565b818155600101614070565b9092508290614067565b1561409857565b60405162461bcd60e51b815260206004820152601560248201527410d85b5c185a59db881dd85cc81c99599d5b991959605a1b6044820152606490fd5b6001600160a01b0382811693919084156144a05760009183835260049560209387855260409484868320541680151580614498575b61436a575b5086825288815284868320541697331515806142d8575b50881580156142a5575b84845260058352878420805460010190558884528a835287842080546001600160a01b0319168617905588858b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8780a41561422957600a54888452600b83528784205561419d88614560565b8389036141d8575b5050505016908184036141b9575050505050565b516364283d7b60e01b8152938401526024830152604482015260649150fd5b6141e1906146dc565b6000198101939084116142165782916009918894526008815283832085845281528884842055888352522055388080806141a5565b634e487b7160e01b835260118a52602483fd5b88841461419d57614239896146dc565b888452600983528784205481810361426e575b508884528388812055898452600883528784209084528252828781205561419d565b8a8552600884528885208286528452888520548b8652600885528986208287528552808a872055855260098452888520553861424c565b600089815260066020526040902080546001600160a01b0319169055898452600583528784208054600019019055614130565b80614329575b156142e95738614126565b878a888b61430657916024925191637e27328960e01b8352820152fd5b5163177e802f60e01b815233918101918252602082019290925281906040010390fd5b50338914801561434e575b806142de57508783526006825233868885205416146142de565b5088835260078252868320338452825260ff8784205416614334565b6014825260ff8784205416614463578783526016825260ff878420541661442b5782526015815260ff86832054166143f1578282526015815260ff86832054166143b4573861410f565b8860649187519162461bcd60e51b83528201526018602482015277149958da5c1a595b9d081a5cc8189b1858dadb1a5cdd195960421b6044820152fd5b8860649187519162461bcd60e51b8352820152601560248201527414d95b99195c881a5cc8189b1858dadb1a5cdd1959605a1b6044820152fd5b865162461bcd60e51b8152808b018390526012602482015271151bdad95b881a5cc81cdbdd5b189bdd5b9960721b6044820152606490fd5b865162461bcd60e51b8152808b01839052600f60248201526e2a37b5b2b71034b990333937bd32b760891b6044820152606490fd5b50600161410a565b604051633250574960e11b815260006004820152602490fd5b919082018092116144c657565b634e487b7160e01b600052601160045260246000fd5b818102929181159184041417156144c657565b81156144f9570490565b634e487b7160e01b600052601260045260246000fd5b1561451657565b60405162461bcd60e51b815260206004820152601360248201527243616d706169676e206e6f742061637469766560681b6044820152606490fd5b60001981146144c65760010190565b600a5490600160401b821015610cf757614583826001613ceb9401600a55613df2565b90919082549060031b91821b91600019901b1916179055565b90815491600160401b831015610cf75782614583916001613ceb95018155613e29565b156145c657565b60405162461bcd60e51b815260206004820152601260248201527110d85b5c185a59db881a5cc81c185d5cd95960721b6044820152606490fd5b1561460757565b60405162461bcd60e51b815260206004820152601160248201527010d85b5c185a59db881c99599d5b991959607a1b6044820152606490fd5b1561464757565b60405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081b9bdb9c1c9bd99a5d607a1b6044820152606490fd5b1561468757565b60405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21039bab136b4ba3a32b960791b6044820152606490fd5b600981526839bab136b4ba3a32b960b91b602082015260400190565b6001600160a01b031680156146fc57600052600560205260406000205490565b6040516322718ad960e21b815260006004820152602490fd5b919082039182116144c657565b3d1561474d573d9061473382613e41565b916147416040519384613c88565b82523d6000602084013e565b606090565b1561475957565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b919081101561134c5760051b0190565b600d546001600160a01b031633036147b457565b60405163118cdaa760e01b8152336004820152602490fd5b6000818152600460205260409020546001600160a01b03169081156147ef575090565b60249060405190637e27328960e01b82526004820152fd5b60ff600d5460a01c1661481657565b60405163d93c066560e01b8152600490fd5b6002600e5414614839576002600e55565b604051633ee5aeb560e01b8152600490fd5b1561485257565b60405162461bcd60e51b8152602060048201526014602482015273125b9cdd59999a58da595b9d081c185e5b595b9d60621b6044820152606490fd5b6001600160401b038111610cf75760051b60200190565b919091600090808252602091600c835260408120908551956001600160401b0387116149c0576148df876148d98554613bfc565b8561403b565b8491601f881160011461493c57966149309281927ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7989992610c455750508160011b916000199060031b1c19161790565b90555b604051908152a1565b9190601f198816848452868420935b8181106149a957509160019391897ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce7999a9410614990575b505050811b019055614933565b015160001960f88460031b161c19169055388080614983565b92938760018192878601518155019501930161494b565b634e487b7160e01b82526041600452602482fd5b600090808252600080516020615607833981519152608060206017815260409485812095614a08600988015434101561484b565b600f5496614a1588614551565b600f556007810190614a278254614551565b809255614a348933614c15565b614a49614a4360018301613ca9565b8a6148a5565b888452601885528783852055601985528183852055878452601a8552614a718984862061459c565b60048101614a803482546144b9565b9055600c81015460c01c60ff1615614ad55750614a9d3488615066565b8151908152348482015287876000805160206155a7833981519152843394a4805192348452349084015282015260016060820152a290565b600501614ae33482546144b9565b9055614a9d565b600080516020615607833981519152608060009383855260209060178252604080872096614b1f6111ad8460098b01546144b9565b600f5497614b2c89614551565b600f556007810190614b3e8254614551565b809255614b8c8a85614b508834614715565b95614b5b8333614c15565b614b6a6112d560018701613ca9565b82815260188a528c8282205560198a5285828220558c8152601a8a522061459c565b60048101614b9b3482546144b9565b905560068101614bac8682546144b9565b9055600c81015460c01c60ff1615614c005750614bca84838a615259565b8251908152348582015288886000805160206155a7833981519152853394a481519334855284015282015260016060820152a290565b600501614c0e8382546144b9565b9055614bca565b6040805190614c2382613c6d565b60008083526001600160a01b039484861693909190841561504e5782825260049560209787895280868520541680151580615046575b614f16575b5084845287895285842054168681159182159283614ee3575b82875260058c52888720805460010190558787528a8c5288872080546001600160a01b031916841790558783837fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8a80a415614e6557600a54878752600b8c5288872055614ce487614560565b03614e19575b614e02573b614cfd575b50505050505050565b86614d3a918596979899955180938192630a85bd0160e11b97888452338d8501528760248501526044840152608060648401526084830190613b50565b0381858a5af190829082614db7575b5050614d7f57505050614d5a614722565b80519485614d7957505051633250574960e11b81529182015260249150fd5b85925001fd5b9195506001600160e01b031990911603614da25750505038808080808080614cf4565b51633250574960e11b81529182015260249150fd5b909192508881813d8311614dfb575b614dd08183613c88565b81010312614df75751906001600160e01b031982168203614df45750903880614d49565b80fd5b5080fd5b503d614dc6565b84516339e3563760e11b8152808801849052602490fd5b614e22826146dc565b6000198101908111614e525787855260088a528685208186528a52858786205585855260098a5286852055614cea565b634e487b7160e01b855260118952602485fd5b808214614ce457614e75816146dc565b87875260098c5288872054818103614eaa575b50878752868981205581875260088c528887209087528b528588812055614ce4565b82885260088d528988208289528d528c60088b8a205491858b52528d8b8a2090838b5252808b8a2055885260098d528988205538614e88565b600088815260066020526040902080546001600160a01b031916905581875260058c528887208054600019019055614c77565b60148a5260ff87862054166150115785855260168a5260ff8786205416614fd95784526015895260ff8685205416614f9e578684526015895260ff8685205416614f605738614c5e565b855162461bcd60e51b81528089018a90526018602482015277149958da5c1a595b9d081a5cc8189b1858dadb1a5cdd195960421b6044820152606490fd5b855162461bcd60e51b81528089018a9052601560248201527414d95b99195c881a5cc8189b1858dadb1a5cdd1959605a1b6044820152606490fd5b865162461bcd60e51b8152808a018b90526012602482015271151bdad95b881a5cc81cdbdd5b189bdd5b9960721b6044820152606490fd5b865162461bcd60e51b8152808a018b9052600f60248201526e2a37b5b2b71034b990333937bd32b760891b6044820152606490fd5b506001614c59565b8351633250574960e11b815260048101839052602490fd5b60009181835260209260178452604080822061271061508e61ffff60135460601c16866144dc565b04906150b48261509e8188614715565b96888752601b8a5285872061207e8282546144b9565b6150c3600583019182546144b9565b9055816151b7575b84615103575b600c01548251948552958401528201526001600160a01b03909216916000805160206155c783398151915290606090a3565b600c810160018060a01b0390858080808a868654165af1615122614722565b5015615177579160609593916000805160206155c78339815191529795935416886000805160206155878339815191528551888152868d820152806151688882016146c0565b0390a3919395509193506150d1565b845162461bcd60e51b8152600481018a9052601960248201527814dd589b5a5d1d195c881d1c985b9cd9995c8819985a5b1959603a1b6044820152606490fd5b60018060a01b03848080808685601154165af16151d2614722565b501561521557601154168660008051602061558783398151915260808651868152878c82015260088882015267706c6174666f726d60c01b6060820152a36150cb565b835162461bcd60e51b815260048101899052601c60248201527f506c6174666f726d20666565207472616e73666572206661696c6564000000006044820152606490fd5b90600090828252602093601785526040948584209061271061528461ffff60135460601c16866144dc565b04946152b886615298866111a8838a614715565b966152a387826144b9565b8a8552601b865261207e8c86209182546144b9565b6152c7600585019182546144b9565b9055856153cb575b84615317575b5050600c01549451918252602082019290925260408101919091526001600160a01b03909216916000805160206155c78339815191529080606081015b0390a3565b600c830160018060a01b039180808089868654165af1615335614722565b501561538b57918760008051602061558783398151915261531295936000805160206155c7833981519152999897955416928b8051918983528201528061537d8d82016146c0565b0390a39181939495506152d5565b885162461bcd60e51b815260048101849052601960248201527814dd589b5a5d1d195c881d1c985b9cd9995c8819985a5b1959603a1b6044820152606490fd5b60018060a01b03818080808a85601154165af16153e6614722565b501561542957601154168760008051602061558783398151915260808b518a81528c8782015260088d82015267706c6174666f726d60c01b6060820152a36152cf565b885162461bcd60e51b815260048101849052601c60248201527f506c6174666f726d20666565207472616e73666572206661696c6564000000006044820152606490fd5b9190803b61547c575b50505050565b6154be60018060a01b0380921694604051938493630a85bd0160e11b968786523360048701521660248501526044840152608060648401526084830190613b50565b03906020816000938185885af19082908261553d575b505061550c57826154e3614722565b805191908261550557604051633250574960e11b815260048101839052602490fd5b9050602001fd5b6001600160e01b03191603615525575038808080615476565b60249060405190633250574960e11b82526004820152fd5b909192506020813d60201161557e575b8161555a60209383613c88565b81010312614df75751906001600160e01b031982168203614df457509038806154d4565b3d915061554d56fec5116d0bff033daa6db9b6cf401237ef4f85a0a6cbe32bfb53d189b3e6c4bad644a73422883fd5aac8dde6ef3688c62f25a4fb22e7a395bafb411ec4803ab1bde6bf69167ad8e0c635fcc1b7beeafcc578b34e3c24b18668a3a118279345414a7a9a4f151cc0b6349bd7062416b8f68d1d73c3f457efc221520eb5547595d2d8f1a038a86c47446d2a26b7852348eee74e6d63d5a71792df01e40c2e6d0e1ca2a264697066735822122031d96c1bbb8c35253141d0decb6a04fc7fcf7086be1bcdf45a7368afb129068c64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004e8e445a9957cd251059cd52a00777a25f8cd53e0000000000000000000000000000000000000000000000000000000000000064
-----Decoded View---------------
Arg [0] : _platformTreasury (address): 0x4E8E445A9957cD251059cd52A00777A25f8cD53e
Arg [1] : _platformFeeBps (uint16): 100
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000004e8e445a9957cd251059cd52a00777a25f8cd53e
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000064
Loading...
Loading
Loading...
Loading
Net Worth in USD
$652.79
Net Worth in ETH
0.349673
Token Allocations
ETH
100.00%
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $1,866.85 | 0.3497 | $652.79 |
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.