// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import {ERC721} from "https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol";
import {Owned} from "https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol";
import {LibString} from "https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol";
import {SafeTransferLib} from "https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol";
//////////////////////////////////////////////////////
// //
// //
// ██████████████████████████████████████████ //
// █ █ //
// █ █ //
// █ █ //
// █ █ //
// █ __________ ___________ __ █ //
// █ / ____/ __ \/_ __/ __(_)__ ____/ / █ //
// █ / / / /_/ / / / / /_/ / _ \/ __ / █ //
// █ / /___/ _, _/ / / / __/ / __/ /_/ / █ //
// █ \____/_/ |_| /_/ /_/ /_/\___/\__,_/ █ //
// █ █ //
// █ █ //
// █ █ //
// █ █ //
// ██████████████████████████████████████████ //
// ████████████████░░░░░░░░░█████████████████ //
// ██████████████████████████████████████████ //
// ███■█■███■█■█████████████ ■ █ ■ ████■■■■██ //
// ██████████████████████████████████████████ //
// //
// //
//////////////////////////////////////////////////////
interface CRTfiedOpenEdition {
function balanceOf(address _owner) external view returns (uint256);
}
contract CRTfied is ERC721, Owned {
/* -------------------------------------------------------------------------- */
/* CONSTANTS */
/* -------------------------------------------------------------------------- */
CRTfiedOpenEdition private crtOpenEdition =
CRTfiedOpenEdition(0x301254AA648cF7C0B51aDDcd5d208ef5De0e4D5d);
uint256 public constant MAX_SUPPLY = 480;
uint256 public constant MAX_PER_MINT = 4;
uint256 public price = 0.07 ether;
bool public mintEnabled = true;
bool public publicMintEnabled = false;
/* -------------------------------------------------------------------------- */
/* DATA */
/* -------------------------------------------------------------------------- */
string private _baseURI;
address private _dev;
address private _owner1;
address private _owner2;
uint256 public totalSupply = 0;
mapping(address => bool) public allowList;
/* -------------------------------------------------------------------------- */
/* EVENTS & ERRORS */
/* -------------------------------------------------------------------------- */
error NotAllowed();
error NotCurrentDev();
error NotCurrentOwner();
error InvalidMintAmount();
error TooManyPerMint();
error NotEnoughTokens();
error InvalidMintFee();
/* -------------------------------------------------------------------------- */
/* INIT */
/* -------------------------------------------------------------------------- */
constructor(string memory baseURI, address dev, address owner1, address owner2) ERC721("CRTfied", "CRTFIED") Owned(msg.sender) {
_baseURI = baseURI;
_dev = dev;
_owner1 = owner1;
_owner2 = owner2;
}
/* -------------------------------------------------------------------------- */
/* MINTING */
/* -------------------------------------------------------------------------- */
function mint(uint256 amount) external payable {
if (amount <= 0) revert InvalidMintAmount();
if (amount > MAX_PER_MINT) revert TooManyPerMint();
if (msg.value != amount * price) revert InvalidMintFee();
// if not in public mint, run some checks
if (!publicMintEnabled) {
// revert if sender has no OE and is not on allowlist
if (crtOpenEdition.balanceOf(msg.sender) == 0 && !allowList[msg.sender]) {
revert NotAllowed();
}
}
if (totalSupply + amount > MAX_SUPPLY) revert NotEnoughTokens();
for (uint256 i = 0; i < amount; i++) {
uint256 tokenId = totalSupply + 1;
_mint(msg.sender, tokenId);
totalSupply++;
}
}
/* -------------------------------------------------------------------------- */
/* METADATA */
/* -------------------------------------------------------------------------- */
function tokenURI(uint256 tokenId)
public
view
override
returns (string memory)
{
return string.concat(_baseURI, LibString.toString(tokenId));
}
/* -------------------------------------------------------------------------- */
/* ADMIN */
/* -------------------------------------------------------------------------- */
function withdraw() external {
if (msg.sender != _dev && msg.sender != _owner1 && msg.sender != _owner2) {
revert NotAllowed();
}
uint devCut = address(this).balance * 75/1000;
uint ownerCut = (address(this).balance - devCut) / 2;
SafeTransferLib.safeTransferETH(_dev, devCut);
SafeTransferLib.safeTransferETH(_owner1, ownerCut);
SafeTransferLib.safeTransferETH(_owner2, ownerCut);
}
function setDevAddress(address newDev) external {
if (msg.sender != _dev) revert NotCurrentDev();
_dev = newDev;
}
function setOwner1Address(address newOwner) external {
if (msg.sender != _owner1) revert NotCurrentOwner();
_owner1 = newOwner;
}
function setOwner2Address(address newOwner) external {
if (msg.sender != _owner2) revert NotCurrentOwner();
_owner2 = newOwner;
}
function setBaseURI(string calldata newURI) external onlyOwner {
_baseURI = newURI;
}
function setMintPrice(uint256 newPrice) external onlyOwner {
price = newPrice;
}
function setPublicMintEnabled(bool newState) external onlyOwner {
publicMintEnabled = newState;
}
function setMintEnabled(bool newState) external onlyOwner {
mintEnabled = newState;
}
function setOpenEditionAddress(address newAddress) external onlyOwner {
crtOpenEdition = CRTfiedOpenEdition(newAddress);
}
function addAllowList(address[] calldata addresses) external onlyOwner {
for (uint i = 0; i < addresses.length; i++) {
allowList[addresses[i]] = true;
}
}
}
{
"compilationTarget": {
"CRTfied.sol": "CRTfied"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"address","name":"dev","type":"address"},{"internalType":"address","name":"owner1","type":"address"},{"internalType":"address","name":"owner2","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidMintAmount","type":"error"},{"inputs":[],"name":"InvalidMintFee","type":"error"},{"inputs":[],"name":"NotAllowed","type":"error"},{"inputs":[],"name":"NotCurrentDev","type":"error"},{"inputs":[],"name":"NotCurrentOwner","type":"error"},{"inputs":[],"name":"NotEnoughTokens","type":"error"},{"inputs":[],"name":"TooManyPerMint","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"MAX_PER_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"name":"addAllowList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"allowList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicMintEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newDev","type":"address"}],"name":"setDevAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"newState","type":"bool"}],"name":"setMintEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setMintPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"setOpenEditionAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner1Address","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner2Address","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"newState","type":"bool"}],"name":"setPublicMintEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]