Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 67 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw | 15167941 | 1352 days ago | IN | 0 ETH | 0.00405249 | ||||
| Withdraw | 15167934 | 1352 days ago | IN | 0 ETH | 0.00313707 | ||||
| Purchase | 14978187 | 1384 days ago | IN | 0.5 ETH | 0.00071678 | ||||
| Set Transfer Loc... | 14976089 | 1384 days ago | IN | 0 ETH | 0.00083302 | ||||
| Premint | 14976077 | 1384 days ago | IN | 0 ETH | 0.77333875 | ||||
| Withdraw | 14976073 | 1384 days ago | IN | 0 ETH | 0.00290303 | ||||
| Withdraw | 14976066 | 1384 days ago | IN | 0 ETH | 0.00378943 | ||||
| Deactivate | 14976057 | 1384 days ago | IN | 0 ETH | 0.00149693 | ||||
| Purchase | 14975184 | 1384 days ago | IN | 0.5 ETH | 0.00620915 | ||||
| Purchase | 14975029 | 1384 days ago | IN | 0.5 ETH | 0.0065862 | ||||
| Purchase | 14975010 | 1384 days ago | IN | 0.5 ETH | 0.00608716 | ||||
| Purchase | 14974985 | 1384 days ago | IN | 0.5 ETH | 0.00759434 | ||||
| Purchase | 14974961 | 1384 days ago | IN | 0.5 ETH | 0.00791758 | ||||
| Purchase | 14974905 | 1384 days ago | IN | 0.5 ETH | 0.00587583 | ||||
| Purchase | 14974897 | 1384 days ago | IN | 0.5 ETH | 0.00764682 | ||||
| Purchase | 14974816 | 1384 days ago | IN | 0.5 ETH | 0.008186 | ||||
| Purchase | 14974801 | 1384 days ago | IN | 0.5 ETH | 0.01092325 | ||||
| Purchase | 14974740 | 1384 days ago | IN | 0.5 ETH | 0.01342249 | ||||
| Purchase | 14974691 | 1384 days ago | IN | 0.5 ETH | 0.01006053 | ||||
| Purchase | 14974650 | 1384 days ago | IN | 0.5 ETH | 0.01252355 | ||||
| Purchase | 14974591 | 1384 days ago | IN | 0.5 ETH | 0.00931966 | ||||
| Purchase | 14974458 | 1384 days ago | IN | 0.5 ETH | 0.01273746 | ||||
| Purchase | 14974434 | 1384 days ago | IN | 1 ETH | 0.01138954 | ||||
| Purchase | 14974358 | 1384 days ago | IN | 0.5 ETH | 0.01005241 | ||||
| Purchase | 14974325 | 1384 days ago | IN | 1 ETH | 0.01314716 |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Facets
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
/// @artist: Justin Maller
/// @title: Facets
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// //
// //
// //
// &&& &&&# //
// .&&&&&&&& &&&&&&&&% //
// ,&&&&&&&&&&&&& &&&&&&&&&&&&&# //
// .&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&% //
// ,&&&&&&&&&&&&( ,&&&&&&&&&&&&& //
// *&&/ ,&&% //
// %&&&&&&& &&&&&&&&, //
// .%&&&&&&&&&&&&&&&&&&&&% &% &&&&&&&&&&&&&&&&&&&&&. //
// #&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&%, //
// .&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&( &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //
// (&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //
// %&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&. ,&&&&&&&&&&&&&&&&&&&&&&&&&&&&& //
// &&&&&&&&&&&&&&&&&&&&&&&&&&& #&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&& //
// &&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&& /&&&&&&&&&&&&&&&&&&&&&&&& //
// , &&&&&&&&&&&&&&&&&&&&&& ,&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&& & //
// & &&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&& %&&&&&&&&&&&&&&&&&&& %& //
// && &&&&&&&&&&&&&&&&&, &&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&& /&# //
// &&& &&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&& .&&, //
// &&&& &&&&&&&&&&&&( &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&# &&&&&&&&&&&&, &&& //
// &&&&# &&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&( &&&& //
// &&&&&/ &&&&&&&% &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&. &&&&&&&% &&&&& //
// &&&&&&. &&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&& &&&&&& //
// &&&&&&& .&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&& &&&&&&& //
// ,&&&&&&& / *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& & &&&&&&&& //
// &&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&& //
// &&&&&&&&& &&&&&&&&&& //
// &&&&&&% &&&&&&, //
// &&& * &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& & &&& //
// &&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&& //
// ,&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&& //
// ,&&&&&&&&&&&&&& %&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&% //
// &&&&&&&&&&&&, /&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&* //
// &&&&&&&&&&/ .&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&& //
// %&&&&&&&# &&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&& //
// *&&&&&& &&&&&&&&&&&&&&&&&&&% &&&&&& //
// &&&& &&&&&&&&&&&&&&&( ,&&&# //
// && &&&&&&&&&&&* (&. //
// &&&&&&&. //
// &&& //
// //
// //
// //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@manifoldxyz/libraries-solidity/contracts/access/AdminControl.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "@manifoldxyz/creator-core-solidity/contracts/extensions/ERC721/IERC721CreatorExtensionApproveTransfer.sol";
import "./ERC721BurnRedeem.sol";
import "./ERC721CreatorCollectionBase.sol";
import "./DutchAuction.sol";
contract Facets is ERC721CreatorCollectionBase, IERC721CreatorExtensionApproveTransfer, DutchAuction, ReentrancyGuard, AdminControl {
event SenderRefunded(
uint256 received,
uint256 returned
);
constructor(address creatorAddress, address signingAddress) {
_initialize(
creatorAddress,
365, // purchaseMax_
3650000000000000000, // purchasePrice_
365, // purchaseLimit_
365, // transactionLimit_
0, // presalePurchasePrice_
0, // presalePurchaseLimit_
signingAddress,
false // useDynamicPresalePurchaseLimit_
);
minimumPrice = 500000000000000000;
priceDropInterval = 300;
priceDropMagnitude = 50000000000000000;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721CreatorCollectionBase, IERC165, AdminControl) returns (bool) {
return interfaceId == type(IERC721CreatorExtensionApproveTransfer).interfaceId || ERC721CreatorCollectionBase.supportsInterface(interfaceId) || AdminControl.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Collection-withdraw}.
*/
function withdraw(address payable recipient, uint256 amount) external override adminRequired {
_withdraw(recipient, amount);
}
/**
* @dev See {IERC721Collection-premint}.
*/
function premint(uint16 amount) external override adminRequired {
_premint(amount, owner());
}
/**
* @dev See {IERC721Collection-premint}.
*/
function premint(address[] calldata addresses) external override adminRequired {
_premint(addresses);
}
/**
* @dev See {ERC721CreatorCollectionBase-purchase}.
*/
function purchase(uint16 amount, bytes32 message, bytes calldata signature, bytes32 nonce) public override payable nonReentrant {
ERC721CreatorCollectionBase.purchase(amount, message, signature, nonce);
uint256 totalPrice = amount * getCurrentPrice(presalePurchasePrice, purchasePrice);
if (msg.value > totalPrice) {
Address.sendValue(payable(msg.sender), msg.value - totalPrice);
emit SenderRefunded(msg.value, msg.value - totalPrice);
}
}
/**
* Validate price
*/
function _validatePrice(uint16 amount) internal override {
require(msg.value >= amount * getCurrentPrice(presalePurchasePrice, purchasePrice), "Invalid purchase amount sent");
}
/**
* @dev See {IERC721Collection-activate}.
*/
function activate(uint256 startTime_, uint256 duration, uint256 presaleInterval_, uint256 claimStartTime_, uint256 claimEndTime_) external override adminRequired {
_activate(startTime_, duration, presaleInterval_, claimStartTime_, claimEndTime_);
}
/**
* @dev See {IERC721Collection-deactivate}.
*/
function deactivate() external override adminRequired {
_deactivate();
}
/**
* @dev See {IERC721Collection-setTokenURIPrefix}.
*/
function setTokenURIPrefix(string calldata prefix) external override adminRequired {
_setTokenURIPrefix(prefix);
}
function setTransferLocked(bool locked) external override adminRequired {
_setTransferLocked(locked);
}
/**
* @dev See {IERC721CreatorExtensionApproveTransfer-setApproveTransfer}
*/
function setApproveTransfer(address creator, bool enabled) external override adminRequired {
require(ERC165Checker.supportsInterface(creator, type(IERC721CreatorCore).interfaceId), "Creator must implement IERC721CreatorCore");
IERC721CreatorCore(creator).setApproveTransferExtension(enabled);
}
/**
* @dev See {IERC721CreatorExtensionApproveTransfer-approveTransfer}.
*/
function approveTransfer(address from, address, uint256) external view override returns (bool) {
return _validateTokenTransferability(from);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "./CollectionBase.sol";
/**
* Faux dutch auction library - purchase price descends to 0 over the duration of the sale at a set rate.
*/
abstract contract DutchAuction is CollectionBase {
struct DutchAuctionData {
uint256 minimumPrice;
uint256 priceDropInterval;
uint256 priceDropMagnitude;
}
// If set, price during sale will not drop below this threshold.
uint256 public minimumPrice;
uint256 public priceDropInterval;
uint256 public priceDropMagnitude;
/**
* @dev returns pricing data used to compute current price
*/
function pricingData() external view returns (DutchAuctionData memory) {
return DutchAuctionData(minimumPrice, priceDropInterval, priceDropMagnitude);
}
/**
* @dev Get current price for the token sale based on dutch auction pricing mechanics
* @param presalePurchasePrice The price of the token during the presale interval.
* @param startPrice The starting price of the token during the public sale.
*/
function getCurrentPrice(uint256 presalePurchasePrice, uint256 startPrice) internal view returns (uint256) {
if (_isPresale()) {
return presalePurchasePrice;
}
uint256 timeElapsed = block.timestamp - publicSaleStartTime();
uint256 discount = (timeElapsed / priceDropInterval) * priceDropMagnitude;
if (discount > startPrice) {
return minimumPrice;
}
uint256 currentPrice = startPrice - discount;
return currentPrice > minimumPrice ? currentPrice : minimumPrice;
}
function publicSaleStartTime() public view returns (uint256) {
return startTime + presaleInterval;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@manifoldxyz/creator-core-solidity/contracts/core/IERC721CreatorCore.sol";
import "@manifoldxyz/creator-core-solidity/contracts/extensions/CreatorExtension.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "./IERC721Collection.sol";
import "./CollectionBase.sol";
/**
* ERC721 Creator Collection Drop Contract (Base)
*/
abstract contract ERC721CreatorCollectionBase is CollectionBase, CreatorExtension, IERC721Collection {
using Strings for uint256;
// Immutable variables that should only be set by the constructor or initializer
address internal _creator;
uint16 public transactionLimit;
uint16 public purchaseMax;
uint256 public purchasePrice;
uint16 public purchaseLimit;
uint256 public presalePurchasePrice;
uint16 public presalePurchaseLimit;
bool public useDynamicPresalePurchaseLimit;
// Minted token information
uint16 public purchaseCount;
mapping(address => uint16) internal _addressMintCount;
// Transfer lock
bool public transferLocked;
function _initialize(address creator, uint16 purchaseMax_, uint256 purchasePrice_, uint16 purchaseLimit_, uint16 transactionLimit_, uint256 presalePurchasePrice_, uint16 presalePurchaseLimit_, address signingAddress, bool useDynamicPresalePurchaseLimit_) internal {
require(_creator == address(0) && _signingAddress == address(0), "Already initialized");
_creator = creator;
purchaseMax = purchaseMax_;
purchasePrice = purchasePrice_;
purchaseLimit = purchaseLimit_;
transactionLimit = transactionLimit_;
presalePurchasePrice = presalePurchasePrice_;
presalePurchaseLimit = presalePurchaseLimit_;
_signingAddress = signingAddress;
useDynamicPresalePurchaseLimit = useDynamicPresalePurchaseLimit_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(CreatorExtension, IERC165) returns (bool) {
return interfaceId == type(IERC721Collection).interfaceId || CreatorExtension.supportsInterface(interfaceId);
}
/**
* Premint tokens to the owner. Sale must not be active.
*/
function _premint(uint16 amount, address owner) internal virtual {
require(!active, "Already active");
_mint(owner, amount);
}
/**
* Premint tokens to the list of addresses. Sale must not be active.
*/
function _premint(address[] calldata addresses) internal virtual {
require(!active, "Already active");
for (uint i = 0; i < addresses.length; ) {
_mint(addresses[i], 1);
unchecked {
i++;
}
}
}
/**
* @dev override if you want to perform different mint functionality
*/
function _mint(address to, uint16 amount) internal virtual {
if (amount == 1) {
purchaseCount++;
// Mint token
uint256 tokenId = IERC721CreatorCore(_creator).mintExtension(to);
emit Unveil(purchaseCount, _creator, tokenId);
} else {
uint256 tokenStart = purchaseCount+1;
purchaseCount += amount;
// Mint token
uint256[] memory tokenIds = IERC721CreatorCore(_creator).mintExtensionBatch(to, amount);
for (uint i = 0; i < tokenIds.length; ) {
emit Unveil(tokenStart+i, _creator, tokenIds[i]);
unchecked {
i++;
}
}
}
}
/**
* Set the tokenURI prefix
*/
function _setTokenURIPrefix(string calldata prefix) internal virtual {
IERC721CreatorCore(_creator).setBaseTokenURIExtension(prefix);
}
/**
* Validate price (override for custom pricing mechanics)
*/
function _validatePrice(uint16 amount) internal virtual {
require(msg.value == amount*purchasePrice, "Invalid purchase amount sent");
}
/**
* Validate price (override for custom pricing mechanics)
*/
function _validatePresalePrice(uint16 amount) internal virtual {
require(msg.value == amount*presalePurchasePrice, "Invalid purchase amount sent");
}
/**
* Returns whether or not token transfers are enabled.
*/
function _validateTokenTransferability(address from) internal view returns(bool) {
return from == address(0) || !transferLocked;
}
/**
* Set whether or not token transfers are locked
*/
function _setTransferLocked(bool locked) internal {
transferLocked = locked;
}
/**
* @dev See {IERC721Collection-claim}.
*/
function claim(uint16 amount, bytes32 message, bytes calldata signature, bytes32 nonce) external virtual override {
_validateClaimRestrictions();
_validateClaimRequest(message, signature, nonce, amount);
_mint(msg.sender, amount);
_addressMintCount[msg.sender] += amount;
}
/**
* @dev See {IERC721Collection-purchase}.
*/
function purchase(uint16 amount, bytes32 message, bytes calldata signature, bytes32 nonce) public payable virtual override {
_validatePurchaseRestrictions();
bool isPresale = _isPresale();
// Check purchase amounts
require(amount <= purchaseRemaining() && ((isPresale && useDynamicPresalePurchaseLimit) || transactionLimit == 0 || amount <= transactionLimit), "Too many requested");
if (isPresale) {
if (!useDynamicPresalePurchaseLimit) {
// Make sure we are not over presalePurchaseLimit
if (presalePurchaseLimit != 0) {
uint16 mintCount = _addressMintCount[msg.sender];
require(presalePurchaseLimit > mintCount && amount <= (presalePurchaseLimit-mintCount), "Too many requested");
}
// Make sure we are not over purchaseLimit
if (purchaseLimit != 0) {
uint16 mintCount = _addressMintCount[msg.sender];
require(purchaseLimit > mintCount && amount <= (purchaseLimit-mintCount), "Too many requested");
}
}
_validatePresalePrice(amount);
// Only track mint count if needed
if (!useDynamicPresalePurchaseLimit && (presalePurchaseLimit != 0 || purchaseLimit != 0)) {
_addressMintCount[msg.sender] += amount;
}
} else {
// Make sure we are not over purchaseLimit
if (purchaseLimit != 0) {
uint16 mintCount = _addressMintCount[msg.sender];
require(purchaseLimit > mintCount && amount <= (purchaseLimit-mintCount), "Too many requested");
}
_validatePrice(amount);
if (purchaseLimit != 0) {
_addressMintCount[msg.sender] += amount;
}
}
if (isPresale && useDynamicPresalePurchaseLimit) {
_validatePurchaseRequestWithAmount(message, signature, nonce, amount);
} else {
_validatePurchaseRequest(message, signature, nonce);
}
_mint(msg.sender, amount);
}
/**
* @dev See {IERC721Collection-state}
*/
function state() external override view returns(CollectionState memory) {
return CollectionState(transactionLimit, purchaseMax, purchaseRemaining(), purchasePrice, purchaseLimit, presalePurchasePrice, presalePurchaseLimit, _addressMintCount[msg.sender], active, startTime, endTime, presaleInterval, claimStartTime, claimEndTime, useDynamicPresalePurchaseLimit);
}
/**
* @dev See {IERC721Collection-purchaseRemaining}.
*/
function purchaseRemaining() public view virtual override returns(uint16) {
return purchaseMax-purchaseCount;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@manifoldxyz/creator-core-solidity/contracts/core/IERC721CreatorCore.sol";
import "./ERC721RedeemBase.sol";
import "./IERC721BurnRedeem.sol";
/**
* @dev Burn NFT's to receive another lazy minted NFT
*/
contract ERC721BurnRedeem is ReentrancyGuard, ERC721RedeemBase, IERC721BurnRedeem, IERC1155Receiver, IERC721Receiver {
using EnumerableSet for EnumerableSet.UintSet;
mapping (address => mapping (uint256 => address)) private _recoverableERC721;
constructor(address creator, uint16 redemptionRate, uint16 redemptionMax) ERC721RedeemBase(creator, redemptionRate, redemptionMax) {}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721RedeemBase, IERC165) returns (bool) {
return interfaceId == type(IERC721BurnRedeem).interfaceId || interfaceId == type(IERC1155Receiver).interfaceId
|| interfaceId == type(IERC721Receiver).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721BurnRedeem-setERC721Recoverable}
*/
function setERC721Recoverable(address contract_, uint256 tokenId, address recoverer) external virtual override adminRequired {
require(ERC165Checker.supportsInterface(contract_, type(IERC721).interfaceId), "BurnRedeem: Must implement IERC721");
_recoverableERC721[contract_][tokenId] = recoverer;
}
/**
* @dev See {IERC721BurnRedeem-recoverERC721}
*/
function recoverERC721(address contract_, uint256 tokenId) external virtual override {
address recoverer = _recoverableERC721[contract_][tokenId];
require(recoverer == msg.sender, "BurnRedeem: Permission denied");
IERC721(contract_).safeTransferFrom(address(this), msg.sender, tokenId);
}
/**
* @dev See {IERC721BurnRedeem-redeemERC721}
*/
function redeemERC721(address[] calldata contracts, uint256[] calldata tokenIds) external virtual override nonReentrant {
require(contracts.length == tokenIds.length, "BurnRedeem: Invalid parameters");
require(contracts.length == _redemptionRate, "BurnRedeem: Incorrect number of NFTs being redeemed");
// Attempt Burn
for (uint i = 0; i < contracts.length; i++) {
// Check that we can burn
require(redeemable(contracts[i], tokenIds[i]), "BurnRedeem: Invalid NFT");
try IERC721(contracts[i]).ownerOf(tokenIds[i]) returns (address ownerOfAddress) {
require(ownerOfAddress == msg.sender, "BurnRedeem: Caller must own NFTs");
} catch (bytes memory) {
revert("BurnRedeem: Bad token contract");
}
if (!IERC721(contracts[i]).isApprovedForAll(msg.sender, address(this))) {
try IERC721(contracts[i]).getApproved(tokenIds[i]) returns (address approvedAddress) {
require(approvedAddress == address(this), "BurnRedeem: Contract must be given approval to burn NFT");
} catch (bytes memory) {
revert("BurnRedeem: Bad token contract");
}
}
// Then burn
try IERC721(contracts[i]).transferFrom(msg.sender, address(0xdEaD), tokenIds[i]) {
} catch (bytes memory) {
revert("BurnRedeem: Burn failure");
}
}
// Mint reward
_mintRedemption(msg.sender);
}
/**
* @dev See {IERC721Receiver-onERC721Received}.
*/
function onERC721Received(address, address from, uint256 tokenId, bytes calldata data) external override nonReentrant returns (bytes4) {
require(redeemable(msg.sender, tokenId), "BurnRedeem: Invalid NFT");
require(_redemptionRate == 1, "BurnRedeem: Can only allow direct receiving of redemptions of 1 NFT");
// Burn it
try IERC721(msg.sender).safeTransferFrom(address(this), address(0xdEaD), tokenId, data) {
} catch (bytes memory) {
revert("BurnRedeem: Burn failure");
}
// Mint reward
_mintRedemption(from);
return this.onERC721Received.selector;
}
/**
* @dev See {IERC1155Receiver-onERC1155Received}.
*/
function onERC1155Received(
address,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external override nonReentrant returns(bytes4) {
require(redeemable(msg.sender, id), "BurnRedeem: Invalid NFT");
require(value == _redemptionRate, "BurnRedeem: Incorrect number of NFTs being redeemed");
// Burn it
try IERC1155(msg.sender).safeTransferFrom(address(this), address(0xdEaD), id, value, data) {
} catch (bytes memory) {
revert("BurnRedeem: Burn failure");
}
// Mint reward
_mintRedemption(from);
return this.onERC1155Received.selector;
}
/**
* @dev See {IERC1155Receiver-onERC1155BatchReceived}.
*/
function onERC1155BatchReceived(
address,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external override nonReentrant returns(bytes4) {
require(ids.length == values.length, "BurnRedeem: Invalid input");
uint256 totalValue = 0;
for (uint i=0; i<ids.length; i++) {
require(redeemable(msg.sender, ids[i]), "BurnRedeem: Invalid NFT");
totalValue += values[i];
}
require(totalValue == _redemptionRate, "BurnRedeem: Incorrect number of NFTs being redeemed");
// Burn it
try IERC1155(msg.sender).safeBatchTransferFrom(address(this), address(0xdEaD), ids, values, data) {
} catch (bytes memory) {
revert("BurnRedeem: Burn failure");
}
// Mint reward
_mintRedemption(from);
return this.onERC1155BatchReceived.selector;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* Implement this if you want your extension to approve a transfer
*/
interface IERC721CreatorExtensionApproveTransfer is IERC165 {
/**
* @dev Set whether or not the creator will check the extension for approval of token transfer
*/
function setApproveTransfer(address creator, bool enabled) external;
/**
* @dev Called by creator contract to approve a transfer
*/
function approveTransfer(address from, address to, uint256 tokenId) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Library used to query support of an interface declared via {IERC165}.
*
* Note that these functions return the actual result of the query: they do not
* `revert` if an interface is not supported. It is up to the caller to decide
* what to do in these cases.
*/
library ERC165Checker {
// As per the EIP-165 spec, no interface should ever match 0xffffffff
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
/**
* @dev Returns true if `account` supports the {IERC165} interface,
*/
function supportsERC165(address account) internal view returns (bool) {
// Any contract that implements ERC165 must explicitly indicate support of
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
return
_supportsERC165Interface(account, type(IERC165).interfaceId) &&
!_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
}
/**
* @dev Returns true if `account` supports the interface defined by
* `interfaceId`. Support for {IERC165} itself is queried automatically.
*
* See {IERC165-supportsInterface}.
*/
function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
// query support of both ERC165 as per the spec and support of _interfaceId
return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);
}
/**
* @dev Returns a boolean array where each value corresponds to the
* interfaces passed in and whether they're supported or not. This allows
* you to batch check interfaces for a contract where your expectation
* is that some interfaces may not be supported.
*
* See {IERC165-supportsInterface}.
*
* _Available since v3.4._
*/
function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)
internal
view
returns (bool[] memory)
{
// an array of booleans corresponding to interfaceIds and whether they're supported or not
bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);
// query support of ERC165 itself
if (supportsERC165(account)) {
// query support of each interface in interfaceIds
for (uint256 i = 0; i < interfaceIds.length; i++) {
interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);
}
}
return interfaceIdsSupported;
}
/**
* @dev Returns true if `account` supports all the interfaces defined in
* `interfaceIds`. Support for {IERC165} itself is queried automatically.
*
* Batch-querying can lead to gas savings by skipping repeated checks for
* {IERC165} support.
*
* See {IERC165-supportsInterface}.
*/
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
// query support of ERC165 itself
if (!supportsERC165(account)) {
return false;
}
// query support of each interface in _interfaceIds
for (uint256 i = 0; i < interfaceIds.length; i++) {
if (!_supportsERC165Interface(account, interfaceIds[i])) {
return false;
}
}
// all interfaces supported
return true;
}
/**
* @notice Query if a contract implements an interface, does not check ERC165 support
* @param account The address of the contract to query for support of an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @return true if the contract at account indicates support of the interface with
* identifier interfaceId, false otherwise
* @dev Assumes that account contains a contract that supports ERC165, otherwise
* the behavior of this method is undefined. This precondition can be checked
* with {supportsERC165}.
* Interface identification is specified in ERC-165.
*/
function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);
(bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);
if (result.length < 32) return false;
return success && abi.decode(result, (bool));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./IAdminControl.sol";
abstract contract AdminControl is Ownable, IAdminControl, ERC165 {
using EnumerableSet for EnumerableSet.AddressSet;
// Track registered admins
EnumerableSet.AddressSet private _admins;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IAdminControl).interfaceId
|| super.supportsInterface(interfaceId);
}
/**
* @dev Only allows approved admins to call the specified function
*/
modifier adminRequired() {
require(owner() == msg.sender || _admins.contains(msg.sender), "AdminControl: Must be owner or admin");
_;
}
/**
* @dev See {IAdminControl-getAdmins}.
*/
function getAdmins() external view override returns (address[] memory admins) {
admins = new address[](_admins.length());
for (uint i = 0; i < _admins.length(); i++) {
admins[i] = _admins.at(i);
}
return admins;
}
/**
* @dev See {IAdminControl-approveAdmin}.
*/
function approveAdmin(address admin) external override onlyOwner {
if (!_admins.contains(admin)) {
emit AdminApproved(admin, msg.sender);
_admins.add(admin);
}
}
/**
* @dev See {IAdminControl-revokeAdmin}.
*/
function revokeAdmin(address admin) external override onlyOwner {
if (_admins.contains(admin)) {
emit AdminRevoked(admin, msg.sender);
_admins.remove(admin);
}
}
/**
* @dev See {IAdminControl-isAdmin}.
*/
function isAdmin(address admin) public override view returns (bool) {
return (owner() == admin || _admins.contains(admin));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), 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 virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits a {ApprovalForAll} event.
*/
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "./ICollectionBase.sol";
/**
* Collection Drop Contract (Base)
*/
abstract contract CollectionBase is ICollectionBase {
using ECDSA for bytes32;
// Immutable variables that should only be set by the constructor or initializer
address internal _signingAddress;
// Message nonces
mapping(bytes32 => bool) private _usedNonces;
// Sale start/end control
bool public active;
uint256 public startTime;
uint256 public endTime;
uint256 public presaleInterval;
// Claim period start/end control
uint256 public claimStartTime;
uint256 public claimEndTime;
/**
* Withdraw funds
*/
function _withdraw(address payable recipient, uint256 amount) internal {
(bool success,) = recipient.call{value:amount}("");
require(success);
}
/**
* Activate the sale
*/
function _activate(uint256 startTime_, uint256 duration, uint256 presaleInterval_, uint256 claimStartTime_, uint256 claimEndTime_) internal virtual {
require(!active, "Already active");
require(startTime_ > block.timestamp, "Cannot activate in the past");
require(presaleInterval_ <= duration, "Presale Interval cannot be longer than the sale");
require(claimStartTime_ <= claimEndTime_ && claimEndTime_ <= startTime_, "Invalid claim times");
startTime = startTime_;
endTime = startTime + duration;
presaleInterval = presaleInterval_;
claimStartTime = claimStartTime_;
claimEndTime = claimEndTime_;
active = true;
emit CollectionActivated(startTime, endTime, presaleInterval, claimStartTime, claimEndTime);
}
/**
* Deactivate the sale
*/
function _deactivate() internal virtual {
startTime = 0;
endTime = 0;
active = false;
claimStartTime = 0;
claimEndTime = 0;
emit CollectionDeactivated();
}
/**
* Validate claim signature
*/
function _validateClaimRequest(bytes32 message, bytes calldata signature, bytes32 nonce, uint16 amount) internal virtual {
_validatePurchaseRequestWithAmount(message, signature, nonce, amount);
}
/**
* Validate claim restrictions
*/
function _validateClaimRestrictions() internal virtual {
require(active, "Inactive");
require(block.timestamp >= claimStartTime && block.timestamp <= claimEndTime, "Outside claim period.");
}
/**
* Validate purchase signature
*/
function _validatePurchaseRequest(bytes32 message, bytes calldata signature, bytes32 nonce) internal virtual {
// Verify nonce usage/re-use
require(!_usedNonces[nonce], "Cannot replay transaction");
// Verify valid message based on input variables
bytes32 expectedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n52", msg.sender, nonce));
require(message == expectedMessage, "Malformed message");
// Verify signature was performed by the expected signing address
address signer = message.recover(signature);
require(signer == _signingAddress, "Invalid signature");
_usedNonces[nonce] = true;
}
/**
* Validate purchase signature with amount
*/
function _validatePurchaseRequestWithAmount(bytes32 message, bytes calldata signature, bytes32 nonce, uint16 amount) internal virtual {
// Verify nonce usage/re-use
require(!_usedNonces[nonce], "Cannot replay transaction");
// Verify valid message based on input variables
bytes32 expectedMessage = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n54", msg.sender, nonce, amount));
require(message == expectedMessage, "Malformed message");
// Verify signature was performed by the expected signing address
address signer = message.recover(signature);
require(signer == _signingAddress, "Invalid signature");
_usedNonces[nonce] = true;
}
/**
* Perform purchase restriciton checks. Override if more logic is needed
*/
function _validatePurchaseRestrictions() internal virtual {
require(active, "Inactive");
require(block.timestamp >= startTime, "Purchasing not active");
}
/**
* @dev See {ICollectionBase-nonceUsed}.
*/
function nonceUsed(bytes32 nonce) external view override returns(bool) {
return _usedNonces[nonce];
}
/**
* @dev Check if currently in presale
*/
function _isPresale() internal view returns (bool) {
return block.timestamp > startTime && block.timestamp - startTime < presaleInterval;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "./ICollectionBase.sol";
/**
* @dev ERC721 Collection Interface
*/
interface IERC721Collection is ICollectionBase, IERC165 {
event Unveil(uint256 collectibleId, address tokenAddress, uint256 tokenId);
struct CollectionState {
uint16 transactionLimit;
uint16 purchaseMax;
uint16 purchaseRemaining;
uint256 purchasePrice;
uint16 purchaseLimit;
uint256 presalePurchasePrice;
uint16 presalePurchaseLimit;
uint16 purchaseCount;
bool active;
uint256 startTime;
uint256 endTime;
uint256 presaleInterval;
uint256 claimStartTime;
uint256 claimEndTime;
bool useDynamicPresalePurchaseLimit;
}
/**
* @dev Pre-mint
*/
function premint(uint16 amount) external;
function premint(address[] calldata addresses) external;
/**
* @dev set the tokenURI prefix
*/
function setTokenURIPrefix(string calldata prefix) external;
/**
* @dev Withdraw funds
*/
function withdraw(address payable recipient, uint256 amount) external;
/**
* @dev Set whether or not token transfers are locked until end of sale.
* @param locked Whether or not transfers are locked
*/
function setTransferLocked(bool locked) external;
/**
* @dev Activate the contract
*/
function activate(uint256 startTime_, uint256 duration, uint256 presaleInterval_, uint256 claimStartTime_, uint256 claimEndTime_) external;
/**
* @dev Deactivate the contract
*/
function deactivate() external;
/**
* @dev claim
*/
function claim(uint16 amount, bytes32 message, bytes calldata signature, bytes32 nonce) external;
/**
* @dev purchase
*/
function purchase(uint16 amount, bytes32 message, bytes calldata signature, bytes32 nonce) external payable;
/**
* @dev returns the collection state
*/
function state() external view returns(CollectionState memory);
/**
* @dev Get number of tokens left
*/
function purchaseRemaining() external view returns(uint16);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
/**
* @dev Base creator extension variables
*/
abstract contract CreatorExtension is ERC165 {
/**
* @dev Legacy extension interface identifiers
*
* {IERC165-supportsInterface} needs to return 'true' for this interface
* in order backwards compatible with older creator contracts
*/
bytes4 constant internal LEGACY_EXTENSION_INTERFACE = 0x7005caad;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165) returns (bool) {
return interfaceId == LEGACY_EXTENSION_INTERFACE
|| super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "./ICreatorCore.sol";
/**
* @dev Core ERC721 creator interface
*/
interface IERC721CreatorCore is ICreatorCore {
/**
* @dev mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/
function mintBase(address to) external returns (uint256);
/**
* @dev mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/
function mintBase(address to, string calldata uri) external returns (uint256);
/**
* @dev batch mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/
function mintBaseBatch(address to, uint16 count) external returns (uint256[] memory);
/**
* @dev batch mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/
function mintBaseBatch(address to, string[] calldata uris) external returns (uint256[] memory);
/**
* @dev mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/
function mintExtension(address to) external returns (uint256);
/**
* @dev mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/
function mintExtension(address to, string calldata uri) external returns (uint256);
/**
* @dev batch mint a token. Can only be called by a registered extension.
* Returns tokenIds minted
*/
function mintExtensionBatch(address to, uint16 count) external returns (uint256[] memory);
/**
* @dev batch mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/
function mintExtensionBatch(address to, string[] calldata uris) external returns (uint256[] memory);
/**
* @dev burn a token. Can only be called by token owner or approved address.
* On burn, calls back to the registered extension's onBurn method
*/
function burn(uint256 tokenId) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "./IERC721RedeemBase.sol";
/**
* @dev Burn NFT's to receive another lazy minted NFT
*/
interface IERC721BurnRedeem is IERC721RedeemBase {
/**
* @dev Enable recovery of a given token. Can only be called by contract owner/admin.
* This is a special function used in case someone accidentally sends a token to this contract.
*/
function setERC721Recoverable(address contract_, uint256 tokenId, address recoverer) external;
/**
* @dev Recover a token. Returns it to the recoverer set by setERC721Recoverable
* This is a special function used in case someone accidentally sends a token to this contract.
*/
function recoverERC721(address contract_, uint256 tokenId) external;
/**
* @dev Redeem ERC721 tokens for redemption reward NFT.
* Requires the user to grant approval beforehand by calling contract's 'approve' function.
* If the it cannot redeem the NFT, it will clear approvals
*/
function redeemERC721(address[] calldata contracts, uint256[] calldata tokenIds) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "@manifoldxyz/creator-core-solidity/contracts/core/IERC721CreatorCore.sol";
import "@manifoldxyz/creator-core-solidity/contracts/extensions/CreatorExtension.sol";
import "./ERC721SingleCreatorExtension.sol";
import "./RedeemBase.sol";
import "./IERC721RedeemBase.sol";
/**
* @dev Redeem NFT base logic
*/
abstract contract ERC721RedeemBase is ERC721SingleCreatorExtension, RedeemBase, CreatorExtension, IERC721RedeemBase {
uint16 internal immutable _redemptionRate;
uint16 private _redemptionMax;
uint16 private _redemptionCount;
uint256[] private _mintedTokens;
mapping(uint256 => uint256) internal _mintNumbers;
constructor(address creator, uint16 redemptionRate_, uint16 redemptionMax_) ERC721SingleCreatorExtension(creator) {
require(ERC165Checker.supportsInterface(creator, type(IERC721CreatorCore).interfaceId) ||
ERC165Checker.supportsInterface(creator, LegacyInterfaces.IERC721CreatorCore_v1),
"Redeem: Minting reward contract must implement IERC721CreatorCore");
_redemptionRate = redemptionRate_;
_redemptionMax = redemptionMax_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(RedeemBase, CreatorExtension, IERC165) returns (bool) {
return interfaceId == type(IERC721RedeemBase).interfaceId || RedeemBase.supportsInterface(interfaceId) || CreatorExtension.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721RedeemBase-redemptionMax}
*/
function redemptionMax() external view virtual override returns(uint16) {
return _redemptionMax;
}
/**
* @dev See {IERC721RedeemBase-redemptionRate}
*/
function redemptionRate() external view virtual override returns(uint16) {
return _redemptionRate;
}
/**
* @dev See {IERC721RedeemBase-redemptionRemaining}
*/
function redemptionRemaining() public view virtual override returns(uint16) {
return _redemptionMax-_redemptionCount;
}
/**
* @dev See {IERC721RedeemBase-mintNumber}.
*/
function mintNumber(uint256 tokenId) external view virtual override returns(uint256) {
return _mintNumbers[tokenId];
}
/**
* @dev See {IERC721RedeemBase-mintedTokens}.
*/
function mintedTokens() external view override returns(uint256[] memory) {
return _mintedTokens;
}
/**
* @dev mint token that was redeemed for
*/
function _mintRedemption(address to) internal virtual returns (uint256) {
require(_redemptionCount < _redemptionMax, "Redeem: No redemptions remaining");
_redemptionCount++;
// Mint token
uint256 tokenId = _mint(to, _redemptionCount);
_mintedTokens.push(tokenId);
_mintNumbers[tokenId] = _redemptionCount;
return tokenId;
}
/**
* @dev override if you want to perform different mint functionality
*/
function _mint(address to, uint16) internal virtual returns (uint256) {
return IERC721CreatorCore(_creator).mintExtension(to);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/EnumerableSet.sol)
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
return _values(set._inner);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
external
view
returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev _Available since v3.1._
*/
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Interface for admin control
*/
interface IAdminControl is IERC165 {
event AdminApproved(address indexed account, address indexed sender);
event AdminRevoked(address indexed account, address indexed sender);
/**
* @dev gets address of all admins
*/
function getAdmins() external view returns (address[] memory);
/**
* @dev add an admin. Can only be called by contract owner.
*/
function approveAdmin(address admin) external;
/**
* @dev remove an admin. Can only be called by contract owner.
*/
function revokeAdmin(address admin) external;
/**
* @dev checks whether or not given address is an admin
* Returns True if they are
*/
function isAdmin(address admin) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
/**
* @dev Collection Interface
*/
interface ICollectionBase {
event CollectionActivated(uint256 startTime, uint256 endTime, uint256 presaleInterval, uint256 claimStartTime, uint256 claimEndTime);
event CollectionDeactivated();
/**
* @dev Check if nonce has been used
*/
function nonceUsed(bytes32 nonce) external view returns(bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "./IRedeemBase.sol";
/**
* @dev Base redemption interface
*/
interface IERC721RedeemBase is IRedeemBase {
/**
* @dev Get the max number of redemptions
*/
function redemptionMax() external view returns(uint16);
/**
* @dev Get the redemption rate
*/
function redemptionRate() external view returns(uint16);
/**
* @dev Get number of redemptions left
*/
function redemptionRemaining() external view returns(uint16);
/**
* @dev Get the mint number of a created token id
*/
function mintNumber(uint256 tokenId) external view returns(uint256);
/**
* @dev Get list of all minted tokens
*/
function mintedTokens() external view returns(uint256[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@manifoldxyz/libraries-solidity/contracts/access/AdminControl.sol";
import "./IRedeemBase.sol";
struct range{
uint256 min;
uint256 max;
}
/**
* @dev Burn NFT's to receive another lazy minted NFT
*/
abstract contract RedeemBase is AdminControl, IRedeemBase {
using EnumerableSet for EnumerableSet.UintSet;
// approved contract tokens
mapping(address => bool) internal _approvedContracts;
// approved specific tokens
mapping(address => EnumerableSet.UintSet) internal _approvedTokens;
mapping(address => range[]) internal _approvedTokenRange;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(AdminControl, IERC165) returns (bool) {
return interfaceId == type(IRedeemBase).interfaceId
|| super.supportsInterface(interfaceId);
}
/**
* @dev See {IRedeemBase-updateApprovedContracts}
*/
function updateApprovedContracts(address[] memory contracts, bool[] memory approved) public virtual override adminRequired {
require(contracts.length == approved.length, "Redeem: Invalid input parameters");
for (uint i=0; i < contracts.length; i++) {
_approvedContracts[contracts[i]] = approved[i];
}
emit UpdateApprovedContracts(contracts, approved);
}
/**
* @dev See {IRedeemBase-updateApprovedTokens}
*/
function updateApprovedTokens(address contract_, uint256[] memory tokenIds, bool[] memory approved) public virtual override adminRequired {
require(tokenIds.length == approved.length, "Redeem: Invalid input parameters");
for (uint i=0; i < tokenIds.length; i++) {
if (approved[i] && !_approvedTokens[contract_].contains(tokenIds[i])) {
_approvedTokens[contract_].add(tokenIds[i]);
} else if (!approved[i] && _approvedTokens[contract_].contains(tokenIds[i])) {
_approvedTokens[contract_].remove(tokenIds[i]);
}
}
emit UpdateApprovedTokens(contract_, tokenIds, approved);
}
/**
* @dev See {IRedeemBase-updateApprovedTokenRanges}
*/
function updateApprovedTokenRanges(address contract_, uint256[] memory minTokenIds, uint256[] memory maxTokenIds) public virtual override adminRequired {
require(minTokenIds.length == maxTokenIds.length, "Redeem: Invalid input parameters");
delete _approvedTokenRange[contract_];
for (uint i=0; i < minTokenIds.length; i++) {
require(minTokenIds[i] < maxTokenIds[i], "Redeem: min must be less than max");
_approvedTokenRange[contract_].push(range(minTokenIds[i], maxTokenIds[i]));
}
emit UpdateApprovedTokenRanges(contract_, minTokenIds, maxTokenIds);
}
/**
* @dev See {IRedeemBase-redeemable}
*/
function redeemable(address contract_, uint256 tokenId) public view virtual override returns(bool) {
if (_approvedContracts[contract_]) {
return true;
}
if (_approvedTokens[contract_].contains(tokenId)) {
return true;
}
if (_approvedTokenRange[contract_].length > 0) {
for (uint i=0; i < _approvedTokenRange[contract_].length; i++) {
if (_approvedTokenRange[contract_][i].max != 0 && tokenId >= _approvedTokenRange[contract_][i].min && tokenId <= _approvedTokenRange[contract_][i].max) {
return true;
}
}
}
return false;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "./ERC721SingleCreatorExtensionBase.sol";
/**
* @dev Extension that only uses a single creator contract instance
*/
abstract contract ERC721SingleCreatorExtension is ERC721SingleCreatorExtensionBase {
constructor(address creator) {
_setCreator(creator);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
// Check the signature length
// - case 65: r,s,v signature (standard)
// - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else if (signature.length == 64) {
bytes32 r;
bytes32 vs;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
assembly {
r := mload(add(signature, 0x20))
vs := mload(add(signature, 0x40))
}
return tryRecover(hash, r, vs);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Core creator interface
*/
interface ICreatorCore is IERC165 {
event ExtensionRegistered(address indexed extension, address indexed sender);
event ExtensionUnregistered(address indexed extension, address indexed sender);
event ExtensionBlacklisted(address indexed extension, address indexed sender);
event MintPermissionsUpdated(address indexed extension, address indexed permissions, address indexed sender);
event RoyaltiesUpdated(uint256 indexed tokenId, address payable[] receivers, uint256[] basisPoints);
event DefaultRoyaltiesUpdated(address payable[] receivers, uint256[] basisPoints);
event ExtensionRoyaltiesUpdated(address indexed extension, address payable[] receivers, uint256[] basisPoints);
event ExtensionApproveTransferUpdated(address indexed extension, bool enabled);
/**
* @dev gets address of all extensions
*/
function getExtensions() external view returns (address[] memory);
/**
* @dev add an extension. Can only be called by contract owner or admin.
* extension address must point to a contract implementing ICreatorExtension.
* Returns True if newly added, False if already added.
*/
function registerExtension(address extension, string calldata baseURI) external;
/**
* @dev add an extension. Can only be called by contract owner or admin.
* extension address must point to a contract implementing ICreatorExtension.
* Returns True if newly added, False if already added.
*/
function registerExtension(address extension, string calldata baseURI, bool baseURIIdentical) external;
/**
* @dev add an extension. Can only be called by contract owner or admin.
* Returns True if removed, False if already removed.
*/
function unregisterExtension(address extension) external;
/**
* @dev blacklist an extension. Can only be called by contract owner or admin.
* This function will destroy all ability to reference the metadata of any tokens created
* by the specified extension. It will also unregister the extension if needed.
* Returns True if removed, False if already removed.
*/
function blacklistExtension(address extension) external;
/**
* @dev set the baseTokenURI of an extension. Can only be called by extension.
*/
function setBaseTokenURIExtension(string calldata uri) external;
/**
* @dev set the baseTokenURI of an extension. Can only be called by extension.
* For tokens with no uri configured, tokenURI will return "uri+tokenId"
*/
function setBaseTokenURIExtension(string calldata uri, bool identical) external;
/**
* @dev set the common prefix of an extension. Can only be called by extension.
* If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI"
* Useful if you want to use ipfs/arweave
*/
function setTokenURIPrefixExtension(string calldata prefix) external;
/**
* @dev set the tokenURI of a token extension. Can only be called by extension that minted token.
*/
function setTokenURIExtension(uint256 tokenId, string calldata uri) external;
/**
* @dev set the tokenURI of a token extension for multiple tokens. Can only be called by extension that minted token.
*/
function setTokenURIExtension(uint256[] memory tokenId, string[] calldata uri) external;
/**
* @dev set the baseTokenURI for tokens with no extension. Can only be called by owner/admin.
* For tokens with no uri configured, tokenURI will return "uri+tokenId"
*/
function setBaseTokenURI(string calldata uri) external;
/**
* @dev set the common prefix for tokens with no extension. Can only be called by owner/admin.
* If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI"
* Useful if you want to use ipfs/arweave
*/
function setTokenURIPrefix(string calldata prefix) external;
/**
* @dev set the tokenURI of a token with no extension. Can only be called by owner/admin.
*/
function setTokenURI(uint256 tokenId, string calldata uri) external;
/**
* @dev set the tokenURI of multiple tokens with no extension. Can only be called by owner/admin.
*/
function setTokenURI(uint256[] memory tokenIds, string[] calldata uris) external;
/**
* @dev set a permissions contract for an extension. Used to control minting.
*/
function setMintPermissions(address extension, address permissions) external;
/**
* @dev Configure so transfers of tokens created by the caller (must be extension) gets approval
* from the extension before transferring
*/
function setApproveTransferExtension(bool enabled) external;
/**
* @dev get the extension of a given token
*/
function tokenExtension(uint256 tokenId) external view returns (address);
/**
* @dev Set default royalties
*/
function setRoyalties(address payable[] calldata receivers, uint256[] calldata basisPoints) external;
/**
* @dev Set royalties of a token
*/
function setRoyalties(uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints) external;
/**
* @dev Set royalties of an extension
*/
function setRoyaltiesExtension(address extension, address payable[] calldata receivers, uint256[] calldata basisPoints) external;
/**
* @dev Get royalites of a token. Returns list of receivers and basisPoints
*/
function getRoyalties(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
// Royalty support for various other standards
function getFeeRecipients(uint256 tokenId) external view returns (address payable[] memory);
function getFeeBps(uint256 tokenId) external view returns (uint[] memory);
function getFees(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
function royaltyInfo(uint256 tokenId, uint256 value) external view returns (address, uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@manifoldxyz/libraries-solidity/contracts/access/IAdminControl.sol";
/**
* @dev Base redemption interface
*/
interface IRedeemBase is IAdminControl {
event UpdateApprovedContracts(address[] contracts, bool[] approved);
event UpdateApprovedTokens(address contract_, uint256[] tokenIds, bool[] approved);
event UpdateApprovedTokenRanges(address contract_, uint256[] minTokenIds, uint256[] maxTokenIds);
/**
* @dev Update approved contracts that can be used to redeem. Can only be called by contract owner/admin.
*/
function updateApprovedContracts(address[] calldata contracts, bool[] calldata approved) external;
/**
* @dev Update approved tokens that can be used to redeem. Can only be called by contract owner/admin.
*/
function updateApprovedTokens(address contract_, uint256[] calldata tokenIds, bool[] calldata approved) external;
/**
* @dev Update approved token ranges that can be used to redeem. Can only be called by contract owner/admin.
* Clears out old ranges
*/
function updateApprovedTokenRanges(address contract_, uint256[] calldata minTokenIds, uint256[] calldata maxTokenIds) external;
/**
* @dev Check if an NFT is redeemable
*/
function redeemable(address contract_, uint256 tokenId) external view returns(bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "@manifoldxyz/creator-core-solidity/contracts/core/IERC721CreatorCore.sol";
import "./LegacyInterfaces.sol";
import "./SingleCreatorExtensionBase.sol";
/**
* @dev Extension that only uses a single creator contract instance
*/
abstract contract ERC721SingleCreatorExtensionBase is SingleCreatorExtensionBase {
function _setCreator(address creator) internal override {
require(ERC165Checker.supportsInterface(creator, type(IERC721CreatorCore).interfaceId) ||
ERC165Checker.supportsInterface(creator, LegacyInterfaces.IERC721CreatorCore_v1),
"Creator contract must implement IERC721CreatorCore");
super._setCreator(creator);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @author: manifold.xyz
/**
* @dev Extension that only uses a single creator contract instance
*/
abstract contract SingleCreatorExtensionBase {
address internal _creator;
/**
* @dev Override with appropriate interface checks if necessary
*/
function _setCreator(address creator) internal virtual {
_creator = creator;
}
function creatorContract() public view returns(address) {
return _creator;
}
}// SPDX-License-Identifier: BSD-4-Clause
pragma solidity ^0.8.0;
/// @author: manifold.xyz
/**
* Library of legacy interface constants
*/
library LegacyInterfaces {
// LEGACY ERC721CreatorCore interface
bytes4 internal constant IERC721CreatorCore_v1 = 0x478c8530;
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"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":"creatorAddress","type":"address"},{"internalType":"address","name":"signingAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"AdminApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"AdminRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"presaleInterval","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claimStartTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claimEndTime","type":"uint256"}],"name":"CollectionActivated","type":"event"},{"anonymous":false,"inputs":[],"name":"CollectionDeactivated","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":"uint256","name":"received","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"returned","type":"uint256"}],"name":"SenderRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"collectibleId","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Unveil","type":"event"},{"inputs":[{"internalType":"uint256","name":"startTime_","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"},{"internalType":"uint256","name":"presaleInterval_","type":"uint256"},{"internalType":"uint256","name":"claimStartTime_","type":"uint256"},{"internalType":"uint256","name":"claimEndTime_","type":"uint256"}],"name":"activate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"active","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"approveAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"approveTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"amount","type":"uint16"},{"internalType":"bytes32","name":"message","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deactivate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAdmins","outputs":[{"internalType":"address[]","name":"admins","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"nonceUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"amount","type":"uint16"}],"name":"premint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"name":"premint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"presaleInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presalePurchaseLimit","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presalePurchasePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceDropInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceDropMagnitude","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricingData","outputs":[{"components":[{"internalType":"uint256","name":"minimumPrice","type":"uint256"},{"internalType":"uint256","name":"priceDropInterval","type":"uint256"},{"internalType":"uint256","name":"priceDropMagnitude","type":"uint256"}],"internalType":"struct DutchAuction.DutchAuctionData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicSaleStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"amount","type":"uint16"},{"internalType":"bytes32","name":"message","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"nonce","type":"bytes32"}],"name":"purchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"purchaseCount","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"purchaseLimit","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"purchaseMax","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"purchasePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"purchaseRemaining","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"revokeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setApproveTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"prefix","type":"string"}],"name":"setTokenURIPrefix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"locked","type":"bool"}],"name":"setTransferLocked","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state","outputs":[{"components":[{"internalType":"uint16","name":"transactionLimit","type":"uint16"},{"internalType":"uint16","name":"purchaseMax","type":"uint16"},{"internalType":"uint16","name":"purchaseRemaining","type":"uint16"},{"internalType":"uint256","name":"purchasePrice","type":"uint256"},{"internalType":"uint16","name":"purchaseLimit","type":"uint16"},{"internalType":"uint256","name":"presalePurchasePrice","type":"uint256"},{"internalType":"uint16","name":"presalePurchaseLimit","type":"uint16"},{"internalType":"uint16","name":"purchaseCount","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"presaleInterval","type":"uint256"},{"internalType":"uint256","name":"claimStartTime","type":"uint256"},{"internalType":"uint256","name":"claimEndTime","type":"uint256"},{"internalType":"bool","name":"useDynamicPresalePurchaseLimit","type":"bool"}],"internalType":"struct IERC721Collection.CollectionState","name":"","type":"tuple"}],"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":"transactionLimit","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"useDynamicPresalePurchaseLimit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b50604051620032f0380380620032f0833981016040819052620000349162000209565b6200003f3362000087565b6001601355620000628261016d6732a767a9562d000081806000808881620000d9565b50506706f05b59d3b2000060105561012c60115566b1a2bc2ec5000060125562000241565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6009546001600160a01b0316158015620000fc57506000546001600160a01b0316155b6200014d5760405162461bcd60e51b815260206004820152601360248201527f416c726561647920696e697469616c697a656400000000000000000000000000604482015260640160405180910390fd5b60098054600a98909855600b805461ffff98891661ffff19909116179055948616600160a01b0261ffff60a01b19988716600160b01b02600163ffff000160a01b03199098166001600160a01b039a8b1617979097179790971695909517909255600c55600d805460008054959097166001600160a01b03199590951694909417909555921515620100000262ffffff19909216921691909117179055565b80516001600160a01b03811681146200020457600080fd5b919050565b600080604083850312156200021d57600080fd5b6200022883620001ec565b91506200023860208401620001ec565b90509250929050565b61309f80620002516000396000f3fe6080604052600436106102515760003560e01c8063715018a611610139578063a6a11bb1116100b6578063e59bb7a81161007a578063e59bb7a8146106a2578063f19605d6146106c2578063f2fde38b146106e4578063f3fef3a314610704578063f474307014610724578063fe73ad771461073f57600080fd5b8063a6a11bb11461061c578063c19d93fb14610632578063c8a84a8214610654578063defd6c5f14610676578063e3b9398b1461068c57600080fd5b806382580805116100fd5780638258080514610574578063850217d8146105945780638da5cb5b146105b4578063956447d8146105dc57806399e0dd7c146105fc57600080fd5b8063715018a6146104fd57806378e979251461051257806379070afa146105285780637f386b6c1461054857806381960b5c1461055e57600080fd5b806331ae450b116101d257806355461d6d1161019657806355461d6d1461042e57806361a4422b1461044e5780636741f24a1461047e5780636b9990dc146104915780636bb7b1d9146104c85780636d73e669146104dd57600080fd5b806331ae450b146103ab57806335e60bd4146103cd578063379ffdca146103ed57806340d1d2551461040357806351b42b001461041957600080fd5b80631b95a227116102195780631b95a2271461031157806324d7806c146103335780632b85ed9c146103535780632d345670146103755780633197cbb61461039557600080fd5b806301ffc9a71461025657806302fb0c5e1461028b57806312686aae146102a557806318886657146102bf5780631b4d21c8146102ed575b600080fd5b34801561026257600080fd5b50610276610271366004612b3a565b610754565b60405190151581526020015b60405180910390f35b34801561029757600080fd5b506002546102769060ff1681565b3480156102b157600080fd5b50600f546102769060ff1681565b3480156102cb57600080fd5b50600b546102da9061ffff1681565b60405161ffff9091168152602001610282565b3480156102f957600080fd5b5061030360115481565b604051908152602001610282565b34801561031d57600080fd5b5061033161032c366004612974565b61078e565b005b34801561033f57600080fd5b5061027661034e3660046128ea565b6108b0565b34801561035f57600080fd5b50600d546102da906301000000900461ffff1681565b34801561038157600080fd5b506103316103903660046128ea565b6108e9565b3480156103a157600080fd5b5061030360045481565b3480156103b757600080fd5b506103c0610969565b6040516102829190612cb2565b3480156103d957600080fd5b506103316103e8366004612ae7565b610a18565b3480156103f957600080fd5b5061030360125481565b34801561040f57600080fd5b5061030360075481565b34801561042557600080fd5b50610331610a73565b34801561043a57600080fd5b50600d546102769062010000900460ff1681565b34801561045a57600080fd5b50610276610469366004612b21565b60009081526001602052604090205460ff1690565b61033161048c366004612bc1565b610ac7565b34801561049d57600080fd5b506104a6610bb9565b6040805182518152602080840151908201529181015190820152606001610282565b3480156104d457600080fd5b50610303610c03565b3480156104e957600080fd5b506103316104f83660046128ea565b610c1a565b34801561050957600080fd5b50610331610c94565b34801561051e57600080fd5b5061030360035481565b34801561053457600080fd5b50610331610543366004612bc1565b610cc8565b34801561055457600080fd5b5061030360105481565b34801561056a57600080fd5b50610303600c5481565b34801561058057600080fd5b5061027661058f366004612933565b610d2b565b3480156105a057600080fd5b506103316105af366004612ba6565b610d3e565b3480156105c057600080fd5b506008546040516001600160a01b039091168152602001610282565b3480156105e857600080fd5b506103316105f7366004612c3c565b610da3565b34801561060857600080fd5b50610331610617366004612b64565b610e01565b34801561062857600080fd5b5061030360065481565b34801561063e57600080fd5b50610647610e55565b6040516102829190612dfb565b34801561066057600080fd5b506009546102da90600160b01b900461ffff1681565b34801561068257600080fd5b50610303600a5481565b34801561069857600080fd5b5061030360055481565b3480156106ae57600080fd5b506103316106bd3660046129ad565b610f9f565b3480156106ce57600080fd5b506009546102da90600160a01b900461ffff1681565b3480156106f057600080fd5b506103316106ff3660046128ea565b610ff3565b34801561071057600080fd5b5061033161071f366004612907565b61108b565b34801561073057600080fd5b50600d546102da9061ffff1681565b34801561074b57600080fd5b506102da6110df565b60006001600160e01b03198216634ce6d51160e11b1480610779575061077982611108565b8061078857506107888261112d565b92915050565b336107a16008546001600160a01b031690565b6001600160a01b031614806107bc57506107bc601433611152565b6107e15760405162461bcd60e51b81526004016107d890612db7565b60405180910390fd5b6107f282639088c20760e01b611177565b6108505760405162461bcd60e51b815260206004820152602960248201527f43726561746f72206d75737420696d706c656d656e74204945524337323143726044820152686561746f72436f726560b81b60648201526084016107d8565b604051635606467d60e11b815281151560048201526001600160a01b0383169063ac0c8cfa906024015b600060405180830381600087803b15801561089457600080fd5b505af11580156108a8573d6000803e3d6000fd5b505050505050565b6000816001600160a01b03166108ce6008546001600160a01b031690565b6001600160a01b031614806107885750610788601483611152565b6008546001600160a01b031633146109135760405162461bcd60e51b81526004016107d890612d5a565b61091e601482611152565b156109665760405133906001600160a01b038316907f7c0c3c84c67c85fcac635147348bfe374c24a1a93d0366d1cfe9d8853cbf89d590600090a3610964601482611193565b505b50565b606061097560146111a8565b67ffffffffffffffff81111561098d5761098d613030565b6040519080825280602002602001820160405280156109b6578160200160208202803683370190505b50905060005b6109c660146111a8565b811015610a14576109d86014826111b2565b8282815181106109ea576109ea61301a565b6001600160a01b039092166020928302919091019091015280610a0c81612fbd565b9150506109bc565b5090565b33610a2b6008546001600160a01b031690565b6001600160a01b03161480610a465750610a46601433611152565b610a625760405162461bcd60e51b81526004016107d890612db7565b600f805460ff191682151517905550565b33610a866008546001600160a01b031690565b6001600160a01b03161480610aa15750610aa1601433611152565b610abd5760405162461bcd60e51b81526004016107d890612db7565b610ac56111be565b565b60026013541415610b1a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107d8565b6002601355610b2c8585858585611207565b6000610b3c600c54600a54611505565b610b4a9061ffff8816612f42565b905080341115610bac57610b6733610b628334612f84565b61158f565b7f7fb144214d6945ccc22e755bd2fa1e65488d2c9d08af5f0a40a766426865f3ed34610b938382612f84565b6040805192835260208301919091520160405180910390a15b5050600160135550505050565b610bdd60405180606001604052806000815260200160008152602001600081525090565b604051806060016040528060105481526020016011548152602001601254815250905090565b6000600554600354610c159190612f08565b905090565b6008546001600160a01b03163314610c445760405162461bcd60e51b81526004016107d890612d5a565b610c4f601482611152565b6109665760405133906001600160a01b038316907f7e1a1a08d52e4ba0e21554733d66165fd5151f99460116223d9e3a608eec5cb190600090a36109646014826116ad565b6008546001600160a01b03163314610cbe5760405162461bcd60e51b81526004016107d890612d5a565b610ac560006116c2565b610cd0611714565b610cdd84848484896117a9565b610ce733866117b6565b336000908152600e602052604081208054879290610d0a90849061ffff16612ee2565b92506101000a81548161ffff021916908361ffff1602179055505050505050565b6000610d3684611a65565b949350505050565b33610d516008546001600160a01b031690565b6001600160a01b03161480610d6c5750610d6c601433611152565b610d885760405162461bcd60e51b81526004016107d890612db7565b61096681610d9e6008546001600160a01b031690565b611a85565b33610db66008546001600160a01b031690565b6001600160a01b03161480610dd15750610dd1601433611152565b610ded5760405162461bcd60e51b81526004016107d890612db7565b610dfa8585858585611ab2565b5050505050565b33610e146008546001600160a01b031690565b6001600160a01b03161480610e2f5750610e2f601433611152565b610e4b5760405162461bcd60e51b81526004016107d890612db7565b6109648282611c68565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c0810191909152604080516101e08101825260095461ffff600160a01b820481168352600160b01b909104166020820152908101610f036110df565b61ffff9081168252600a54602080840191909152600b548216604080850191909152600c546060850152600d548084166080860152336000908152600e90935291205490911660a083015260025460ff908116151560c084015260035460e08401526004546101008401526005546101208401526006546101408401526007546101608401526201000090910416151561018090910152919050565b33610fb26008546001600160a01b031690565b6001600160a01b03161480610fcd5750610fcd601433611152565b610fe95760405162461bcd60e51b81526004016107d890612db7565b6109648282611c9a565b6008546001600160a01b0316331461101d5760405162461bcd60e51b81526004016107d890612d5a565b6001600160a01b0381166110825760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016107d8565b610966816116c2565b3361109e6008546001600160a01b031690565b6001600160a01b031614806110b957506110b9601433611152565b6110d55760405162461bcd60e51b81526004016107d890612db7565b6109648282611d01565b600d54600954600091610c159161ffff6301000000909204821691600160b01b90910416612f61565b60006001600160e01b0319821663da192f9f60e01b1480610788575061078882611d61565b60006001600160e01b03198216632a9f3abf60e11b1480610788575061078882611108565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b600061118283611d96565b801561117057506111708383611dc9565b6000611170836001600160a01b038416611ea8565b6000610788825490565b60006111708383611f9b565b6000600381905560048190556002805460ff19169055600681905560078190556040517fb02389feab3af620e2374d4d559b436ea226b1e6c9c31fe77dfbff3d40cbe9ba9190a1565b61120f611fc5565b600061121961204c565b90506112236110df565b61ffff168661ffff161115801561127c575080801561124a5750600d5462010000900460ff165b806112605750600954600160a01b900461ffff16155b8061127c575060095461ffff600160a01b909104811690871611155b6112985760405162461bcd60e51b81526004016107d890612d2e565b801561140457600d5462010000900460ff1661138657600d5461ffff161561131a57336000908152600e6020526040902054600d5461ffff9182169116811080156112fc5750600d546112f090829061ffff16612f61565b61ffff168761ffff1611155b6113185760405162461bcd60e51b81526004016107d890612d2e565b505b600b5461ffff161561138657336000908152600e6020526040902054600b5461ffff9182169116811080156113685750600b5461135c90829061ffff16612f61565b61ffff168761ffff1611155b6113845760405162461bcd60e51b81526004016107d890612d2e565b505b61138f86612070565b600d5462010000900460ff161580156113bc5750600d5461ffff161515806113bc5750600b5461ffff1615155b156113ff57336000908152600e6020526040812080548892906113e490849061ffff16612ee2565b92506101000a81548161ffff021916908361ffff1602179055505b6114c3565b600b5461ffff161561147057336000908152600e6020526040902054600b5461ffff9182169116811080156114525750600b5461144690829061ffff16612f61565b61ffff168761ffff1611155b61146e5760405162461bcd60e51b81526004016107d890612d2e565b505b611479866120cf565b600b5461ffff16156114c357336000908152600e6020526040812080548892906114a890849061ffff16612ee2565b92506101000a81548161ffff021916908361ffff1602179055505b8080156114d85750600d5462010000900460ff165b156114ef576114ea858585858a61213a565b6114fb565b6114fb8585858561230e565b6108a833876117b6565b600061150f61204c565b1561151b575081610788565b6000611525610c03565b61152f9042612f84565b90506000601254601154836115449190612f20565b61154e9190612f42565b9050838111156115645760105492505050610788565b60006115708286612f84565b9050601054811161158357601054611585565b805b9695505050505050565b804710156115df5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016107d8565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461162c576040519150601f19603f3d011682016040523d82523d6000602084013e611631565b606091505b50509050806116a85760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016107d8565b505050565b6000611170836001600160a01b0384166124cd565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60025460ff166117515760405162461bcd60e51b8152602060048201526008602482015267496e61637469766560c01b60448201526064016107d8565b600654421015801561176557506007544211155b610ac55760405162461bcd60e51b815260206004820152601560248201527427baba39b4b2329031b630b4b6903832b934b7b21760591b60448201526064016107d8565b610dfa858585858561213a565b8061ffff16600114156118df57600d80546301000000900461ffff169060036117de83612f9b565b825461ffff9182166101009390930a928302919092021990911617905550600954604051630525194b60e31b81526001600160a01b0384811660048301526000921690632928ca5890602401602060405180830381600087803b15801561184457600080fd5b505af1158015611858573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061187c9190612c23565b600d5460095460408051630100000090930461ffff1683526001600160a01b03909116602083015281018290529091507f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba39060600160405180910390a150610964565b600d546000906118fb906301000000900461ffff166001612ee2565b600d805461ffff9283169350849260039161191f9185916301000000900416612ee2565b82546101009290920a61ffff81810219909316918316021790915560095460405163e00aab4b60e01b81526001600160a01b03878116600483015292861660248201526000935091169063e00aab4b90604401600060405180830381600087803b15801561198c57600080fd5b505af11580156119a0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526119c89190810190612a22565b905060005b8151811015610dfa577f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba3611a018285612f08565b60095484516001600160a01b0390911690859085908110611a2457611a2461301a565b6020026020010151604051611a55939291909283526001600160a01b03919091166020830152604082015260600190565b60405180910390a16001016119cd565b60006001600160a01b03821615806107885750600f5460ff161592915050565b60025460ff1615611aa85760405162461bcd60e51b81526004016107d890612d8f565b61096481836117b6565b60025460ff1615611ad55760405162461bcd60e51b81526004016107d890612d8f565b428511611b245760405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f7420616374697661746520696e207468652070617374000000000060448201526064016107d8565b83831115611b8c5760405162461bcd60e51b815260206004820152602f60248201527f50726573616c6520496e74657276616c2063616e6e6f74206265206c6f6e676560448201526e72207468616e207468652073616c6560881b60648201526084016107d8565b808211158015611b9c5750848111155b611bde5760405162461bcd60e51b8152602060048201526013602482015272496e76616c696420636c61696d2074696d657360681b60448201526064016107d8565b6003859055611bed8486612f08565b60048190556005849055600683905560078290556002805460ff1916600117905560035460408051918252602082019290925290810184905260608101839052608081018290527fe512d106f8172b08abfd2fc5ddfdb7e2401381780ae29e29f1352b862f1d27319060a00160405180910390a15050505050565b6009546040516307cc269760e31b81526001600160a01b0390911690633e6134b89061087a9085908590600401612cff565b60025460ff1615611cbd5760405162461bcd60e51b81526004016107d890612d8f565b60005b818110156116a857611cf9838383818110611cdd57611cdd61301a565b9050602002016020810190611cf291906128ea565b60016117b6565b600101611cc0565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611d4e576040519150601f19603f3d011682016040523d82523d6000602084013e611d53565b606091505b50509050806116a857600080fd5b60006001600160e01b03198216637005caad60e01b148061078857506301ffc9a760e01b6001600160e01b0319831614610788565b6000611da9826301ffc9a760e01b611dc9565b80156107885750611dc2826001600160e01b0319611dc9565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b0387169061753090611e30908690612c77565b6000604051808303818686fa925050503d8060008114611e6c576040519150601f19603f3d011682016040523d82523d6000602084013e611e71565b606091505b5091509150602081511015611e8c5760009350505050610788565b8180156115855750808060200190518101906115859190612b04565b60008181526001830160205260408120548015611f91576000611ecc600183612f84565b8554909150600090611ee090600190612f84565b9050818114611f45576000866000018281548110611f0057611f0061301a565b9060005260206000200154905080876000018481548110611f2357611f2361301a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611f5657611f56613004565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610788565b6000915050610788565b6000826000018281548110611fb257611fb261301a565b9060005260206000200154905092915050565b60025460ff166120025760405162461bcd60e51b8152602060048201526008602482015267496e61637469766560c01b60448201526064016107d8565b600354421015610ac55760405162461bcd60e51b815260206004820152601560248201527450757263686173696e67206e6f742061637469766560581b60448201526064016107d8565b600060035442118015610c15575060055460035461206a9042612f84565b10905090565b600c546120819061ffff8316612f42565b34146109665760405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420707572636861736520616d6f756e742073656e740000000060448201526064016107d8565b6120dd600c54600a54611505565b6120eb9061ffff8316612f42565b3410156109665760405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420707572636861736520616d6f756e742073656e740000000060448201526064016107d8565b60008281526001602052604090205460ff16156121955760405162461bcd60e51b815260206004820152601960248201527821b0b73737ba103932b83630bc903a3930b739b0b1ba34b7b760391b60448201526064016107d8565b6040517f19457468657265756d205369676e6564204d6573736167653a0a35340000000060208201526bffffffffffffffffffffffff193360601b16603c820152605081018390526001600160f01b031960f083901b1660708201526000906072016040516020818303038152906040528051906020012090508086146122525760405162461bcd60e51b81526020600482015260116024820152704d616c666f726d6564206d65737361676560781b60448201526064016107d8565b600061229686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b9392505061251c9050565b6000549091506001600160a01b038083169116146122ea5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b60448201526064016107d8565b5050506000908152600160208190526040909120805460ff19169091179055505050565b60008181526001602052604090205460ff16156123695760405162461bcd60e51b815260206004820152601960248201527821b0b73737ba103932b83630bc903a3930b739b0b1ba34b7b760391b60448201526064016107d8565b6040517f19457468657265756d205369676e6564204d6573736167653a0a35320000000060208201526bffffffffffffffffffffffff193360601b16603c820152605081018290526000906070016040516020818303038152906040528051906020012090508085146124125760405162461bcd60e51b81526020600482015260116024820152704d616c666f726d6564206d65737361676560781b60448201526064016107d8565b600061245685858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9392505061251c9050565b6000549091506001600160a01b038083169116146124aa5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b60448201526064016107d8565b50506000908152600160208190526040909120805460ff19169091179055505050565b600081815260018301602052604081205461251457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610788565b506000610788565b600080600061252b8585612540565b91509150612538816125b0565b509392505050565b6000808251604114156125775760208301516040840151606085015160001a61256b8782858561276b565b945094505050506125a9565b8251604014156125a15760208301516040840151612596868383612858565b9350935050506125a9565b506000905060025b9250929050565b60008160048111156125c4576125c4612fee565b14156125cd5750565b60018160048111156125e1576125e1612fee565b141561262f5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016107d8565b600281600481111561264357612643612fee565b14156126915760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016107d8565b60038160048111156126a5576126a5612fee565b14156126fe5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016107d8565b600481600481111561271257612712612fee565b14156109665760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016107d8565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156127a2575060009050600361284f565b8460ff16601b141580156127ba57508460ff16601c14155b156127cb575060009050600461284f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561281f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166128485760006001925092505061284f565b9150600090505b94509492505050565b6000806001600160ff1b0383168161287560ff86901c601b612f08565b90506128838782888561276b565b935093505050935093915050565b60008083601f8401126128a357600080fd5b50813567ffffffffffffffff8111156128bb57600080fd5b6020830191508360208285010111156125a957600080fd5b803561ffff811681146128e557600080fd5b919050565b6000602082840312156128fc57600080fd5b813561117081613046565b6000806040838503121561291a57600080fd5b823561292581613046565b946020939093013593505050565b60008060006060848603121561294857600080fd5b833561295381613046565b9250602084013561296381613046565b929592945050506040919091013590565b6000806040838503121561298757600080fd5b823561299281613046565b915060208301356129a28161305b565b809150509250929050565b600080602083850312156129c057600080fd5b823567ffffffffffffffff808211156129d857600080fd5b818501915085601f8301126129ec57600080fd5b8135818111156129fb57600080fd5b8660208260051b8501011115612a1057600080fd5b60209290920196919550909350505050565b60006020808385031215612a3557600080fd5b825167ffffffffffffffff80821115612a4d57600080fd5b818501915085601f830112612a6157600080fd5b815181811115612a7357612a73613030565b8060051b604051601f19603f83011681018181108582111715612a9857612a98613030565b604052828152858101935084860182860187018a1015612ab757600080fd5b600095505b83861015612ada578051855260019590950194938601938601612abc565b5098975050505050505050565b600060208284031215612af957600080fd5b81356111708161305b565b600060208284031215612b1657600080fd5b81516111708161305b565b600060208284031215612b3357600080fd5b5035919050565b600060208284031215612b4c57600080fd5b81356001600160e01b03198116811461117057600080fd5b60008060208385031215612b7757600080fd5b823567ffffffffffffffff811115612b8e57600080fd5b612b9a85828601612891565b90969095509350505050565b600060208284031215612bb857600080fd5b611170826128d3565b600080600080600060808688031215612bd957600080fd5b612be2866128d3565b945060208601359350604086013567ffffffffffffffff811115612c0557600080fd5b612c1188828901612891565b96999598509660600135949350505050565b600060208284031215612c3557600080fd5b5051919050565b600080600080600060a08688031215612c5457600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000825160005b81811015612c985760208186018101518583015201612c7e565b81811115612ca7576000828501525b509190910192915050565b6020808252825182820181905260009190848201906040850190845b81811015612cf35783516001600160a01b031683529284019291840191600101612cce565b50909695505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b602080825260129082015271151bdbc81b585b9e481c995c5d595cdd195960721b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600e908201526d416c72656164792061637469766560901b604082015260600190565b60208082526024908201527f41646d696e436f6e74726f6c3a204d757374206265206f776e6572206f7220616040820152633236b4b760e11b606082015260800190565b815161ffff1681526101e081016020830151612e1d602084018261ffff169052565b506040830151612e33604084018261ffff169052565b50606083015160608301526080830151612e53608084018261ffff169052565b5060a083015160a083015260c0830151612e7360c084018261ffff169052565b5060e0830151612e8960e084018261ffff169052565b506101008381015115159083015261012080840151908301526101408084015190830152610160808401519083015261018080840151908301526101a080840151908301526101c0928301511515929091019190915290565b600061ffff808316818516808303821115612eff57612eff612fd8565b01949350505050565b60008219821115612f1b57612f1b612fd8565b500190565b600082612f3d57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615612f5c57612f5c612fd8565b500290565b600061ffff83811690831681811015612f7c57612f7c612fd8565b039392505050565b600082821015612f9657612f96612fd8565b500390565b600061ffff80831681811415612fb357612fb3612fd8565b6001019392505050565b6000600019821415612fd157612fd1612fd8565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461096657600080fd5b801515811461096657600080fdfea2646970667358221220abc9b3c13ea0bb53b365445d0e384ca738adc8f9ad9dfae82f67c5cec1cd735564736f6c63430008070033000000000000000000000000677c46bd518e11bb35e69e0f7300b8ee932c7b270000000000000000000000007aab51a9668e0979481a4a5c18aa98a066484607
Deployed Bytecode
0x6080604052600436106102515760003560e01c8063715018a611610139578063a6a11bb1116100b6578063e59bb7a81161007a578063e59bb7a8146106a2578063f19605d6146106c2578063f2fde38b146106e4578063f3fef3a314610704578063f474307014610724578063fe73ad771461073f57600080fd5b8063a6a11bb11461061c578063c19d93fb14610632578063c8a84a8214610654578063defd6c5f14610676578063e3b9398b1461068c57600080fd5b806382580805116100fd5780638258080514610574578063850217d8146105945780638da5cb5b146105b4578063956447d8146105dc57806399e0dd7c146105fc57600080fd5b8063715018a6146104fd57806378e979251461051257806379070afa146105285780637f386b6c1461054857806381960b5c1461055e57600080fd5b806331ae450b116101d257806355461d6d1161019657806355461d6d1461042e57806361a4422b1461044e5780636741f24a1461047e5780636b9990dc146104915780636bb7b1d9146104c85780636d73e669146104dd57600080fd5b806331ae450b146103ab57806335e60bd4146103cd578063379ffdca146103ed57806340d1d2551461040357806351b42b001461041957600080fd5b80631b95a227116102195780631b95a2271461031157806324d7806c146103335780632b85ed9c146103535780632d345670146103755780633197cbb61461039557600080fd5b806301ffc9a71461025657806302fb0c5e1461028b57806312686aae146102a557806318886657146102bf5780631b4d21c8146102ed575b600080fd5b34801561026257600080fd5b50610276610271366004612b3a565b610754565b60405190151581526020015b60405180910390f35b34801561029757600080fd5b506002546102769060ff1681565b3480156102b157600080fd5b50600f546102769060ff1681565b3480156102cb57600080fd5b50600b546102da9061ffff1681565b60405161ffff9091168152602001610282565b3480156102f957600080fd5b5061030360115481565b604051908152602001610282565b34801561031d57600080fd5b5061033161032c366004612974565b61078e565b005b34801561033f57600080fd5b5061027661034e3660046128ea565b6108b0565b34801561035f57600080fd5b50600d546102da906301000000900461ffff1681565b34801561038157600080fd5b506103316103903660046128ea565b6108e9565b3480156103a157600080fd5b5061030360045481565b3480156103b757600080fd5b506103c0610969565b6040516102829190612cb2565b3480156103d957600080fd5b506103316103e8366004612ae7565b610a18565b3480156103f957600080fd5b5061030360125481565b34801561040f57600080fd5b5061030360075481565b34801561042557600080fd5b50610331610a73565b34801561043a57600080fd5b50600d546102769062010000900460ff1681565b34801561045a57600080fd5b50610276610469366004612b21565b60009081526001602052604090205460ff1690565b61033161048c366004612bc1565b610ac7565b34801561049d57600080fd5b506104a6610bb9565b6040805182518152602080840151908201529181015190820152606001610282565b3480156104d457600080fd5b50610303610c03565b3480156104e957600080fd5b506103316104f83660046128ea565b610c1a565b34801561050957600080fd5b50610331610c94565b34801561051e57600080fd5b5061030360035481565b34801561053457600080fd5b50610331610543366004612bc1565b610cc8565b34801561055457600080fd5b5061030360105481565b34801561056a57600080fd5b50610303600c5481565b34801561058057600080fd5b5061027661058f366004612933565b610d2b565b3480156105a057600080fd5b506103316105af366004612ba6565b610d3e565b3480156105c057600080fd5b506008546040516001600160a01b039091168152602001610282565b3480156105e857600080fd5b506103316105f7366004612c3c565b610da3565b34801561060857600080fd5b50610331610617366004612b64565b610e01565b34801561062857600080fd5b5061030360065481565b34801561063e57600080fd5b50610647610e55565b6040516102829190612dfb565b34801561066057600080fd5b506009546102da90600160b01b900461ffff1681565b34801561068257600080fd5b50610303600a5481565b34801561069857600080fd5b5061030360055481565b3480156106ae57600080fd5b506103316106bd3660046129ad565b610f9f565b3480156106ce57600080fd5b506009546102da90600160a01b900461ffff1681565b3480156106f057600080fd5b506103316106ff3660046128ea565b610ff3565b34801561071057600080fd5b5061033161071f366004612907565b61108b565b34801561073057600080fd5b50600d546102da9061ffff1681565b34801561074b57600080fd5b506102da6110df565b60006001600160e01b03198216634ce6d51160e11b1480610779575061077982611108565b8061078857506107888261112d565b92915050565b336107a16008546001600160a01b031690565b6001600160a01b031614806107bc57506107bc601433611152565b6107e15760405162461bcd60e51b81526004016107d890612db7565b60405180910390fd5b6107f282639088c20760e01b611177565b6108505760405162461bcd60e51b815260206004820152602960248201527f43726561746f72206d75737420696d706c656d656e74204945524337323143726044820152686561746f72436f726560b81b60648201526084016107d8565b604051635606467d60e11b815281151560048201526001600160a01b0383169063ac0c8cfa906024015b600060405180830381600087803b15801561089457600080fd5b505af11580156108a8573d6000803e3d6000fd5b505050505050565b6000816001600160a01b03166108ce6008546001600160a01b031690565b6001600160a01b031614806107885750610788601483611152565b6008546001600160a01b031633146109135760405162461bcd60e51b81526004016107d890612d5a565b61091e601482611152565b156109665760405133906001600160a01b038316907f7c0c3c84c67c85fcac635147348bfe374c24a1a93d0366d1cfe9d8853cbf89d590600090a3610964601482611193565b505b50565b606061097560146111a8565b67ffffffffffffffff81111561098d5761098d613030565b6040519080825280602002602001820160405280156109b6578160200160208202803683370190505b50905060005b6109c660146111a8565b811015610a14576109d86014826111b2565b8282815181106109ea576109ea61301a565b6001600160a01b039092166020928302919091019091015280610a0c81612fbd565b9150506109bc565b5090565b33610a2b6008546001600160a01b031690565b6001600160a01b03161480610a465750610a46601433611152565b610a625760405162461bcd60e51b81526004016107d890612db7565b600f805460ff191682151517905550565b33610a866008546001600160a01b031690565b6001600160a01b03161480610aa15750610aa1601433611152565b610abd5760405162461bcd60e51b81526004016107d890612db7565b610ac56111be565b565b60026013541415610b1a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107d8565b6002601355610b2c8585858585611207565b6000610b3c600c54600a54611505565b610b4a9061ffff8816612f42565b905080341115610bac57610b6733610b628334612f84565b61158f565b7f7fb144214d6945ccc22e755bd2fa1e65488d2c9d08af5f0a40a766426865f3ed34610b938382612f84565b6040805192835260208301919091520160405180910390a15b5050600160135550505050565b610bdd60405180606001604052806000815260200160008152602001600081525090565b604051806060016040528060105481526020016011548152602001601254815250905090565b6000600554600354610c159190612f08565b905090565b6008546001600160a01b03163314610c445760405162461bcd60e51b81526004016107d890612d5a565b610c4f601482611152565b6109665760405133906001600160a01b038316907f7e1a1a08d52e4ba0e21554733d66165fd5151f99460116223d9e3a608eec5cb190600090a36109646014826116ad565b6008546001600160a01b03163314610cbe5760405162461bcd60e51b81526004016107d890612d5a565b610ac560006116c2565b610cd0611714565b610cdd84848484896117a9565b610ce733866117b6565b336000908152600e602052604081208054879290610d0a90849061ffff16612ee2565b92506101000a81548161ffff021916908361ffff1602179055505050505050565b6000610d3684611a65565b949350505050565b33610d516008546001600160a01b031690565b6001600160a01b03161480610d6c5750610d6c601433611152565b610d885760405162461bcd60e51b81526004016107d890612db7565b61096681610d9e6008546001600160a01b031690565b611a85565b33610db66008546001600160a01b031690565b6001600160a01b03161480610dd15750610dd1601433611152565b610ded5760405162461bcd60e51b81526004016107d890612db7565b610dfa8585858585611ab2565b5050505050565b33610e146008546001600160a01b031690565b6001600160a01b03161480610e2f5750610e2f601433611152565b610e4b5760405162461bcd60e51b81526004016107d890612db7565b6109648282611c68565b604080516101e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c0810191909152604080516101e08101825260095461ffff600160a01b820481168352600160b01b909104166020820152908101610f036110df565b61ffff9081168252600a54602080840191909152600b548216604080850191909152600c546060850152600d548084166080860152336000908152600e90935291205490911660a083015260025460ff908116151560c084015260035460e08401526004546101008401526005546101208401526006546101408401526007546101608401526201000090910416151561018090910152919050565b33610fb26008546001600160a01b031690565b6001600160a01b03161480610fcd5750610fcd601433611152565b610fe95760405162461bcd60e51b81526004016107d890612db7565b6109648282611c9a565b6008546001600160a01b0316331461101d5760405162461bcd60e51b81526004016107d890612d5a565b6001600160a01b0381166110825760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016107d8565b610966816116c2565b3361109e6008546001600160a01b031690565b6001600160a01b031614806110b957506110b9601433611152565b6110d55760405162461bcd60e51b81526004016107d890612db7565b6109648282611d01565b600d54600954600091610c159161ffff6301000000909204821691600160b01b90910416612f61565b60006001600160e01b0319821663da192f9f60e01b1480610788575061078882611d61565b60006001600160e01b03198216632a9f3abf60e11b1480610788575061078882611108565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b600061118283611d96565b801561117057506111708383611dc9565b6000611170836001600160a01b038416611ea8565b6000610788825490565b60006111708383611f9b565b6000600381905560048190556002805460ff19169055600681905560078190556040517fb02389feab3af620e2374d4d559b436ea226b1e6c9c31fe77dfbff3d40cbe9ba9190a1565b61120f611fc5565b600061121961204c565b90506112236110df565b61ffff168661ffff161115801561127c575080801561124a5750600d5462010000900460ff165b806112605750600954600160a01b900461ffff16155b8061127c575060095461ffff600160a01b909104811690871611155b6112985760405162461bcd60e51b81526004016107d890612d2e565b801561140457600d5462010000900460ff1661138657600d5461ffff161561131a57336000908152600e6020526040902054600d5461ffff9182169116811080156112fc5750600d546112f090829061ffff16612f61565b61ffff168761ffff1611155b6113185760405162461bcd60e51b81526004016107d890612d2e565b505b600b5461ffff161561138657336000908152600e6020526040902054600b5461ffff9182169116811080156113685750600b5461135c90829061ffff16612f61565b61ffff168761ffff1611155b6113845760405162461bcd60e51b81526004016107d890612d2e565b505b61138f86612070565b600d5462010000900460ff161580156113bc5750600d5461ffff161515806113bc5750600b5461ffff1615155b156113ff57336000908152600e6020526040812080548892906113e490849061ffff16612ee2565b92506101000a81548161ffff021916908361ffff1602179055505b6114c3565b600b5461ffff161561147057336000908152600e6020526040902054600b5461ffff9182169116811080156114525750600b5461144690829061ffff16612f61565b61ffff168761ffff1611155b61146e5760405162461bcd60e51b81526004016107d890612d2e565b505b611479866120cf565b600b5461ffff16156114c357336000908152600e6020526040812080548892906114a890849061ffff16612ee2565b92506101000a81548161ffff021916908361ffff1602179055505b8080156114d85750600d5462010000900460ff165b156114ef576114ea858585858a61213a565b6114fb565b6114fb8585858561230e565b6108a833876117b6565b600061150f61204c565b1561151b575081610788565b6000611525610c03565b61152f9042612f84565b90506000601254601154836115449190612f20565b61154e9190612f42565b9050838111156115645760105492505050610788565b60006115708286612f84565b9050601054811161158357601054611585565b805b9695505050505050565b804710156115df5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016107d8565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461162c576040519150601f19603f3d011682016040523d82523d6000602084013e611631565b606091505b50509050806116a85760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016107d8565b505050565b6000611170836001600160a01b0384166124cd565b600880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60025460ff166117515760405162461bcd60e51b8152602060048201526008602482015267496e61637469766560c01b60448201526064016107d8565b600654421015801561176557506007544211155b610ac55760405162461bcd60e51b815260206004820152601560248201527427baba39b4b2329031b630b4b6903832b934b7b21760591b60448201526064016107d8565b610dfa858585858561213a565b8061ffff16600114156118df57600d80546301000000900461ffff169060036117de83612f9b565b825461ffff9182166101009390930a928302919092021990911617905550600954604051630525194b60e31b81526001600160a01b0384811660048301526000921690632928ca5890602401602060405180830381600087803b15801561184457600080fd5b505af1158015611858573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061187c9190612c23565b600d5460095460408051630100000090930461ffff1683526001600160a01b03909116602083015281018290529091507f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba39060600160405180910390a150610964565b600d546000906118fb906301000000900461ffff166001612ee2565b600d805461ffff9283169350849260039161191f9185916301000000900416612ee2565b82546101009290920a61ffff81810219909316918316021790915560095460405163e00aab4b60e01b81526001600160a01b03878116600483015292861660248201526000935091169063e00aab4b90604401600060405180830381600087803b15801561198c57600080fd5b505af11580156119a0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526119c89190810190612a22565b905060005b8151811015610dfa577f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba3611a018285612f08565b60095484516001600160a01b0390911690859085908110611a2457611a2461301a565b6020026020010151604051611a55939291909283526001600160a01b03919091166020830152604082015260600190565b60405180910390a16001016119cd565b60006001600160a01b03821615806107885750600f5460ff161592915050565b60025460ff1615611aa85760405162461bcd60e51b81526004016107d890612d8f565b61096481836117b6565b60025460ff1615611ad55760405162461bcd60e51b81526004016107d890612d8f565b428511611b245760405162461bcd60e51b815260206004820152601b60248201527f43616e6e6f7420616374697661746520696e207468652070617374000000000060448201526064016107d8565b83831115611b8c5760405162461bcd60e51b815260206004820152602f60248201527f50726573616c6520496e74657276616c2063616e6e6f74206265206c6f6e676560448201526e72207468616e207468652073616c6560881b60648201526084016107d8565b808211158015611b9c5750848111155b611bde5760405162461bcd60e51b8152602060048201526013602482015272496e76616c696420636c61696d2074696d657360681b60448201526064016107d8565b6003859055611bed8486612f08565b60048190556005849055600683905560078290556002805460ff1916600117905560035460408051918252602082019290925290810184905260608101839052608081018290527fe512d106f8172b08abfd2fc5ddfdb7e2401381780ae29e29f1352b862f1d27319060a00160405180910390a15050505050565b6009546040516307cc269760e31b81526001600160a01b0390911690633e6134b89061087a9085908590600401612cff565b60025460ff1615611cbd5760405162461bcd60e51b81526004016107d890612d8f565b60005b818110156116a857611cf9838383818110611cdd57611cdd61301a565b9050602002016020810190611cf291906128ea565b60016117b6565b600101611cc0565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611d4e576040519150601f19603f3d011682016040523d82523d6000602084013e611d53565b606091505b50509050806116a857600080fd5b60006001600160e01b03198216637005caad60e01b148061078857506301ffc9a760e01b6001600160e01b0319831614610788565b6000611da9826301ffc9a760e01b611dc9565b80156107885750611dc2826001600160e01b0319611dc9565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b0387169061753090611e30908690612c77565b6000604051808303818686fa925050503d8060008114611e6c576040519150601f19603f3d011682016040523d82523d6000602084013e611e71565b606091505b5091509150602081511015611e8c5760009350505050610788565b8180156115855750808060200190518101906115859190612b04565b60008181526001830160205260408120548015611f91576000611ecc600183612f84565b8554909150600090611ee090600190612f84565b9050818114611f45576000866000018281548110611f0057611f0061301a565b9060005260206000200154905080876000018481548110611f2357611f2361301a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611f5657611f56613004565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610788565b6000915050610788565b6000826000018281548110611fb257611fb261301a565b9060005260206000200154905092915050565b60025460ff166120025760405162461bcd60e51b8152602060048201526008602482015267496e61637469766560c01b60448201526064016107d8565b600354421015610ac55760405162461bcd60e51b815260206004820152601560248201527450757263686173696e67206e6f742061637469766560581b60448201526064016107d8565b600060035442118015610c15575060055460035461206a9042612f84565b10905090565b600c546120819061ffff8316612f42565b34146109665760405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420707572636861736520616d6f756e742073656e740000000060448201526064016107d8565b6120dd600c54600a54611505565b6120eb9061ffff8316612f42565b3410156109665760405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420707572636861736520616d6f756e742073656e740000000060448201526064016107d8565b60008281526001602052604090205460ff16156121955760405162461bcd60e51b815260206004820152601960248201527821b0b73737ba103932b83630bc903a3930b739b0b1ba34b7b760391b60448201526064016107d8565b6040517f19457468657265756d205369676e6564204d6573736167653a0a35340000000060208201526bffffffffffffffffffffffff193360601b16603c820152605081018390526001600160f01b031960f083901b1660708201526000906072016040516020818303038152906040528051906020012090508086146122525760405162461bcd60e51b81526020600482015260116024820152704d616c666f726d6564206d65737361676560781b60448201526064016107d8565b600061229686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b9392505061251c9050565b6000549091506001600160a01b038083169116146122ea5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b60448201526064016107d8565b5050506000908152600160208190526040909120805460ff19169091179055505050565b60008181526001602052604090205460ff16156123695760405162461bcd60e51b815260206004820152601960248201527821b0b73737ba103932b83630bc903a3930b739b0b1ba34b7b760391b60448201526064016107d8565b6040517f19457468657265756d205369676e6564204d6573736167653a0a35320000000060208201526bffffffffffffffffffffffff193360601b16603c820152605081018290526000906070016040516020818303038152906040528051906020012090508085146124125760405162461bcd60e51b81526020600482015260116024820152704d616c666f726d6564206d65737361676560781b60448201526064016107d8565b600061245685858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9392505061251c9050565b6000549091506001600160a01b038083169116146124aa5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b60448201526064016107d8565b50506000908152600160208190526040909120805460ff19169091179055505050565b600081815260018301602052604081205461251457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610788565b506000610788565b600080600061252b8585612540565b91509150612538816125b0565b509392505050565b6000808251604114156125775760208301516040840151606085015160001a61256b8782858561276b565b945094505050506125a9565b8251604014156125a15760208301516040840151612596868383612858565b9350935050506125a9565b506000905060025b9250929050565b60008160048111156125c4576125c4612fee565b14156125cd5750565b60018160048111156125e1576125e1612fee565b141561262f5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016107d8565b600281600481111561264357612643612fee565b14156126915760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016107d8565b60038160048111156126a5576126a5612fee565b14156126fe5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016107d8565b600481600481111561271257612712612fee565b14156109665760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b60648201526084016107d8565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156127a2575060009050600361284f565b8460ff16601b141580156127ba57508460ff16601c14155b156127cb575060009050600461284f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561281f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166128485760006001925092505061284f565b9150600090505b94509492505050565b6000806001600160ff1b0383168161287560ff86901c601b612f08565b90506128838782888561276b565b935093505050935093915050565b60008083601f8401126128a357600080fd5b50813567ffffffffffffffff8111156128bb57600080fd5b6020830191508360208285010111156125a957600080fd5b803561ffff811681146128e557600080fd5b919050565b6000602082840312156128fc57600080fd5b813561117081613046565b6000806040838503121561291a57600080fd5b823561292581613046565b946020939093013593505050565b60008060006060848603121561294857600080fd5b833561295381613046565b9250602084013561296381613046565b929592945050506040919091013590565b6000806040838503121561298757600080fd5b823561299281613046565b915060208301356129a28161305b565b809150509250929050565b600080602083850312156129c057600080fd5b823567ffffffffffffffff808211156129d857600080fd5b818501915085601f8301126129ec57600080fd5b8135818111156129fb57600080fd5b8660208260051b8501011115612a1057600080fd5b60209290920196919550909350505050565b60006020808385031215612a3557600080fd5b825167ffffffffffffffff80821115612a4d57600080fd5b818501915085601f830112612a6157600080fd5b815181811115612a7357612a73613030565b8060051b604051601f19603f83011681018181108582111715612a9857612a98613030565b604052828152858101935084860182860187018a1015612ab757600080fd5b600095505b83861015612ada578051855260019590950194938601938601612abc565b5098975050505050505050565b600060208284031215612af957600080fd5b81356111708161305b565b600060208284031215612b1657600080fd5b81516111708161305b565b600060208284031215612b3357600080fd5b5035919050565b600060208284031215612b4c57600080fd5b81356001600160e01b03198116811461117057600080fd5b60008060208385031215612b7757600080fd5b823567ffffffffffffffff811115612b8e57600080fd5b612b9a85828601612891565b90969095509350505050565b600060208284031215612bb857600080fd5b611170826128d3565b600080600080600060808688031215612bd957600080fd5b612be2866128d3565b945060208601359350604086013567ffffffffffffffff811115612c0557600080fd5b612c1188828901612891565b96999598509660600135949350505050565b600060208284031215612c3557600080fd5b5051919050565b600080600080600060a08688031215612c5457600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000825160005b81811015612c985760208186018101518583015201612c7e565b81811115612ca7576000828501525b509190910192915050565b6020808252825182820181905260009190848201906040850190845b81811015612cf35783516001600160a01b031683529284019291840191600101612cce565b50909695505050505050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b602080825260129082015271151bdbc81b585b9e481c995c5d595cdd195960721b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252600e908201526d416c72656164792061637469766560901b604082015260600190565b60208082526024908201527f41646d696e436f6e74726f6c3a204d757374206265206f776e6572206f7220616040820152633236b4b760e11b606082015260800190565b815161ffff1681526101e081016020830151612e1d602084018261ffff169052565b506040830151612e33604084018261ffff169052565b50606083015160608301526080830151612e53608084018261ffff169052565b5060a083015160a083015260c0830151612e7360c084018261ffff169052565b5060e0830151612e8960e084018261ffff169052565b506101008381015115159083015261012080840151908301526101408084015190830152610160808401519083015261018080840151908301526101a080840151908301526101c0928301511515929091019190915290565b600061ffff808316818516808303821115612eff57612eff612fd8565b01949350505050565b60008219821115612f1b57612f1b612fd8565b500190565b600082612f3d57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615612f5c57612f5c612fd8565b500290565b600061ffff83811690831681811015612f7c57612f7c612fd8565b039392505050565b600082821015612f9657612f96612fd8565b500390565b600061ffff80831681811415612fb357612fb3612fd8565b6001019392505050565b6000600019821415612fd157612fd1612fd8565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461096657600080fd5b801515811461096657600080fdfea2646970667358221220abc9b3c13ea0bb53b365445d0e384ca738adc8f9ad9dfae82f67c5cec1cd735564736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000677c46bd518e11bb35e69e0f7300b8ee932c7b270000000000000000000000007aab51a9668e0979481a4a5c18aa98a066484607
-----Decoded View---------------
Arg [0] : creatorAddress (address): 0x677C46bd518e11bB35E69E0f7300B8eE932c7b27
Arg [1] : signingAddress (address): 0x7aAb51A9668e0979481A4A5c18Aa98A066484607
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000677c46bd518e11bb35e69e0f7300b8ee932c7b27
Arg [1] : 0000000000000000000000007aab51a9668e0979481a4a5c18aa98a066484607
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.