Skip to content

Commit

Permalink
Remove artist-customizable signer, everyone must use platform signer
Browse files Browse the repository at this point in the history
  • Loading branch information
Vectorized committed Dec 6, 2023
1 parent f10c723 commit ee342c1
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 164 deletions.
63 changes: 4 additions & 59 deletions contracts/modules/SuperMinterV1_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -253,17 +253,13 @@ contract SuperMinterV1_1 is ISuperMinterV1_1, EIP712 {
uint8 mode = c.mode;

if (mode == DEFAULT) {
c.signer = address(0);
c.merkleRoot = bytes32(0);
} else if (mode == VERIFY_MERKLE) {
_validateMerkleRoot(c.merkleRoot);
c.signer = address(0);
} else if (mode == VERIFY_SIGNATURE) {
_validateSigner(c.signer);
c.merkleRoot = bytes32(0);
c.maxMintablePerAccount = type(uint32).max;
} else if (mode == PLATFORM_AIRDROP) {
c.signer = address(1); // We will just use the `platformSigner`.
c.merkleRoot = bytes32(0);
c.maxMintablePerAccount = type(uint32).max;
c.price = 0; // Platform airdrop mode doesn't have a price.
Expand Down Expand Up @@ -301,7 +297,6 @@ contract SuperMinterV1_1 is ISuperMinterV1_1, EIP712 {
editionHead.numMintData = uint16(n);

uint256 mintId = LibOps.packId(c.edition, c.tier, scheduleNum);
bool usePlatformSigner = c.signer == address(1);

MintData storage d = _mintData[mintId];
d.platform = c.platform;
Expand All @@ -312,16 +307,13 @@ contract SuperMinterV1_1 is ISuperMinterV1_1, EIP712 {
d.maxMintable = c.maxMintable;
d.affiliateFeeBPS = c.affiliateFeeBPS;
d.mode = c.mode;
d.flags = _MINT_CREATED_FLAG | LibOps.toFlag(usePlatformSigner, _USE_PLATFORM_SIGNER_FLAG);
d.flags = _MINT_CREATED_FLAG;
d.next = editionHead.head;
editionHead.head = uint16((uint256(c.tier) << 8) | uint256(scheduleNum));

// Skip writing zeros, to avoid cold SSTOREs.
if (c.affiliateMerkleRoot != bytes32(0)) d.affiliateMerkleRoot = c.affiliateMerkleRoot;
if (c.merkleRoot != bytes32(0)) d.merkleRoot = c.merkleRoot;
if (c.signer != address(0)) {
if (!usePlatformSigner) d.signer = c.signer; // Only write if it is not the platform signer.
}

emit MintCreated(c.edition, c.tier, scheduleNum, c);
}
Expand Down Expand Up @@ -608,26 +600,6 @@ contract SuperMinterV1_1 is ISuperMinterV1_1, EIP712 {
emit MerkleRootSet(edition, tier, scheduleNum, merkleRoot);
}

/**
* @inheritdoc ISuperMinterV1_1
*/
function setSigner(
address edition,
uint8 tier,
uint8 scheduleNum,
address signer
) public onlyEditionOwnerOrAdmin(edition) {
uint256 mintId = LibOps.packId(edition, tier, scheduleNum);
MintData storage d = _getMintData(mintId);
// Note that `PLATFORM_AIRDROP` does not allow for configuration of the signer.
if (d.mode != VERIFY_SIGNATURE) revert NotConfigurable();
_validateSigner(signer);
bool usePlatformSigner = signer == address(1);
d.flags = LibOps.setFlagTo(d.flags, _USE_PLATFORM_SIGNER_FLAG, usePlatformSigner);
if (!usePlatformSigner) d.signer = signer;
emit SignerSet(edition, tier, scheduleNum, signer);
}

// Withdrawal functions:
// ---------------------
// These functions can be called by anyone.
Expand Down Expand Up @@ -928,8 +900,7 @@ contract SuperMinterV1_1 is ISuperMinterV1_1, EIP712 {
info.paused = _isPaused(d);
info.affiliateMerkleRoot = d.affiliateMerkleRoot;
info.merkleRoot = d.merkleRoot;
info.signer = _effectiveSigner(d);
info.usePlatformSigner = _usePlatformSigner(d);
info.signer = platformSigner[d.platform];
}

/**
Expand Down Expand Up @@ -1016,14 +987,6 @@ contract SuperMinterV1_1 is ISuperMinterV1_1, EIP712 {
if (merkleRoot == bytes32(0)) revert MerkleRootIsEmpty();
}

/**
* @dev Validates that the signer is not the zero address.
* @param signer The signer.
*/
function _validateSigner(address signer) internal pure {
if (signer == address(0)) revert SignerIsZeroAddress();
}

/**
* @dev Validates that the affiliate fee BPS does not exceed the max threshold.
* @param bps The affiliate fee BPS.
Expand Down Expand Up @@ -1157,7 +1120,7 @@ contract SuperMinterV1_1 is ISuperMinterV1_1, EIP712 {
*/
function _verifyAndClaimSignature(MintData storage d, MintTo calldata p) internal {
if (p.quantity > p.signedQuantity) revert ExceedsSignedQuantity();
address signer = _effectiveSigner(d);
address signer = platformSigner[d.platform];
if (!SignatureCheckerLib.isValidSignatureNowCalldata(signer, computeMintToDigest(p), p.signature))
revert InvalidSignature();
if (block.timestamp > p.signedDeadline) revert SignatureExpired();
Expand All @@ -1172,7 +1135,7 @@ contract SuperMinterV1_1 is ISuperMinterV1_1, EIP712 {
*/
function _verifyAndClaimPlatfromAidropSignature(MintData storage d, PlatformAirdrop calldata p) internal {
// Unlike regular signature mints, platform airdrops only use `signedQuantity`.
address signer = _effectiveSigner(d);
address signer = platformSigner[d.platform];
if (!SignatureCheckerLib.isValidSignatureNowCalldata(signer, computePlatformAirdropDigest(p), p.signature))
revert InvalidSignature();
if (block.timestamp > p.signedDeadline) revert SignatureExpired();
Expand Down Expand Up @@ -1335,22 +1298,4 @@ contract SuperMinterV1_1 is ISuperMinterV1_1, EIP712 {
function _isPaused(MintData storage d) internal view returns (bool) {
return d.flags & _MINT_PAUSED_FLAG != 0;
}

/**
* @dev Returns the effective signer.
* @param d The storage pointer to the mint data.
* @return The effective signer.
*/
function _effectiveSigner(MintData storage d) internal view returns (address) {
return _usePlatformSigner(d) ? platformSigner[d.platform] : d.signer;
}

/**
* @dev Returns whether the platform signer is to be used instead.
* @param d The storage pointer to the mint data.
* @return Whether the platform signer is to be used instead.
*/
function _usePlatformSigner(MintData storage d) internal view returns (bool) {
return d.flags & _USE_PLATFORM_SIGNER_FLAG != 0;
}
}
37 changes: 1 addition & 36 deletions contracts/modules/interfaces/ISuperMinterV1_1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ interface ISuperMinterV1_1 is IERC165 {
address platform;
// The mode of the mint. Options: `DEFAULT`, `VERIFY_MERKLE`, `VERIFY_SIGNATURE`.
uint8 mode;
// The signer address, required if `mode` is `VERIFY_SIGNATURE`.
// If set to `address(1)`, the platform signer will be used instead.
address signer;
// The Merkle root hash, required if `mode` is `VERIFY_MERKLE`.
bytes32 merkleRoot;
}
Expand Down Expand Up @@ -241,12 +238,8 @@ interface ISuperMinterV1_1 is IERC165 {
bytes32 affiliateMerkleRoot;
// The Merkle root hash, required if `mode` is `VERIFY_MERKLE`.
bytes32 merkleRoot;
// The signer address, required if `mode` is `VERIFY_SIGNATURE` or `PLATFORM_AIRDROP`.
// This value will be the platform signer instead if it is configured to be `address(1)`.
// The signer address, used if `mode` is `VERIFY_SIGNATURE` or `PLATFORM_AIRDROP`.
address signer;
// Whether the platform signer is being used instead
// (i.e. `signer` configured to be `address(1)`).
bool usePlatformSigner;
}

// =============================================================
Expand Down Expand Up @@ -317,15 +310,6 @@ interface ISuperMinterV1_1 is IERC165 {
*/
event MerkleRootSet(address indexed edition, uint8 tier, uint8 scheduleNum, bytes32 merkleRoot);

/**
* @dev Emitted when the signer of a mint is updated.
* @param edition The address of the Sound Edition.
* @param tier The tier.
* @param scheduleNum The edition-tier schedule number.
* @param signer The signer of the mint.
*/
event SignerSet(address indexed edition, uint8 tier, uint8 scheduleNum, address signer);

/**
* @dev Emitted when the affiliate fee BPS for a mint is updated.
* @param edition The address of the Sound Edition.
Expand Down Expand Up @@ -512,11 +496,6 @@ interface ISuperMinterV1_1 is IERC165 {
*/
error SignatureAlreadyUsed();

/**
* @dev The signer cannot be the zero address.
*/
error SignerIsZeroAddress();

/**
* @dev The Merkle root cannot be empty.
*/
Expand Down Expand Up @@ -728,20 +707,6 @@ interface ISuperMinterV1_1 is IERC165 {
bytes32 merkleRoot
) external;

/**
* @dev Sets the signer for the mint. The mint mode must be `VERIFY_SIGNATURE`.
* @param edition The address of the Sound Edition.
* @param tier The tier.
* @param scheduleNum The edition-tier schedule number.
* @param signer The signer of the mint.
*/
function setSigner(
address edition,
uint8 tier,
uint8 scheduleNum,
address signer
) external;

/**
* @dev Withdraws all accrued fees of the affiliate, to the affiliate.
* @param affiliate The affiliate address.
Expand Down
79 changes: 10 additions & 69 deletions tests/modules/SuperMinterV1_1.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
}
if (i == 2) {
c.mode = sm.VERIFY_SIGNATURE();
c.signer = address(2);
}
uint8 nextScheduleNum = sm.nextScheduleNum(c.edition, c.tier);
assertEq(sm.createEditionMint(c), nextScheduleNum);
Expand All @@ -87,6 +86,9 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
}
}

address signer = _randomNonZeroAddress();
sm.setPlatformSigner(signer);

ISuperMinterV1_1.MintInfo[] memory mintInfoList = sm.mintInfoList(address(edition));
assertEq(mintInfoList.length, 3 * 3);
for (uint256 j; j < 3; ++j) {
Expand All @@ -103,7 +105,7 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
assertEq(info.endTime, type(uint32).max);
assertEq(info.mode, sm.DEFAULT());
assertEq(info.merkleRoot, bytes32(0));
assertEq(info.signer, address(0));
assertEq(info.signer, signer);
}
if (i == 1) {
assertEq(info.mode, sm.VERIFY_MERKLE());
Expand All @@ -112,14 +114,15 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
assertEq(info.endTime, uint32(block.timestamp + 1000 + i));
assertEq(info.mode, sm.VERIFY_MERKLE());
assertEq(info.merkleRoot, keccak256("x"));
assertEq(info.signer, signer);
}
if (i == 2) {
assertEq(info.mode, sm.VERIFY_SIGNATURE());
assertEq(info.price, i * 1 ether);
assertEq(info.maxMintablePerAccount, type(uint32).max);
assertEq(info.endTime, uint32(block.timestamp + 1000 + i));
assertEq(info.mode, sm.VERIFY_SIGNATURE());
assertEq(info.signer, address(2));
assertEq(info.signer, signer);
}
}
}
Expand All @@ -137,19 +140,13 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
c.endTime = uint32(c.startTime + _bound(_random(), 0, 1000));
c.maxMintablePerAccount = uint32(_bound(_random(), 1, type(uint32).max));
c.merkleRoot = keccak256(abi.encodePacked(_random()));
c.signer = _randomNonZeroAddress();
if (c.signer == address(1)) c.signer = address(2);

assertEq(sm.createEditionMint(c), 0);

ISuperMinterV1_1.MintInfo memory info = sm.mintInfo(address(edition), c.tier, 0);
assertEq(info.platform, address(this));
if (c.tier == 0) {
if (c.mode == sm.DEFAULT()) {
assertEq(info.signer, address(0));
vm.expectRevert(ISuperMinterV1_1.NotConfigurable.selector);
sm.setSigner(address(edition), c.tier, 0, c.signer);

assertEq(info.merkleRoot, bytes32(0));
vm.expectRevert(ISuperMinterV1_1.NotConfigurable.selector);
sm.setMerkleRoot(address(edition), c.tier, 0, c.merkleRoot);
Expand All @@ -166,10 +163,6 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
vm.expectRevert(ISuperMinterV1_1.NotConfigurable.selector);
sm.setMaxMintablePerAccount(address(edition), c.tier, 0, c.maxMintablePerAccount);
} else if (c.mode == sm.VERIFY_MERKLE()) {
assertEq(info.signer, address(0));
vm.expectRevert(ISuperMinterV1_1.NotConfigurable.selector);
sm.setSigner(address(edition), c.tier, 0, c.signer);

assertEq(info.merkleRoot, c.merkleRoot);
sm.setMerkleRoot(address(edition), c.tier, 0, c.merkleRoot);

Expand All @@ -184,8 +177,7 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
vm.expectRevert(ISuperMinterV1_1.NotConfigurable.selector);
sm.setMaxMintablePerAccount(address(edition), c.tier, 0, c.maxMintablePerAccount);
} else if (c.mode == sm.VERIFY_SIGNATURE()) {
assertEq(info.signer, c.signer);
sm.setSigner(address(edition), c.tier, 0, c.signer);
assertEq(info.signer, sm.platformSigner(c.platform));

assertEq(info.merkleRoot, bytes32(0));
vm.expectRevert(ISuperMinterV1_1.NotConfigurable.selector);
Expand All @@ -203,10 +195,6 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
}
} else {
if (c.mode == sm.DEFAULT()) {
assertEq(info.signer, address(0));
vm.expectRevert(ISuperMinterV1_1.NotConfigurable.selector);
sm.setSigner(address(edition), c.tier, 0, c.signer);

assertEq(info.merkleRoot, bytes32(0));
vm.expectRevert(ISuperMinterV1_1.NotConfigurable.selector);
sm.setMerkleRoot(address(edition), c.tier, 0, c.merkleRoot);
Expand All @@ -220,10 +208,6 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
assertEq(info.maxMintablePerAccount, c.maxMintablePerAccount);
sm.setMaxMintablePerAccount(address(edition), c.tier, 0, c.maxMintablePerAccount);
} else if (c.mode == sm.VERIFY_MERKLE()) {
assertEq(info.signer, address(0));
vm.expectRevert(ISuperMinterV1_1.NotConfigurable.selector);
sm.setSigner(address(edition), c.tier, 0, c.signer);

assertEq(info.merkleRoot, c.merkleRoot);
sm.setMerkleRoot(address(edition), c.tier, 0, c.merkleRoot);

Expand All @@ -236,8 +220,7 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
assertEq(info.maxMintablePerAccount, c.maxMintablePerAccount);
sm.setMaxMintablePerAccount(address(edition), c.tier, 0, c.maxMintablePerAccount);
} else if (c.mode == sm.VERIFY_SIGNATURE()) {
assertEq(info.signer, c.signer);
sm.setSigner(address(edition), c.tier, 0, c.signer);
assertEq(info.signer, sm.platformSigner(c.platform));

assertEq(info.merkleRoot, bytes32(0));
vm.expectRevert(ISuperMinterV1_1.NotConfigurable.selector);
Expand Down Expand Up @@ -662,9 +645,6 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
if (c.mode == sm.VERIFY_MERKLE()) {
c.merkleRoot = bytes32(_random() | 1);
}
if (c.mode == sm.VERIFY_SIGNATURE()) {
c.signer = address(2);
}
assertEq(sm.createEditionMint(c), 0);

uint256 gaPrice = uint96(_bound(_random(), 0, type(uint96).max));
Expand Down Expand Up @@ -982,13 +962,8 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
c.mode = sm.VERIFY_SIGNATURE();
c.endTime = uint32(block.timestamp + 1000);
c.maxMintablePerAccount = type(uint32).max;
if (_random() % 2 == 0) {
c.signer = signer;
} else {
c.signer = address(1);
vm.prank(c.platform);
sm.setPlatformSigner(signer);
}
vm.prank(c.platform);
sm.setPlatformSigner(signer);
assertEq(sm.createEditionMint(c), 0);

ISuperMinterV1_1.MintTo memory p;
Expand Down Expand Up @@ -1075,38 +1050,4 @@ contract SuperMinterV1_1Tests is TestConfigV2_1 {
vm.deal(address(this), type(uint192).max);
sm.mintTo{ value: uint256(p.quantity) * uint256(gaPrice) }(p);
}

function test_setSigner(uint256) public {
address initialSigner = _random() % 2 == 0 ? address(1) : _randomNonZeroAddress();

ISuperMinterV1_1.MintCreation memory c;
c.maxMintable = type(uint32).max;
c.platform = _randomNonZeroAddress();
c.edition = address(edition);
c.tier = uint8(_random() % 2);
c.startTime = 0;
c.mode = sm.VERIFY_SIGNATURE();
c.endTime = uint32(block.timestamp + 1000);
c.maxMintablePerAccount = type(uint32).max;
c.signer = initialSigner;
assertEq(sm.createEditionMint(c), 0);

address platformSigner = _randomNonZeroAddress();
vm.prank(c.platform);
sm.setPlatformSigner(platformSigner);

ISuperMinterV1_1.MintInfo memory info = sm.mintInfo(address(edition), c.tier, 0);
assertEq(info.signer, initialSigner == address(1) ? platformSigner : initialSigner);
assertEq(info.usePlatformSigner, initialSigner == address(1));

for (uint256 i; i != 2; ++i) {
address updatedSigner = _random() % 2 == 0 ? address(1) : _randomNonZeroAddress();
sm.setSigner(address(edition), c.tier, 0, updatedSigner);

info = sm.mintInfo(address(edition), c.tier, 0);
assertEq(info.platform, c.platform);
assertEq(info.signer, updatedSigner == address(1) ? platformSigner : updatedSigner);
assertEq(info.usePlatformSigner, updatedSigner == address(1));
}
}
}

0 comments on commit ee342c1

Please sign in to comment.