Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert to SoundEditionV2 events, change SoundEditionV2_1 interface ID #306

Merged
merged 3 commits into from
Dec 28, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/heavy-planets-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@soundxyz/sound-protocol": patch
---

Revert to SoundEditionV2 events, change SoundEditionV2_1 interface ID
21 changes: 15 additions & 6 deletions contracts/core/SoundEditionV2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,21 @@ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC
*/
uint16 public constant BPS_DENOMINATOR = LibOps.BPS_DENOMINATOR;

/**
* @dev For making the the interface ID different.
*/
bool public constant V2_1 = true;

/**
* @dev The interface ID for EIP-2981 (royaltyInfo)
*/
bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;

/**
* @dev The interface ID for SoundEditionV2.
*/
bytes4 private constant _INTERFACE_ID_SOUND_EDITION_V2 = 0x7888cfe1;

/**
* @dev The boolean flag on whether the metadata is frozen.
*/
Expand Down Expand Up @@ -219,10 +229,9 @@ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC
address to,
uint256 quantity
) external payable onlyRolesOrOwner(ADMIN_ROLE | MINTER_ROLE) returns (uint256 fromTokenId) {
uint32 fromTierTokenIdIndex;
(fromTokenId, fromTierTokenIdIndex) = _beforeTieredMint(tier, quantity);
(fromTokenId, ) = _beforeTieredMint(tier, quantity);
_batchMint(to, quantity);
emit Minted(tier, to, quantity, fromTokenId, fromTierTokenIdIndex);
emit Minted(tier, to, quantity, fromTokenId);
}

/**
Expand All @@ -233,17 +242,16 @@ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC
address[] calldata to,
uint256 quantity
) external payable onlyRolesOrOwner(ADMIN_ROLE | MINTER_ROLE) returns (uint256 fromTokenId) {
uint32 fromTierTokenIdIndex;
unchecked {
// Multiplication overflow is not possible due to the max block gas limit.
// If `quantity` is too big (e.g. 2**64), the loop in `_batchMint` will run out of gas.
// If `to.length` is too big (e.g. 2**64), the airdrop mint loop will run out of gas.
(fromTokenId, fromTierTokenIdIndex) = _beforeTieredMint(tier, to.length * quantity);
(fromTokenId, ) = _beforeTieredMint(tier, to.length * quantity);
for (uint256 i; i != to.length; ++i) {
_batchMint(to[i], quantity);
}
}
emit Airdropped(tier, to, quantity, fromTokenId, fromTierTokenIdIndex);
emit Airdropped(tier, to, quantity, fromTokenId);
}

/**
Expand Down Expand Up @@ -718,6 +726,7 @@ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC
LibOps.or(
interfaceId == type(ISoundEditionV2_1).interfaceId,
ERC721AUpgradeable.supportsInterface(interfaceId),
interfaceId == _INTERFACE_ID_SOUND_EDITION_V2,
interfaceId == _INTERFACE_ID_ERC2981
);
}
Expand Down
12 changes: 8 additions & 4 deletions contracts/core/interfaces/ISoundEditionV2_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -234,19 +234,17 @@ interface ISoundEditionV2_1 is IERC721AUpgradeable, IERC2981Upgradeable {
* @param to The address to mint to.
* @param quantity The number of minted.
* @param fromTokenId The first token ID minted.
* @param fromTierTokenIdIndex The first token index in the tier.
*/
event Minted(uint8 tier, address to, uint256 quantity, uint256 fromTokenId, uint32 fromTierTokenIdIndex);
event Minted(uint8 tier, address to, uint256 quantity, uint256 fromTokenId);

/**
* @dev Emitted upon an airdrop.
* @param tier The tier.
* @param to The recipients of the airdrop.
* @param quantity The number of tokens airdropped to each address in `to`.
* @param fromTokenId The first token ID minted to the first address in `to`.
* @param fromTierTokenIdIndex The first token index in the tier.
*/
event Airdropped(uint8 tier, address[] to, uint256 quantity, uint256 fromTokenId, uint32 fromTierTokenIdIndex);
event Airdropped(uint8 tier, address[] to, uint256 quantity, uint256 fromTokenId);

/**
* @dev EIP-4906 event to signal marketplaces to refresh the metadata.
Expand Down Expand Up @@ -810,4 +808,10 @@ interface ISoundEditionV2_1 is IERC721AUpgradeable, IERC2981Upgradeable {
view
override(IERC721AUpgradeable, IERC165Upgradeable)
returns (bool);

/**
* @dev Filler function to make the interface ID different.
* @return True.
*/
function V2_1() external view returns (bool);
}
14 changes: 8 additions & 6 deletions tests/core/SoundEditionV2_1.t.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import { ISoundEditionV2 } from "@core/SoundEditionV2.sol";
import { IERC721AUpgradeable, ISoundEditionV2_1, SoundEditionV2_1 } from "@core/SoundEditionV2_1.sol";
import { Ownable, OwnableRoles } from "solady/auth/OwnableRoles.sol";
import { LibSort } from "solady/utils/LibSort.sol";
Expand All @@ -25,8 +26,8 @@ contract SoundEditionV2_1Tests is TestConfigV2_1 {
event TierFrozen(uint8 tier);
event ETHWithdrawn(address recipient, uint256 amount, address caller);
event ERC20Withdrawn(address recipient, address[] tokens, uint256[] amounts, address caller);
event Minted(uint8 tier, address to, uint256 quantity, uint256 fromTokenId, uint32 fromTierTokenIdIndex);
event Airdropped(uint8 tier, address[] to, uint256 quantity, uint256 fromTokenId, uint32 fromTierTokenIdIndex);
event Minted(uint8 tier, address to, uint256 quantity, uint256 fromTokenId);
event Airdropped(uint8 tier, address[] to, uint256 quantity, uint256 fromTokenId);
event BatchMetadataUpdate(uint256 fromTokenId, uint256 toTokenId);

uint16 public constant BPS_DENOMINATOR = 10000;
Expand Down Expand Up @@ -143,24 +144,24 @@ contract SoundEditionV2_1Tests is TestConfigV2_1 {
) internal {
uint256 r = _random() % 3;
uint256 expectedFromTokenId = edition.nextTokenId();
uint32 expectedFromTierTokenIdIndex = edition.tierInfo(tier).minted;

if (r == 0) {
vm.expectEmit(true, true, true, true);
emit Minted(tier, to, quantity, expectedFromTokenId, expectedFromTierTokenIdIndex);
emit Minted(tier, to, quantity, expectedFromTokenId);
edition.mint(tier, to, quantity);
} else if (r == 1) {
address[] memory recipients = new address[](quantity);
for (uint256 i; i != quantity; ++i) {
recipients[i] = to;
}
vm.expectEmit(true, true, true, true);
emit Airdropped(tier, recipients, 1, expectedFromTokenId, expectedFromTierTokenIdIndex);
emit Airdropped(tier, recipients, 1, expectedFromTokenId);
edition.airdrop(tier, recipients, 1);
} else {
address[] memory recipients = new address[](1);
recipients[0] = to;
vm.expectEmit(true, true, true, true);
emit Airdropped(tier, recipients, quantity, expectedFromTokenId, expectedFromTierTokenIdIndex);
emit Airdropped(tier, recipients, quantity, expectedFromTokenId);
edition.airdrop(tier, recipients, quantity);
}
}
Expand Down Expand Up @@ -441,6 +442,7 @@ contract SoundEditionV2_1Tests is TestConfigV2_1 {
assertTrue(edition.supportsInterface(0x80ac58cd)); // IERC721.
assertTrue(edition.supportsInterface(0x01ffc9a7)); // IERC165.
assertTrue(edition.supportsInterface(0x5b5e139f)); // IERC721Metadata.
assertTrue(edition.supportsInterface(type(ISoundEditionV2).interfaceId));
assertTrue(edition.supportsInterface(type(ISoundEditionV2_1).interfaceId));

assertFalse(edition.supportsInterface(0x11223344)); // Some random ID.
Expand Down
Loading