Skip to content

Commit

Permalink
mitigation: change feeRecipient to immutable and add min fee (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xble authored Aug 12, 2024
1 parent cd465c0 commit 0fc9646
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 56 deletions.
27 changes: 13 additions & 14 deletions src/NFTMint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ contract NFTMint is Ownable {
error NFTMint_InvalidPerWalletLimit();
error NFTMint_InvalidMaxMints();
error NFTMint_InvalidOwner();
error NFTMint_InvalidFeeRecipient();
error NFTMint_InsufficientFee();

event MintCreated(MintERC1155 indexed mint, MintArgs args);
event OrderPlaced(
Expand All @@ -38,8 +38,6 @@ contract NFTMint is Ownable {
uint96 feePerMint;
// Address of the owner of the mint
address payable owner;
// Address to receive the fee
address payable feeRecipient;
// Timestamp when the mint expires
uint40 mintExpiration;
// Merkle root for the allowlist
Expand Down Expand Up @@ -72,8 +70,6 @@ contract NFTMint is Ownable {
uint32 perWalletLimit;
// Timestamp when the mint expires
uint40 mintExpiration;
// Address to receive the fee
address payable feeRecipient;
// Merkle root for the allowlist
bytes32 allowlistMerkleRoot;
// Mapping of addresses to the number of mints they have made
Expand Down Expand Up @@ -103,8 +99,15 @@ contract NFTMint is Ownable {
/// @notice Array of all orders placed. Filled orders are deleted.
Order[] public orders;

constructor(address owner_) Ownable(owner_) {
/// @notice Address of the mint fee recipient
address payable public immutable FEE_RECIPIENT;

/// @notice Minimum fee per mint (approximately $0.05)
uint96 public constant MIN_FEE_PER_MINT = 0.00002 ether;

constructor(address owner_, address feeRecipient_) Ownable(owner_) {
MINT_NFT_LOGIC = address(new MintERC1155(address(this)));
FEE_RECIPIENT = payable(feeRecipient_);
}

/**
Expand All @@ -124,8 +127,8 @@ contract NFTMint is Ownable {
if (args.owner == address(0)) {
revert NFTMint_InvalidOwner();
}
if (args.feeRecipient == address(0) && args.feePerMint != 0) {
revert NFTMint_InvalidFeeRecipient();
if (args.feePerMint < MIN_FEE_PER_MINT) {
revert NFTMint_InsufficientFee();

Check warning on line 131 in src/NFTMint.sol

View check run for this annotation

Codecov / codecov/patch

src/NFTMint.sol#L131

Added line #L131 was not covered by tests
}

MintERC1155 newMint = MintERC1155(
Expand All @@ -139,7 +142,6 @@ contract NFTMint is Ownable {
mintInfo.remainingMints = args.maxMints;
mintInfo.pricePerMint = args.pricePerMint;
mintInfo.feePerMint = args.feePerMint;
mintInfo.feeRecipient = args.feeRecipient;
mintInfo.perWalletLimit = args.perWalletLimit;
mintInfo.allowlistMerkleRoot = args.allowlistMerkleRoot;
mintInfo.mintExpiration = args.mintExpiration;
Expand Down Expand Up @@ -203,11 +205,8 @@ contract NFTMint is Ownable {
);

{
bool feeSuccess = true;
if (mintInfo.feePerMint > 0) {
(feeSuccess,) =
mintInfo.feeRecipient.call{ value: mintInfo.feePerMint * modifiedAmount, gas: 100_000 }("");
}
(bool feeSuccess,) = FEE_RECIPIENT.call{ value: mintInfo.feePerMint * modifiedAmount, gas: 100_000 }("");

bool mintProceedsSuccess = true;
if (mintInfo.pricePerMint > 0) {
(mintProceedsSuccess,) =
Expand Down
46 changes: 4 additions & 42 deletions test/NFTMint.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import { MockFailingRecipient } from "./util/MockFailingRecipient.sol";

contract NFTMintTest is TestBase {
NFTMint nftMint;
address feeRecipient = vm.createWallet("feeRecipient").addr;

function setUp() external {
nftMint = new NFTMint(address(this));
nftMint = new NFTMint(address(this), feeRecipient);
}

function test_createMint() public returns (MintERC1155) {
Expand Down Expand Up @@ -47,7 +48,6 @@ contract NFTMintTest is TestBase {
perWalletLimit: 105,
feePerMint: 0.001 ether,
owner: payable(address(this)),
feeRecipient: payable(address(this)),
name: "My Token Name",
imageURI: "image here",
description: "This is a description",
Expand Down Expand Up @@ -78,7 +78,6 @@ contract NFTMintTest is TestBase {
perWalletLimit: 105,
feePerMint: 0.001 ether,
owner: payable(address(this)),
feeRecipient: payable(address(this)),
name: "My Token Name",
imageURI: "image here",
description: "This is a description",
Expand Down Expand Up @@ -110,7 +109,6 @@ contract NFTMintTest is TestBase {
perWalletLimit: 0,
feePerMint: 0.001 ether,
owner: payable(address(this)),
feeRecipient: payable(address(this)),
name: "My Token Name",
imageURI: "image here",
description: "This is a description",
Expand Down Expand Up @@ -142,7 +140,6 @@ contract NFTMintTest is TestBase {
perWalletLimit: 1,
feePerMint: 0.001 ether,
owner: payable(address(this)),
feeRecipient: payable(address(this)),
name: "My Token Name",
imageURI: "image here",
description: "This is a description",
Expand Down Expand Up @@ -174,7 +171,6 @@ contract NFTMintTest is TestBase {
perWalletLimit: 1,
feePerMint: 0.001 ether,
owner: payable(address(0)),
feeRecipient: payable(address(this)),
name: "My Token Name",
imageURI: "image here",
description: "This is a description",
Expand All @@ -185,38 +181,6 @@ contract NFTMintTest is TestBase {
nftMint.createMint(mintArgs);
}

function test_createMint_invalidFeeRecipient() external {
MintERC1155.Attribute[] memory attributes = new MintERC1155.Attribute[](1);
attributes[0] = MintERC1155.Attribute({ traitType: "traitType", value: "value" });

MintERC1155.Edition[] memory editions = new MintERC1155.Edition[](1);
editions[0] = MintERC1155.Edition({
name: "Edition 1",
imageURI: "https://example.com/image1.png",
percentChance: 100,
attributes: attributes
});

NFTMint.MintArgs memory mintArgs = NFTMint.MintArgs({
mintExpiration: uint40(block.timestamp + 1 days),
maxMints: 1,
editions: editions,
allowlistMerkleRoot: bytes32(0),
pricePerMint: 0.01 ether,
perWalletLimit: 1,
feePerMint: 0.001 ether,
owner: payable(address(this)),
feeRecipient: payable(address(0)),
name: "My Token Name",
imageURI: "image here",
description: "This is a description",
royaltyAmountBps: 150
});

vm.expectRevert(NFTMint.NFTMint_InvalidFeeRecipient.selector);
nftMint.createMint(mintArgs);
}

event OrderPlaced(
MintERC1155 indexed mint, uint256 indexed orderId, address indexed to, uint256 amount, string comment
);
Expand Down Expand Up @@ -365,7 +329,6 @@ contract NFTMintTest is TestBase {
perWalletLimit: 105,
feePerMint: 0.001 ether,
owner: payable(address(this)),
feeRecipient: payable(address(this)),
name: "My Token Name",
imageURI: "image here",
description: "This is a description",
Expand Down Expand Up @@ -394,7 +357,7 @@ contract NFTMintTest is TestBase {
attributes: attributes
});

address minter = _randomAddress();
address minter = address(new MockFailingRecipient());

vm.deal(minter, 10 ether);
vm.prank(minter);
Expand All @@ -409,7 +372,6 @@ contract NFTMintTest is TestBase {
perWalletLimit: 105,
feePerMint: 0.001 ether,
owner: payable(address(this)),
feeRecipient: payable(address(new MockFailingRecipient())),
name: "My Token Name",
imageURI: "image here",
description: "This is a description",
Expand All @@ -420,7 +382,7 @@ contract NFTMintTest is TestBase {

vm.expectRevert(NFTMint.NFTMint_FailedToTransferFunds.selector);
vm.prank(minter);
nftMint.order{ value: 0.011 ether }(mint, 1, "", new bytes32[](0));
nftMint.order{ value: 0.012 ether }(mint, 1, "", new bytes32[](0));
}

event OrderFilled(
Expand Down

0 comments on commit 0fc9646

Please sign in to comment.