From 4e902c4cb0fc62f8a42cb980e1f0eab2bdeca450 Mon Sep 17 00:00:00 2001 From: tenthirtyone Date: Tue, 1 Apr 2025 18:06:16 -0500 Subject: [PATCH 1/3] Remove string hardcoding --- contracts/nft/erc721m/ERC721M.sol | 148 +++++++++++++++++++++++------- 1 file changed, 114 insertions(+), 34 deletions(-) diff --git a/contracts/nft/erc721m/ERC721M.sol b/contracts/nft/erc721m/ERC721M.sol index 22d1315b..c5ef76ff 100644 --- a/contracts/nft/erc721m/ERC721M.sol +++ b/contracts/nft/erc721m/ERC721M.sol @@ -75,18 +75,33 @@ contract ERC721M is /// @notice Returns the contract name and version /// @return The contract name and version as strings - function contractNameAndVersion() public pure returns (string memory, string memory) { + function contractNameAndVersion() + public + pure + returns (string memory, string memory) + { return ("ERC721M", "1.0.0"); } /// @notice Gets the token URI for a specific token ID /// @param tokenId The ID of the token /// @return The token URI - function tokenURI(uint256 tokenId) public view override(ERC721A, IERC721A) returns (string memory) { + function tokenURI( + uint256 tokenId + ) public view override(ERC721A, IERC721A) returns (string memory) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); string memory baseURI = _currentBaseURI; - return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId), _tokenURISuffix)) : ""; + return + bytes(baseURI).length != 0 + ? string( + abi.encodePacked( + baseURI, + _toString(tokenId), + _tokenURISuffix + ) + ) + : ""; } /// @notice Gets the contract URI @@ -122,12 +137,13 @@ contract ERC721M is /// @param proof The merkle proof for allowlist minting /// @param timestamp The timestamp for the minting action (used in cosigning) /// @param signature The cosigner's signature - function mint(uint32 qty, uint32 limit, bytes32[] calldata proof, uint256 timestamp, bytes calldata signature) - external - payable - virtual - nonReentrant - { + function mint( + uint32 qty, + uint32 limit, + bytes32[] calldata proof, + uint256 timestamp, + bytes calldata signature + ) external payable virtual nonReentrant { _mintInternal(qty, msg.sender, limit, proof, timestamp, signature); } @@ -156,9 +172,11 @@ contract ERC721M is /// @notice Gets the stage info for a given stage index /// @param index The stage index /// @return The stage info, wallet minted count, and stage minted count - function getStageInfo(uint256 index) external view override returns (MintStageInfo memory, uint32, uint256) { + function getStageInfo( + uint256 index + ) external view override returns (MintStageInfo memory, uint32, uint256) { if (index >= _mintStages.length) { - revert("InvalidStage"); + revert(InvalidStage); } uint32 walletMinted = _stageMintedCountsPerWallet[index][msg.sender]; uint256 stageMinted = _stageMintedCounts[index]; @@ -205,16 +223,23 @@ contract ERC721M is /// @notice Gets the total minted count for a specific address /// @param a The address to get the minted count for /// @return The total minted count - function totalMintedByAddress(address a) external view virtual override returns (uint256) { + function totalMintedByAddress( + address a + ) external view virtual override returns (uint256) { return _numberMinted(a); } /// @notice Gets the active stage from the timestamp /// @param timestamp The timestamp to get the active stage from /// @return The active stage - function getActiveStageFromTimestamp(uint256 timestamp) public view returns (uint256) { + function getActiveStageFromTimestamp( + uint256 timestamp + ) public view returns (uint256) { for (uint256 i = 0; i < _mintStages.length; i++) { - if (timestamp >= _mintStages[i].startTimeUnixSeconds && timestamp < _mintStages[i].endTimeUnixSeconds) { + if ( + timestamp >= _mintStages[i].startTimeUnixSeconds && + timestamp < _mintStages[i].endTimeUnixSeconds + ) { return i; } } @@ -233,7 +258,9 @@ contract ERC721M is /// @notice Removes an authorized minter /// @param minter The address to remove as an authorized minter - function removeAuthorizedMinter(address minter) external override onlyOwner { + function removeAuthorizedMinter( + address minter + ) external override onlyOwner { _removeAuthorizedMinter(minter); } @@ -245,7 +272,9 @@ contract ERC721M is /// @notice Sets the timestamp expiry seconds /// @param timestampExpirySeconds The expiry time in seconds for timestamps - function setTimestampExpirySeconds(uint256 timestampExpirySeconds) external override onlyOwner { + function setTimestampExpirySeconds( + uint256 timestampExpirySeconds + ) external override onlyOwner { _setTimestampExpirySeconds(timestampExpirySeconds); } @@ -257,13 +286,17 @@ contract ERC721M is for (uint256 i = 0; i < newStages.length; i++) { if (i >= 1) { if ( - newStages[i].startTimeUnixSeconds - < newStages[i - 1].endTimeUnixSeconds + getTimestampExpirySeconds() + newStages[i].startTimeUnixSeconds < + newStages[i - 1].endTimeUnixSeconds + + getTimestampExpirySeconds() ) { revert InsufficientStageTimeGap(); } } - _assertValidStartAndEndTimestamp(newStages[i].startTimeUnixSeconds, newStages[i].endTimeUnixSeconds); + _assertValidStartAndEndTimestamp( + newStages[i].startTimeUnixSeconds, + newStages[i].endTimeUnixSeconds + ); _mintStages.push( MintStageInfo({ price: newStages[i].price, @@ -295,7 +328,9 @@ contract ERC721M is /// @notice Sets the maximum mintable supply /// @param maxMintableSupply The maximum mintable supply to set - function setMaxMintableSupply(uint256 maxMintableSupply) external virtual onlyOwner { + function setMaxMintableSupply( + uint256 maxMintableSupply + ) external virtual onlyOwner { if (maxMintableSupply > _maxMintableSupply) { revert CannotIncreaseMaxMintableSupply(); } @@ -305,7 +340,9 @@ contract ERC721M is /// @notice Sets the global wallet limit /// @param globalWalletLimit The global wallet limit to set - function setGlobalWalletLimit(uint256 globalWalletLimit) external onlyOwner { + function setGlobalWalletLimit( + uint256 globalWalletLimit + ) external onlyOwner { if (globalWalletLimit > _maxMintableSupply) { revert GlobalWalletLimitOverflow(); } @@ -316,19 +353,22 @@ contract ERC721M is /// @notice Allows the owner to mint tokens for a specific address /// @param qty The quantity to mint /// @param to The address to mint tokens for - function ownerMint(uint32 qty, address to) external onlyOwner hasSupply(qty) { + function ownerMint( + uint32 qty, + address to + ) external onlyOwner hasSupply(qty) { _safeMint(to, qty); } /// @notice Withdraws the total mint fee and remaining balance from the contract /// @dev Can only be called by the owner function withdraw() external onlyOwner { - (bool success,) = MINT_FEE_RECEIVER.call{value: _totalMintFee}(""); + (bool success, ) = MINT_FEE_RECEIVER.call{value: _totalMintFee}(""); if (!success) revert TransferFailed(); _totalMintFee = 0; uint256 remainingValue = address(this).balance; - (success,) = _fundReceiver.call{value: remainingValue}(""); + (success, ) = _fundReceiver.call{value: remainingValue}(""); if (!success) revert WithdrawFailed(); emit Withdraw(_totalMintFee + remainingValue); @@ -340,14 +380,21 @@ contract ERC721M is if (_mintCurrency == address(0)) revert WrongMintCurrency(); uint256 totalFee = _totalMintFee; - uint256 remaining = SafeTransferLib.balanceOf(_mintCurrency, address(this)); + uint256 remaining = SafeTransferLib.balanceOf( + _mintCurrency, + address(this) + ); if (remaining < totalFee) revert InsufficientBalance(); _totalMintFee = 0; uint256 totalAmount = totalFee + remaining; - SafeTransferLib.safeTransfer(_mintCurrency, MINT_FEE_RECEIVER, totalFee); + SafeTransferLib.safeTransfer( + _mintCurrency, + MINT_FEE_RECEIVER, + totalFee + ); SafeTransferLib.safeTransfer(_mintCurrency, _fundReceiver, remaining); emit WithdrawERC20(_mintCurrency, totalAmount); @@ -396,7 +443,13 @@ contract ERC721M is bool waiveMintFee = false; if (getCosigner() != address(0)) { - waiveMintFee = assertValidCosign(msg.sender, qty, timestamp, signature, getCosignNonce(msg.sender)); + waiveMintFee = assertValidCosign( + msg.sender, + qty, + timestamp, + signature, + getCosignNonce(msg.sender) + ); _assertValidTimestamp(timestamp); stageTimestamp = timestamp; } @@ -407,7 +460,10 @@ contract ERC721M is uint256 adjustedMintFee = waiveMintFee ? 0 : _mintFee; // Check value if minting with ETH - if (_mintCurrency == address(0) && msg.value < (stage.price + adjustedMintFee) * qty) revert NotEnoughValue(); + if ( + _mintCurrency == address(0) && + msg.value < (stage.price + adjustedMintFee) * qty + ) revert NotEnoughValue(); // Check stage supply if applicable if (stage.maxStageSupply > 0) { @@ -425,19 +481,31 @@ contract ERC721M is // Check wallet limit for stage if applicable, limit == 0 means no limit enforced if (stage.walletLimit > 0) { - if (_stageMintedCountsPerWallet[activeStage][to] + qty > stage.walletLimit) { + if ( + _stageMintedCountsPerWallet[activeStage][to] + qty > + stage.walletLimit + ) { revert WalletStageLimitExceeded(); } } // Check merkle proof if applicable, merkleRoot == 0x00...00 means no proof required if (stage.merkleRoot != 0) { - if (!MerkleProofLib.verify(proof, stage.merkleRoot, keccak256(abi.encodePacked(to, limit)))) { + if ( + !MerkleProofLib.verify( + proof, + stage.merkleRoot, + keccak256(abi.encodePacked(to, limit)) + ) + ) { revert InvalidProof(); } // Verify merkle proof mint limit - if (limit > 0 && _stageMintedCountsPerWallet[activeStage][to] + qty > limit) { + if ( + limit > 0 && + _stageMintedCountsPerWallet[activeStage][to] + qty > limit + ) { revert WalletStageLimitExceeded(); } } @@ -445,7 +513,10 @@ contract ERC721M is if (_mintCurrency != address(0)) { // ERC20 mint payment SafeTransferLib.safeTransferFrom( - _mintCurrency, msg.sender, address(this), (stage.price + adjustedMintFee) * qty + _mintCurrency, + msg.sender, + address(this), + (stage.price + adjustedMintFee) * qty ); } @@ -459,12 +530,21 @@ contract ERC721M is /// @notice Validates the start and end timestamps for a stage /// @param start The start timestamp /// @param end The end timestamp - function _assertValidStartAndEndTimestamp(uint256 start, uint256 end) internal pure { + function _assertValidStartAndEndTimestamp( + uint256 start, + uint256 end + ) internal pure { if (start >= end) revert InvalidStartAndEndTimestamp(); } /// @dev Overriden to prevent double-initialization of the owner. - function _guardInitializeOwner() internal pure virtual override returns (bool) { + function _guardInitializeOwner() + internal + pure + virtual + override + returns (bool) + { return true; } } From 6dadf5e265b02c40c76571bac533907a87508843 Mon Sep 17 00:00:00 2001 From: tenthirtyone Date: Tue, 1 Apr 2025 18:08:14 -0500 Subject: [PATCH 2/3] forge fmt --- contracts/nft/erc721m/ERC721M.sol | 146 +++++++----------------------- 1 file changed, 33 insertions(+), 113 deletions(-) diff --git a/contracts/nft/erc721m/ERC721M.sol b/contracts/nft/erc721m/ERC721M.sol index c5ef76ff..2f5c3faa 100644 --- a/contracts/nft/erc721m/ERC721M.sol +++ b/contracts/nft/erc721m/ERC721M.sol @@ -75,33 +75,18 @@ contract ERC721M is /// @notice Returns the contract name and version /// @return The contract name and version as strings - function contractNameAndVersion() - public - pure - returns (string memory, string memory) - { + function contractNameAndVersion() public pure returns (string memory, string memory) { return ("ERC721M", "1.0.0"); } /// @notice Gets the token URI for a specific token ID /// @param tokenId The ID of the token /// @return The token URI - function tokenURI( - uint256 tokenId - ) public view override(ERC721A, IERC721A) returns (string memory) { + function tokenURI(uint256 tokenId) public view override(ERC721A, IERC721A) returns (string memory) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); string memory baseURI = _currentBaseURI; - return - bytes(baseURI).length != 0 - ? string( - abi.encodePacked( - baseURI, - _toString(tokenId), - _tokenURISuffix - ) - ) - : ""; + return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId), _tokenURISuffix)) : ""; } /// @notice Gets the contract URI @@ -137,13 +122,12 @@ contract ERC721M is /// @param proof The merkle proof for allowlist minting /// @param timestamp The timestamp for the minting action (used in cosigning) /// @param signature The cosigner's signature - function mint( - uint32 qty, - uint32 limit, - bytes32[] calldata proof, - uint256 timestamp, - bytes calldata signature - ) external payable virtual nonReentrant { + function mint(uint32 qty, uint32 limit, bytes32[] calldata proof, uint256 timestamp, bytes calldata signature) + external + payable + virtual + nonReentrant + { _mintInternal(qty, msg.sender, limit, proof, timestamp, signature); } @@ -172,9 +156,7 @@ contract ERC721M is /// @notice Gets the stage info for a given stage index /// @param index The stage index /// @return The stage info, wallet minted count, and stage minted count - function getStageInfo( - uint256 index - ) external view override returns (MintStageInfo memory, uint32, uint256) { + function getStageInfo(uint256 index) external view override returns (MintStageInfo memory, uint32, uint256) { if (index >= _mintStages.length) { revert(InvalidStage); } @@ -223,23 +205,16 @@ contract ERC721M is /// @notice Gets the total minted count for a specific address /// @param a The address to get the minted count for /// @return The total minted count - function totalMintedByAddress( - address a - ) external view virtual override returns (uint256) { + function totalMintedByAddress(address a) external view virtual override returns (uint256) { return _numberMinted(a); } /// @notice Gets the active stage from the timestamp /// @param timestamp The timestamp to get the active stage from /// @return The active stage - function getActiveStageFromTimestamp( - uint256 timestamp - ) public view returns (uint256) { + function getActiveStageFromTimestamp(uint256 timestamp) public view returns (uint256) { for (uint256 i = 0; i < _mintStages.length; i++) { - if ( - timestamp >= _mintStages[i].startTimeUnixSeconds && - timestamp < _mintStages[i].endTimeUnixSeconds - ) { + if (timestamp >= _mintStages[i].startTimeUnixSeconds && timestamp < _mintStages[i].endTimeUnixSeconds) { return i; } } @@ -258,9 +233,7 @@ contract ERC721M is /// @notice Removes an authorized minter /// @param minter The address to remove as an authorized minter - function removeAuthorizedMinter( - address minter - ) external override onlyOwner { + function removeAuthorizedMinter(address minter) external override onlyOwner { _removeAuthorizedMinter(minter); } @@ -272,9 +245,7 @@ contract ERC721M is /// @notice Sets the timestamp expiry seconds /// @param timestampExpirySeconds The expiry time in seconds for timestamps - function setTimestampExpirySeconds( - uint256 timestampExpirySeconds - ) external override onlyOwner { + function setTimestampExpirySeconds(uint256 timestampExpirySeconds) external override onlyOwner { _setTimestampExpirySeconds(timestampExpirySeconds); } @@ -286,17 +257,13 @@ contract ERC721M is for (uint256 i = 0; i < newStages.length; i++) { if (i >= 1) { if ( - newStages[i].startTimeUnixSeconds < - newStages[i - 1].endTimeUnixSeconds + - getTimestampExpirySeconds() + newStages[i].startTimeUnixSeconds + < newStages[i - 1].endTimeUnixSeconds + getTimestampExpirySeconds() ) { revert InsufficientStageTimeGap(); } } - _assertValidStartAndEndTimestamp( - newStages[i].startTimeUnixSeconds, - newStages[i].endTimeUnixSeconds - ); + _assertValidStartAndEndTimestamp(newStages[i].startTimeUnixSeconds, newStages[i].endTimeUnixSeconds); _mintStages.push( MintStageInfo({ price: newStages[i].price, @@ -328,9 +295,7 @@ contract ERC721M is /// @notice Sets the maximum mintable supply /// @param maxMintableSupply The maximum mintable supply to set - function setMaxMintableSupply( - uint256 maxMintableSupply - ) external virtual onlyOwner { + function setMaxMintableSupply(uint256 maxMintableSupply) external virtual onlyOwner { if (maxMintableSupply > _maxMintableSupply) { revert CannotIncreaseMaxMintableSupply(); } @@ -340,9 +305,7 @@ contract ERC721M is /// @notice Sets the global wallet limit /// @param globalWalletLimit The global wallet limit to set - function setGlobalWalletLimit( - uint256 globalWalletLimit - ) external onlyOwner { + function setGlobalWalletLimit(uint256 globalWalletLimit) external onlyOwner { if (globalWalletLimit > _maxMintableSupply) { revert GlobalWalletLimitOverflow(); } @@ -353,22 +316,19 @@ contract ERC721M is /// @notice Allows the owner to mint tokens for a specific address /// @param qty The quantity to mint /// @param to The address to mint tokens for - function ownerMint( - uint32 qty, - address to - ) external onlyOwner hasSupply(qty) { + function ownerMint(uint32 qty, address to) external onlyOwner hasSupply(qty) { _safeMint(to, qty); } /// @notice Withdraws the total mint fee and remaining balance from the contract /// @dev Can only be called by the owner function withdraw() external onlyOwner { - (bool success, ) = MINT_FEE_RECEIVER.call{value: _totalMintFee}(""); + (bool success,) = MINT_FEE_RECEIVER.call{value: _totalMintFee}(""); if (!success) revert TransferFailed(); _totalMintFee = 0; uint256 remainingValue = address(this).balance; - (success, ) = _fundReceiver.call{value: remainingValue}(""); + (success,) = _fundReceiver.call{value: remainingValue}(""); if (!success) revert WithdrawFailed(); emit Withdraw(_totalMintFee + remainingValue); @@ -380,21 +340,14 @@ contract ERC721M is if (_mintCurrency == address(0)) revert WrongMintCurrency(); uint256 totalFee = _totalMintFee; - uint256 remaining = SafeTransferLib.balanceOf( - _mintCurrency, - address(this) - ); + uint256 remaining = SafeTransferLib.balanceOf(_mintCurrency, address(this)); if (remaining < totalFee) revert InsufficientBalance(); _totalMintFee = 0; uint256 totalAmount = totalFee + remaining; - SafeTransferLib.safeTransfer( - _mintCurrency, - MINT_FEE_RECEIVER, - totalFee - ); + SafeTransferLib.safeTransfer(_mintCurrency, MINT_FEE_RECEIVER, totalFee); SafeTransferLib.safeTransfer(_mintCurrency, _fundReceiver, remaining); emit WithdrawERC20(_mintCurrency, totalAmount); @@ -443,13 +396,7 @@ contract ERC721M is bool waiveMintFee = false; if (getCosigner() != address(0)) { - waiveMintFee = assertValidCosign( - msg.sender, - qty, - timestamp, - signature, - getCosignNonce(msg.sender) - ); + waiveMintFee = assertValidCosign(msg.sender, qty, timestamp, signature, getCosignNonce(msg.sender)); _assertValidTimestamp(timestamp); stageTimestamp = timestamp; } @@ -460,10 +407,7 @@ contract ERC721M is uint256 adjustedMintFee = waiveMintFee ? 0 : _mintFee; // Check value if minting with ETH - if ( - _mintCurrency == address(0) && - msg.value < (stage.price + adjustedMintFee) * qty - ) revert NotEnoughValue(); + if (_mintCurrency == address(0) && msg.value < (stage.price + adjustedMintFee) * qty) revert NotEnoughValue(); // Check stage supply if applicable if (stage.maxStageSupply > 0) { @@ -481,31 +425,19 @@ contract ERC721M is // Check wallet limit for stage if applicable, limit == 0 means no limit enforced if (stage.walletLimit > 0) { - if ( - _stageMintedCountsPerWallet[activeStage][to] + qty > - stage.walletLimit - ) { + if (_stageMintedCountsPerWallet[activeStage][to] + qty > stage.walletLimit) { revert WalletStageLimitExceeded(); } } // Check merkle proof if applicable, merkleRoot == 0x00...00 means no proof required if (stage.merkleRoot != 0) { - if ( - !MerkleProofLib.verify( - proof, - stage.merkleRoot, - keccak256(abi.encodePacked(to, limit)) - ) - ) { + if (!MerkleProofLib.verify(proof, stage.merkleRoot, keccak256(abi.encodePacked(to, limit)))) { revert InvalidProof(); } // Verify merkle proof mint limit - if ( - limit > 0 && - _stageMintedCountsPerWallet[activeStage][to] + qty > limit - ) { + if (limit > 0 && _stageMintedCountsPerWallet[activeStage][to] + qty > limit) { revert WalletStageLimitExceeded(); } } @@ -513,10 +445,7 @@ contract ERC721M is if (_mintCurrency != address(0)) { // ERC20 mint payment SafeTransferLib.safeTransferFrom( - _mintCurrency, - msg.sender, - address(this), - (stage.price + adjustedMintFee) * qty + _mintCurrency, msg.sender, address(this), (stage.price + adjustedMintFee) * qty ); } @@ -530,21 +459,12 @@ contract ERC721M is /// @notice Validates the start and end timestamps for a stage /// @param start The start timestamp /// @param end The end timestamp - function _assertValidStartAndEndTimestamp( - uint256 start, - uint256 end - ) internal pure { + function _assertValidStartAndEndTimestamp(uint256 start, uint256 end) internal pure { if (start >= end) revert InvalidStartAndEndTimestamp(); } /// @dev Overriden to prevent double-initialization of the owner. - function _guardInitializeOwner() - internal - pure - virtual - override - returns (bool) - { + function _guardInitializeOwner() internal pure virtual override returns (bool) { return true; } } From 9437ce3f9e02e442104f3fd2423620773f733355 Mon Sep 17 00:00:00 2001 From: tenthirtyone Date: Tue, 1 Apr 2025 18:09:29 -0500 Subject: [PATCH 3/3] fix bug --- contracts/nft/erc721m/ERC721M.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/nft/erc721m/ERC721M.sol b/contracts/nft/erc721m/ERC721M.sol index 2f5c3faa..89902054 100644 --- a/contracts/nft/erc721m/ERC721M.sol +++ b/contracts/nft/erc721m/ERC721M.sol @@ -158,7 +158,7 @@ contract ERC721M is /// @return The stage info, wallet minted count, and stage minted count function getStageInfo(uint256 index) external view override returns (MintStageInfo memory, uint32, uint256) { if (index >= _mintStages.length) { - revert(InvalidStage); + revert InvalidStage(); } uint32 walletMinted = _stageMintedCountsPerWallet[index][msg.sender]; uint256 stageMinted = _stageMintedCounts[index];