文件 1 的 5:IFilteredMinterV0.sol
pragma solidity ^0.8.0;
interface IFilteredMinterV0 {
event PricePerTokenInWeiUpdated(
uint256 indexed _projectId,
uint256 indexed _pricePerTokenInWei
);
event ProjectCurrencyInfoUpdated(
uint256 indexed _projectId,
address indexed _currencyAddress,
string _currencySymbol
);
event PurchaseToDisabledUpdated(
uint256 indexed _projectId,
bool _purchaseToDisabled
);
function minterType() external view returns (string memory);
function genArt721CoreAddress() external returns (address);
function minterFilterAddress() external returns (address);
function purchase(uint256 _projectId)
external
payable
returns (uint256 tokenId);
function purchaseTo(address _to, uint256 _projectId)
external
payable
returns (uint256 tokenId);
function togglePurchaseToDisabled(uint256 _projectId) external;
function setProjectMaxInvocations(uint256 _projectId) external;
function getPriceInfo(uint256 _projectId)
external
view
returns (
bool isConfigured,
uint256 tokenPriceInWei,
string memory currencySymbol,
address currencyAddress
);
}
文件 2 的 5:IGenArt721CoreContractV1.sol
pragma solidity ^0.8.0;
interface IGenArt721CoreContractV1 {
event Mint(
address indexed _to,
uint256 indexed _tokenId,
uint256 indexed _projectId
);
function admin() external view returns (address);
function nextProjectId() external view returns (uint256);
function tokenIdToProjectId(uint256 tokenId)
external
view
returns (uint256 projectId);
function isWhitelisted(address sender) external view returns (bool);
function isMintWhitelisted(address minter) external view returns (bool);
function projectIdToArtistAddress(uint256 _projectId)
external
view
returns (address payable);
function projectIdToAdditionalPayee(uint256 _projectId)
external
view
returns (address payable);
function projectIdToAdditionalPayeePercentage(uint256 _projectId)
external
view
returns (uint256);
function projectTokenInfo(uint256 _projectId)
external
view
returns (
address,
uint256,
uint256,
uint256,
bool,
address,
uint256,
string memory,
address
);
function artblocksAddress() external view returns (address payable);
function artblocksPercentage() external view returns (uint256);
function mint(
address _to,
uint256 _projectId,
address _by
) external returns (uint256 tokenId);
function getRoyaltyData(uint256 _tokenId)
external
view
returns (
address artistAddress,
address additionalPayee,
uint256 additionalPayeePercentage,
uint256 royaltyFeeByID
);
}
文件 3 的 5:IMinterFilterV0.sol
pragma solidity ^0.8.0;
interface IMinterFilterV0 {
event MinterApproved(address indexed _minterAddress, string _minterType);
event MinterRevoked(address indexed _minterAddress);
event ProjectMinterRegistered(
uint256 indexed _projectId,
address indexed _minterAddress,
string _minterType
);
event ProjectMinterRemoved(uint256 indexed _projectId);
function genArt721CoreAddress() external returns (address);
function setMinterForProject(uint256, address) external;
function removeMinterForProject(uint256) external;
function mint(
address _to,
uint256 _projectId,
address sender
) external returns (uint256);
function getMinterForProject(uint256) external view returns (address);
function projectHasMinter(uint256) external view returns (bool);
}
文件 4 的 5:MinterSetPriceV0.sol
import "../interfaces/0.8.x/IGenArt721CoreContractV1.sol";
import "../interfaces/0.8.x/IMinterFilterV0.sol";
import "../interfaces/0.8.x/IFilteredMinterV0.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
pragma solidity 0.8.9;
contract MinterSetPriceV0 is ReentrancyGuard, IFilteredMinterV0 {
address public immutable genArt721CoreAddress;
IGenArt721CoreContractV1 private immutable genArtCoreContract;
address public immutable minterFilterAddress;
IMinterFilterV0 private immutable minterFilter;
string public constant minterType = "MinterSetPriceV0";
uint256 constant ONE_MILLION = 1_000_000;
mapping(uint256 => bool) public contractMintable;
mapping(uint256 => bool) public purchaseToDisabled;
mapping(address => mapping(uint256 => uint256)) public projectMintCounter;
mapping(uint256 => uint256) public projectMintLimit;
mapping(uint256 => bool) public projectMaxHasBeenInvoked;
mapping(uint256 => uint256) public projectMaxInvocations;
mapping(uint256 => uint256) private projectIdToPricePerTokenInWei;
mapping(uint256 => bool) private projectIdToPriceIsConfigured;
modifier onlyCoreWhitelisted() {
require(
genArtCoreContract.isWhitelisted(msg.sender),
"Only Core whitelisted"
);
_;
}
modifier onlyArtist(uint256 _projectId) {
require(
msg.sender ==
genArtCoreContract.projectIdToArtistAddress(_projectId),
"Only Artist"
);
_;
}
constructor(address _genArt721Address, address _minterFilter)
ReentrancyGuard()
{
genArt721CoreAddress = _genArt721Address;
genArtCoreContract = IGenArt721CoreContractV1(_genArt721Address);
minterFilterAddress = _minterFilter;
minterFilter = IMinterFilterV0(_minterFilter);
require(
minterFilter.genArt721CoreAddress() == _genArt721Address,
"Illegal contract pairing"
);
}
function setProjectMintLimit(uint256 _projectId, uint8 _limit)
external
onlyCoreWhitelisted
{
projectMintLimit[_projectId] = _limit;
}
function setProjectMaxInvocations(uint256 _projectId)
external
onlyCoreWhitelisted
{
uint256 invocations;
uint256 maxInvocations;
(, , invocations, maxInvocations, , , , , ) = genArtCoreContract
.projectTokenInfo(_projectId);
projectMaxInvocations[_projectId] = maxInvocations;
if (invocations < maxInvocations) {
projectMaxHasBeenInvoked[_projectId] = false;
}
}
function toggleContractMintable(uint256 _projectId)
external
onlyCoreWhitelisted
{
contractMintable[_projectId] = !contractMintable[_projectId];
}
function togglePurchaseToDisabled(uint256 _projectId)
external
onlyCoreWhitelisted
{
purchaseToDisabled[_projectId] = !purchaseToDisabled[_projectId];
emit PurchaseToDisabledUpdated(
_projectId,
purchaseToDisabled[_projectId]
);
}
function updatePricePerTokenInWei(
uint256 _projectId,
uint256 _pricePerTokenInWei
) external onlyArtist(_projectId) {
projectIdToPricePerTokenInWei[_projectId] = _pricePerTokenInWei;
projectIdToPriceIsConfigured[_projectId] = true;
emit PricePerTokenInWeiUpdated(_projectId, _pricePerTokenInWei);
}
function purchase(uint256 _projectId)
external
payable
returns (uint256 tokenId)
{
tokenId = purchaseTo(msg.sender, _projectId);
return tokenId;
}
function purchaseTo(address _to, uint256 _projectId)
public
payable
nonReentrant
returns (uint256 tokenId)
{
require(
!projectMaxHasBeenInvoked[_projectId],
"Maximum number of invocations reached"
);
require(
projectIdToPriceIsConfigured[_projectId],
"Price not configured"
);
if (!contractMintable[_projectId]) {
require(msg.sender == tx.origin, "No Contract Buys");
}
if (purchaseToDisabled[_projectId]) {
require(msg.sender == _to, "No `purchaseTo` Allowed");
}
require(
msg.value >= projectIdToPricePerTokenInWei[_projectId],
"Must send minimum value to mint!"
);
if (projectMintLimit[_projectId] > 0) {
require(
projectMintCounter[msg.sender][_projectId] <
projectMintLimit[_projectId],
"Reached minting limit"
);
projectMintCounter[msg.sender][_projectId]++;
}
tokenId = minterFilter.mint(_to, _projectId, msg.sender);
if (
projectMaxInvocations[_projectId] > 0 &&
tokenId % ONE_MILLION == projectMaxInvocations[_projectId] - 1
) {
projectMaxHasBeenInvoked[_projectId] = true;
}
_splitFundsETH(_projectId);
return tokenId;
}
function _splitFundsETH(uint256 _projectId) internal {
if (msg.value > 0) {
uint256 pricePerTokenInWei = projectIdToPricePerTokenInWei[
_projectId
];
uint256 refund = msg.value - pricePerTokenInWei;
if (refund > 0) {
(bool success_, ) = msg.sender.call{value: refund}("");
require(success_, "Refund failed");
}
uint256 foundationAmount = (pricePerTokenInWei *
genArtCoreContract.artblocksPercentage()) / 100;
if (foundationAmount > 0) {
(bool success_, ) = genArtCoreContract.artblocksAddress().call{
value: foundationAmount
}("");
require(success_, "Foundation payment failed");
}
uint256 projectFunds = pricePerTokenInWei - foundationAmount;
uint256 additionalPayeeAmount;
if (
genArtCoreContract.projectIdToAdditionalPayeePercentage(
_projectId
) > 0
) {
additionalPayeeAmount =
(projectFunds *
genArtCoreContract.projectIdToAdditionalPayeePercentage(
_projectId
)) /
100;
if (additionalPayeeAmount > 0) {
(bool success_, ) = genArtCoreContract
.projectIdToAdditionalPayee(_projectId)
.call{value: additionalPayeeAmount}("");
require(success_, "Additional payment failed");
}
}
uint256 creatorFunds = projectFunds - additionalPayeeAmount;
if (creatorFunds > 0) {
(bool success_, ) = genArtCoreContract
.projectIdToArtistAddress(_projectId)
.call{value: creatorFunds}("");
require(success_, "Artist payment failed");
}
}
}
function getPriceInfo(uint256 _projectId)
external
view
returns (
bool isConfigured,
uint256 tokenPriceInWei,
string memory currencySymbol,
address currencyAddress
)
{
isConfigured = projectIdToPriceIsConfigured[_projectId];
tokenPriceInWei = projectIdToPricePerTokenInWei[_projectId];
currencySymbol = "ETH";
currencyAddress = address(0);
}
}
文件 5 的 5:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
{
"compilationTarget": {
"contracts/minter-suite/MinterSetPriceV0.sol": "MinterSetPriceV0"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 100
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_genArt721Address","type":"address"},{"internalType":"address","name":"_minterFilter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_pricePerTokenInWei","type":"uint256"}],"name":"PricePerTokenInWeiUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_currencyAddress","type":"address"},{"indexed":false,"internalType":"string","name":"_currencySymbol","type":"string"}],"name":"ProjectCurrencyInfoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_projectId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_purchaseToDisabled","type":"bool"}],"name":"PurchaseToDisabledUpdated","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"contractMintable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"genArt721CoreAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"getPriceInfo","outputs":[{"internalType":"bool","name":"isConfigured","type":"bool"},{"internalType":"uint256","name":"tokenPriceInWei","type":"uint256"},{"internalType":"string","name":"currencySymbol","type":"string"},{"internalType":"address","name":"currencyAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterFilterAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minterType","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"projectMaxHasBeenInvoked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"projectMaxInvocations","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"projectMintCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"projectMintLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"purchase","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"purchaseTo","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"purchaseToDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"setProjectMaxInvocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint8","name":"_limit","type":"uint8"}],"name":"setProjectMintLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"toggleContractMintable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"}],"name":"togglePurchaseToDisabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_projectId","type":"uint256"},{"internalType":"uint256","name":"_pricePerTokenInWei","type":"uint256"}],"name":"updatePricePerTokenInWei","outputs":[],"stateMutability":"nonpayable","type":"function"}]