From 500f6562df3843cc1169dd983197071c0ab1adee Mon Sep 17 00:00:00 2001 From: yash Date: Thu, 16 Jun 2022 16:55:36 +0530 Subject: [PATCH 01/41] [H-2] Batch reveal is permanently corrupted by invocation of public getRevealURI method --- contracts/feature/DelayedReveal.sol | 5 +---- contracts/signature-drop/SignatureDrop.sol | 1 + src/test/SignatureDrop.t.sol | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/contracts/feature/DelayedReveal.sol b/contracts/feature/DelayedReveal.sol index d1db2638a..82aeb0943 100644 --- a/contracts/feature/DelayedReveal.sol +++ b/contracts/feature/DelayedReveal.sol @@ -13,14 +13,11 @@ abstract contract DelayedReveal is IDelayedReveal { } /// @dev Returns the decrypted i.e. revealed URI for a batch of tokens. - function getRevealURI(uint256 _batchId, bytes calldata _key) public returns (string memory revealedURI) { + function getRevealURI(uint256 _batchId, bytes calldata _key) public view returns (string memory revealedURI) { bytes memory encryptedURI = encryptedBaseURI[_batchId]; require(encryptedURI.length != 0, "nothing to reveal."); revealedURI = string(encryptDecrypt(encryptedURI, _key)); - - // yash - added this, and removed view mutability - delete encryptedBaseURI[_batchId]; } /// @dev See: https://ethereum.stackexchange.com/questions/69825/decrypt-message-on-chain diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index 1f8d1bf34..883a50f09 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -173,6 +173,7 @@ contract SignatureDrop is uint256 batchId = getBatchIdAtIndex(_index); revealedURI = getRevealURI(batchId, _key); + _setEncryptedBaseURI(batchId, ""); _setBaseURI(batchId, revealedURI); emit TokenURIRevealed(_index, revealedURI); diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 4b3a6d6b9..82a0d8a0c 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -897,6 +897,24 @@ contract SignatureDropTest is BaseTest { sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } + /*/////////////////////////////////////////////////////////////// + Miscellaneous + //////////////////////////////////////////////////////////////*/ + function test_breaking_reveal() public { + address attacker = getActor(0); + bytes memory encryptedURI = sigdrop.encryptDecrypt("ipfs://", "key"); + + vm.prank(deployerSigner); + sigdrop.lazyMint(100, "", encryptedURI); + + uint256 batchId = sigdrop.getBatchIdAtIndex(0); + vm.prank(attacker); + sigdrop.getRevealURI(batchId, "wrong keyy"); + + vm.prank(deployerSigner); + sigdrop.reveal(0, "key"); + } + /*/////////////////////////////////////////////////////////////// Reentrancy related Tests //////////////////////////////////////////////////////////////*/ From 382f23c6e1044e9d16dc847577bffbc3c75af81e Mon Sep 17 00:00:00 2001 From: yash Date: Thu, 16 Jun 2022 17:04:09 +0530 Subject: [PATCH 02/41] [L-3] LazyMint of a new batch can affect previous batch --- contracts/signature-drop/SignatureDrop.sol | 1 + src/test/SignatureDrop.t.sol | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index 883a50f09..14860fdf7 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -153,6 +153,7 @@ contract SignatureDrop is string calldata _baseURIForTokens, bytes calldata _encryptedBaseURI ) external onlyRole(MINTER_ROLE) returns (uint256 batchId) { + require(_amount != 0, "Zero amount"); uint256 startId = nextTokenIdToMint; (nextTokenIdToMint, batchId) = _batchMint(startId, _amount, _baseURIForTokens); diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 82a0d8a0c..b3ae884c4 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -915,6 +915,23 @@ contract SignatureDropTest is BaseTest { sigdrop.reveal(0, "key"); } + function test_delayedReveal_withNewLazyMintedEmptyBatch() public { + vm.startPrank(deployerSigner); + + bytes memory encryptedURI = sigdrop.encryptDecrypt("ipfs://", "key"); + sigdrop.lazyMint(100, "", encryptedURI); + sigdrop.reveal(0, "key"); + + string memory uri = sigdrop.tokenURI(1); + assertEq(uri, string(abi.encodePacked("ipfs://", "1"))); + + bytes memory newEncryptedURI = sigdrop.encryptDecrypt("ipfs://secret", "key"); + vm.expectRevert("Zero amount"); + sigdrop.lazyMint(0, "", newEncryptedURI); + + vm.stopPrank(); + } + /*/////////////////////////////////////////////////////////////// Reentrancy related Tests //////////////////////////////////////////////////////////////*/ From 0fb253fce0e728b3400c40f65e1e017a5807c22e Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Thu, 16 Jun 2022 17:27:12 -0400 Subject: [PATCH 03/41] [L-4] Incorrect handling of invalid role approvals/removals in Permissions.sol --- contracts/feature/Permissions.sol | 2 + src/test/SignatureDrop.t.sol | 63 +++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/contracts/feature/Permissions.sol b/contracts/feature/Permissions.sol index d990737d6..227b71892 100644 --- a/contracts/feature/Permissions.sol +++ b/contracts/feature/Permissions.sol @@ -33,6 +33,7 @@ contract Permissions is IPermissions { function grantRole(bytes32 role, address account) public virtual override { _checkRole(_getRoleAdmin[role], msg.sender); + require(!_hasRole[role][account], "Can only grant to non holders"); _setupRole(role, account); } @@ -58,6 +59,7 @@ contract Permissions is IPermissions { } function _revokeRole(bytes32 role, address account) internal virtual { + _checkRole(role, account); delete _hasRole[role][account]; emit RoleRevoked(role, account, msg.sender); } diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index b3ae884c4..6f6a350ac 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import { SignatureDrop } from "contracts/signature-drop/SignatureDrop.sol"; // Test imports +import "contracts/lib/TWStrings.sol"; import "./utils/BaseTest.sol"; import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; @@ -155,6 +156,68 @@ contract SignatureDropTest is BaseTest { domainSeparator = keccak256(abi.encode(typehashEip712, nameHash, versionHash, block.chainid, address(sigdrop))); } + /*/////////////////////////////////////////////////////////////// + Unit tests: misc. + //////////////////////////////////////////////////////////////*/ + + /** + * note: Tests whether contract reverts when a non-holder renounces a role. + */ + function test_revert_nonHolder_renounceRole() public { + + address caller = address(0x123); + bytes32 role = keccak256("MINTER_ROLE"); + + vm.prank(caller); + vm.expectRevert( + abi.encodePacked( + "Permissions: account ", + TWStrings.toHexString(uint160(caller), 20), + " is missing role ", + TWStrings.toHexString(uint256(role), 32) + ) + ); + + sigdrop.renounceRole(role, caller); + } + + /** + * note: Tests whether contract reverts when a role admin revokes a role for a non-holder. + */ + function test_revert_revokeRoleForNonHolder() public { + address target = address(0x123); + bytes32 role = keccak256("MINTER_ROLE"); + + vm.prank(deployerSigner); + vm.expectRevert( + abi.encodePacked( + "Permissions: account ", + TWStrings.toHexString(uint160(target), 20), + " is missing role ", + TWStrings.toHexString(uint256(role), 32) + ) + ); + + sigdrop.revokeRole(role, target); + } + + /** + * @dev Tests whether contract reverts when a role is granted to an existent role holder. + */ + function test_revert_grant_role_to_account_with_role() public { + bytes32 role = keccak256("ABC_ROLE"); + address receiver = getActor(0); + + vm.startPrank(deployerSigner); + + sigdrop.grantRole(role, receiver); + + vm.expectRevert("Can only grant to non holders"); + sigdrop.grantRole(role, receiver); + + vm.stopPrank(); + } + /*/////////////////////////////////////////////////////////////// Lazy Mint Tests //////////////////////////////////////////////////////////////*/ From c7ae40424b72eac1736184249cf45fd06ee1787e Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Thu, 16 Jun 2022 17:42:41 -0400 Subject: [PATCH 04/41] [L-5] Incorrect processing of role approval in PermissionsEnumerable.sol --- contracts/feature/PermissionsEnumerable.sol | 14 ++------------ src/test/SignatureDrop.t.sol | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/contracts/feature/PermissionsEnumerable.sol b/contracts/feature/PermissionsEnumerable.sol index 035bb898f..a5580bc26 100644 --- a/contracts/feature/PermissionsEnumerable.sol +++ b/contracts/feature/PermissionsEnumerable.sol @@ -38,18 +38,8 @@ contract PermissionsEnumerable is IPermissionsEnumerable, Permissions { } } - function grantRole(bytes32 role, address account) public override(IPermissions, Permissions) { - super.grantRole(role, account); - _addMember(role, account); - } - - function revokeRole(bytes32 role, address account) public override(IPermissions, Permissions) { - super.revokeRole(role, account); - _removeMember(role, account); - } - - function renounceRole(bytes32 role, address account) public override(IPermissions, Permissions) { - super.renounceRole(role, account); + function _revokeRole(bytes32 role, address account) internal override { + super._revokeRole(role, account); _removeMember(role, account); } diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 6f6a350ac..6e8d23a9b 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -218,6 +218,27 @@ contract SignatureDropTest is BaseTest { vm.stopPrank(); } + /** + * @dev Tests whether role member count is incremented correctly. + */ + function test_member_count_incremented_properly_when_role_granted() public { + bytes32 role = keccak256("ABC_ROLE"); + address receiver = getActor(0); + + vm.startPrank(deployerSigner); + uint256 roleMemberCount = sigdrop.getRoleMemberCount(role); + + assertEq(roleMemberCount, 0); + + sigdrop.grantRole(role, receiver); + + // fails here since it returns 2 + // because there are 2 calls to PermissionsEnumerable._addMember + assertEq(sigdrop.getRoleMemberCount(role), 1); + + vm.stopPrank(); + } + /*/////////////////////////////////////////////////////////////// Lazy Mint Tests //////////////////////////////////////////////////////////////*/ From 3b34c3dd822a35db5bbf191962b885800a906530 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Thu, 16 Jun 2022 18:05:09 -0400 Subject: [PATCH 05/41] [L-6] claimCondition.startTimestamp is not enforced --- contracts/feature/DropSinglePhase.sol | 3 +++ src/test/SignatureDrop.t.sol | 28 +++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index f79c34748..5c8fbed3f 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -47,6 +47,9 @@ abstract contract DropSinglePhase is IDropSinglePhase { AllowlistProof calldata _allowlistProof, bytes memory _data ) public payable virtual override { + + require(claimCondition.startTimestamp < block.timestamp, "cannot claim yet."); + _beforeClaim(_receiver, _quantity, _currency, _pricePerToken, _allowlistProof, _data); bytes32 activeConditionId = conditionId; diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 6e8d23a9b..3775ff517 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -232,13 +232,37 @@ contract SignatureDropTest is BaseTest { sigdrop.grantRole(role, receiver); - // fails here since it returns 2 - // because there are 2 calls to PermissionsEnumerable._addMember assertEq(sigdrop.getRoleMemberCount(role), 1); vm.stopPrank(); } + function test_claimCondition_with_startTimestamp() public { + vm.warp(1); + + address receiver = getActor(0); + bytes32[] memory proofs = new bytes32[](0); + + SignatureDrop.AllowlistProof memory alp; + alp.proof = proofs; + + SignatureDrop.ClaimCondition[] memory conditions = new SignatureDrop.ClaimCondition[](1); + conditions[0].startTimestamp = 100; + conditions[0].maxClaimableSupply = 100; + conditions[0].quantityLimitPerTransaction = 100; + conditions[0].waitTimeInSecondsBetweenClaims = type(uint256).max; + + vm.prank(deployerSigner); + sigdrop.lazyMint(100, "ipfs://", ""); + + vm.prank(deployerSigner); + sigdrop.setClaimConditions(conditions[0], false); + + vm.prank(getActor(5), getActor(5)); + vm.expectRevert("cannot claim yet."); + sigdrop.claim(receiver, 1, address(0), 0, alp, ""); + } + /*/////////////////////////////////////////////////////////////// Lazy Mint Tests //////////////////////////////////////////////////////////////*/ From 47cd19dd78e8ad693445939c3bba3b1139ef76ce Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Thu, 16 Jun 2022 18:05:41 -0400 Subject: [PATCH 06/41] docs update --- docs/DelayedReveal.md | 2 +- docs/Multiwrap.md | 6 +++--- docs/PermissionsEnumerable.md | 6 +++--- docs/SignatureDrop.md | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/DelayedReveal.md b/docs/DelayedReveal.md index d682fe2fb..8f2aeac85 100644 --- a/docs/DelayedReveal.md +++ b/docs/DelayedReveal.md @@ -58,7 +58,7 @@ function encryptedBaseURI(uint256) external view returns (bytes) ### getRevealURI ```solidity -function getRevealURI(uint256 _batchId, bytes _key) external nonpayable returns (string revealedURI) +function getRevealURI(uint256 _batchId, bytes _key) external view returns (string revealedURI) ``` diff --git a/docs/Multiwrap.md b/docs/Multiwrap.md index 332f7930c..a2a5678b3 100644 --- a/docs/Multiwrap.md +++ b/docs/Multiwrap.md @@ -344,7 +344,7 @@ function grantRole(bytes32 role, address account) external nonpayable - +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* #### Parameters @@ -646,7 +646,7 @@ function renounceRole(bytes32 role, address account) external nonpayable - +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* #### Parameters @@ -663,7 +663,7 @@ function revokeRole(bytes32 role, address account) external nonpayable - +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* #### Parameters diff --git a/docs/PermissionsEnumerable.md b/docs/PermissionsEnumerable.md index 0f46e6af5..e7c2ccd45 100644 --- a/docs/PermissionsEnumerable.md +++ b/docs/PermissionsEnumerable.md @@ -102,7 +102,7 @@ function grantRole(bytes32 role, address account) external nonpayable - +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* #### Parameters @@ -165,7 +165,7 @@ function renounceRole(bytes32 role, address account) external nonpayable - +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* #### Parameters @@ -182,7 +182,7 @@ function revokeRole(bytes32 role, address account) external nonpayable - +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* #### Parameters diff --git a/docs/SignatureDrop.md b/docs/SignatureDrop.md index 461c3f153..6820e2ac5 100644 --- a/docs/SignatureDrop.md +++ b/docs/SignatureDrop.md @@ -346,7 +346,7 @@ function getPlatformFeeInfo() external view returns (address, uint16) ### getRevealURI ```solidity -function getRevealURI(uint256 _batchId, bytes _key) external nonpayable returns (string revealedURI) +function getRevealURI(uint256 _batchId, bytes _key) external view returns (string revealedURI) ``` @@ -464,7 +464,7 @@ function grantRole(bytes32 role, address account) external nonpayable - +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* #### Parameters @@ -778,7 +778,7 @@ function renounceRole(bytes32 role, address account) external nonpayable - +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* #### Parameters @@ -818,7 +818,7 @@ function revokeRole(bytes32 role, address account) external nonpayable - +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* #### Parameters From 88d2fd9e946dff65fa11b36cb8e497fe4e820d67 Mon Sep 17 00:00:00 2001 From: yash Date: Sat, 18 Jun 2022 00:15:24 +0530 Subject: [PATCH 07/41] reduce size by merging checks --- contracts/feature/DropSinglePhase.sol | 4 +--- lib/forge-std | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index 5c8fbed3f..07b2bbc8f 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -48,8 +48,6 @@ abstract contract DropSinglePhase is IDropSinglePhase { bytes memory _data ) public payable virtual override { - require(claimCondition.startTimestamp < block.timestamp, "cannot claim yet."); - _beforeClaim(_receiver, _quantity, _currency, _pricePerToken, _allowlistProof, _data); bytes32 activeConditionId = conditionId; @@ -152,7 +150,7 @@ abstract contract DropSinglePhase is IDropSinglePhase { ); (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); - require(lastClaimedAt == 0 || block.timestamp >= nextValidClaimTimestamp, "cannot claim."); + require(claimCondition.startTimestamp < block.timestamp && (lastClaimedAt == 0 || block.timestamp >= nextValidClaimTimestamp), "cannot claim yet."); } /// @dev Checks whether a claimer meets the claim condition's allowlist criteria. diff --git a/lib/forge-std b/lib/forge-std index 1680d7fb3..0d0485bde 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 1680d7fb3e00b7b197a7336e7c88e838c7e6a3ec +Subproject commit 0d0485bdea9f9455bd684acb0ba88548a104d99b From 96faa032ffea0848979fe56845ea58fca55e1297 Mon Sep 17 00:00:00 2001 From: yash Date: Sat, 18 Jun 2022 00:19:47 +0530 Subject: [PATCH 08/41] update tests --- src/test/SignatureDrop.t.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 3775ff517..6b86fb099 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -433,6 +433,7 @@ contract SignatureDropTest is BaseTest { * note: Fuzz testing; a batch of tokens, and nextTokenIdToMint */ function test_fuzz_lazyMint_batchMintAndNextTokenIdToMint(uint256 x) public { + vm.assume(x > 0); vm.startPrank(deployerSigner); sigdrop.lazyMint(x, "ipfs://", ""); @@ -867,7 +868,7 @@ contract SignatureDropTest is BaseTest { vm.prank(getActor(5), getActor(5)); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); - vm.expectRevert("cannot claim."); + vm.expectRevert("cannot claim yet."); vm.prank(getActor(5), getActor(5)); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } From ac789394c99342f6e56497b14768a22e53061143 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Fri, 17 Jun 2022 16:33:58 -0400 Subject: [PATCH 09/41] [Q-1] Emitted TokensLazyMinted event does not match spec --- contracts/signature-drop/SignatureDrop.sol | 2 +- src/test/SignatureDrop.t.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index 14860fdf7..c1949ee92 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -162,7 +162,7 @@ contract SignatureDrop is _setEncryptedBaseURI(batchId, _encryptedBaseURI); } - emit TokensLazyMinted(startId, startId + _amount, _baseURIForTokens, _encryptedBaseURI); + emit TokensLazyMinted(startId, startId + _amount - 1, _baseURIForTokens, _encryptedBaseURI); } /// @dev Lets an account with `MINTER_ROLE` reveal the URI for a batch of 'delayed-reveal' NFTs. diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 3775ff517..a7a7e4c92 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -352,7 +352,7 @@ contract SignatureDropTest is BaseTest { vm.startPrank(deployerSigner); vm.expectEmit(false, false, false, true); - emit TokensLazyMinted(0, 100, "ipfs://", ""); + emit TokensLazyMinted(0, 99, "ipfs://", ""); sigdrop.lazyMint(100, "ipfs://", ""); vm.stopPrank(); From e8b824ced179ff8d09762d7f6312e3296137727d Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Fri, 17 Jun 2022 16:36:12 -0400 Subject: [PATCH 10/41] [L-3] test fix --- src/test/SignatureDrop.t.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index a7a7e4c92..6f45163e1 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -435,6 +435,9 @@ contract SignatureDropTest is BaseTest { function test_fuzz_lazyMint_batchMintAndNextTokenIdToMint(uint256 x) public { vm.startPrank(deployerSigner); + if(x == 0) { + vm.expectRevert("Zero amount"); + } sigdrop.lazyMint(x, "ipfs://", ""); uint256 slot = stdstore.target(address(sigdrop)).sig("nextTokenIdToMint()").find(); From 076687de665b1d505ebbb2b2d777ed34b81d30bc Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Fri, 17 Jun 2022 16:41:32 -0400 Subject: [PATCH 11/41] [Q-3] Some events could use indexed attributes --- contracts/feature/LazyMintERC721.sol | 2 +- contracts/feature/interface/IDropSinglePhase.sol | 2 +- contracts/feature/interface/IOwnable.sol | 2 +- contracts/feature/interface/IPlatformFee.sol | 2 +- contracts/feature/interface/IRoyalty.sol | 4 ++-- contracts/signature-drop/SignatureDrop.sol | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/feature/LazyMintERC721.sol b/contracts/feature/LazyMintERC721.sol index 793b0a8a2..265c8975c 100644 --- a/contracts/feature/LazyMintERC721.sol +++ b/contracts/feature/LazyMintERC721.sol @@ -7,7 +7,7 @@ import "../lib/TWStrings.sol"; abstract contract LazyMintERC721 is LazyMint { using TWStrings for uint256; - event TokensLazyMinted(uint256 startTokenId, uint256 endTokenId, string baseURI, bytes extraData); + event TokensLazyMinted(uint256 indexed startTokenId, uint256 endTokenId, string baseURI, bytes extraData); /// @dev the next available non-minted token id uint256 public nextTokenIdToMint; diff --git a/contracts/feature/interface/IDropSinglePhase.sol b/contracts/feature/interface/IDropSinglePhase.sol index a9342e8ed..1bcd18902 100644 --- a/contracts/feature/interface/IDropSinglePhase.sol +++ b/contracts/feature/interface/IDropSinglePhase.sol @@ -12,7 +12,7 @@ interface IDropSinglePhase is IClaimCondition { event TokensClaimed( address indexed claimer, address indexed receiver, - uint256 startTokenId, + uint256 indexed startTokenId, uint256 quantityClaimed ); diff --git a/contracts/feature/interface/IOwnable.sol b/contracts/feature/interface/IOwnable.sol index 05b5a7eb5..82a6677db 100644 --- a/contracts/feature/interface/IOwnable.sol +++ b/contracts/feature/interface/IOwnable.sol @@ -9,5 +9,5 @@ interface IOwnable { function setOwner(address _newOwner) external; /// @dev Emitted when a new Owner is set. - event OwnerUpdated(address prevOwner, address newOwner); + event OwnerUpdated(address indexed prevOwner, address indexed newOwner); } diff --git a/contracts/feature/interface/IPlatformFee.sol b/contracts/feature/interface/IPlatformFee.sol index 0ae86394e..2d60b9a60 100644 --- a/contracts/feature/interface/IPlatformFee.sol +++ b/contracts/feature/interface/IPlatformFee.sol @@ -9,5 +9,5 @@ interface IPlatformFee { function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external; /// @dev Emitted when fee on primary sales is updated. - event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps); + event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps); } diff --git a/contracts/feature/interface/IRoyalty.sol b/contracts/feature/interface/IRoyalty.sol index 708b82837..e1c91c7e1 100644 --- a/contracts/feature/interface/IRoyalty.sol +++ b/contracts/feature/interface/IRoyalty.sol @@ -33,8 +33,8 @@ interface IRoyalty { returns (address receiver, uint256 royaltyAmount); /// @dev Emitted when royalty info is updated. - event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps); + event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps); /// @dev Emitted when royalty recipient for tokenId is set - event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 royaltyBps); + event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps); } diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index c1949ee92..de5eec0a7 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -67,8 +67,8 @@ contract SignatureDrop is Events //////////////////////////////////////////////////////////////*/ - event TokensLazyMinted(uint256 startTokenId, uint256 endTokenId, string baseURI, bytes encryptedBaseURI); - event TokenURIRevealed(uint256 index, string revealedURI); + event TokensLazyMinted(uint256 indexed startTokenId, uint256 endTokenId, string baseURI, bytes encryptedBaseURI); + event TokenURIRevealed(uint256 indexed index, string revealedURI); /*/////////////////////////////////////////////////////////////// Constructor + initializer logic From ba4e4fe7054e0d5cc74c567ff37851429993d0ac Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Fri, 17 Jun 2022 16:47:08 -0400 Subject: [PATCH 12/41] [Q-5] Visibility for following methods can be changed from public to external --- contracts/feature/Permissions.sol | 2 +- contracts/signature-drop/SignatureDrop.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/feature/Permissions.sol b/contracts/feature/Permissions.sol index 227b71892..a00d02d51 100644 --- a/contracts/feature/Permissions.sol +++ b/contracts/feature/Permissions.sol @@ -27,7 +27,7 @@ contract Permissions is IPermissions { return true; } - function getRoleAdmin(bytes32 role) public view override returns (bytes32) { + function getRoleAdmin(bytes32 role) external view override returns (bytes32) { return _getRoleAdmin[role]; } diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index de5eec0a7..69d920755 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -310,7 +310,7 @@ contract SignatureDrop is //////////////////////////////////////////////////////////////*/ /// @dev Burns `tokenId`. See {ERC721-_burn}. - function burn(uint256 tokenId) public virtual { + function burn(uint256 tokenId) external virtual { // note: ERC721AUpgradeable's `_burn(uint256,bool)` internally checks for token approvals. _burn(tokenId, true); } From 83c99cfe018bf2fe9a09731b3bb075e6327dbdd2 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Fri, 17 Jun 2022 17:17:38 -0400 Subject: [PATCH 13/41] [Q-4] Missing natspec comments --- contracts/feature/ContractMetadata.sol | 7 +++++++ contracts/feature/DelayedReveal.sol | 5 +++++ contracts/feature/LazyMint.sol | 6 ++++++ contracts/feature/Ownable.sol | 6 ++++++ contracts/feature/PlatformFee.sol | 6 ++++++ contracts/feature/PrimarySale.sol | 6 ++++++ contracts/feature/Royalty.sol | 8 +++++++ .../feature/interface/IContractMetadata.sol | 8 +++++++ .../feature/interface/IDelayedReveal.sol | 21 +++++++++++++++++++ .../feature/interface/IDropSinglePhase.sol | 2 ++ contracts/feature/interface/ILazyMint.sol | 19 +++++++++++++++++ contracts/feature/interface/IOwnable.sol | 6 ++++++ contracts/feature/interface/IPermissions.sol | 6 ++++++ contracts/feature/interface/IPlatformFee.sol | 6 ++++++ contracts/feature/interface/IPrimarySale.sol | 6 ++++++ contracts/feature/interface/IRoyalty.sol | 8 +++++++ 16 files changed, 126 insertions(+) diff --git a/contracts/feature/ContractMetadata.sol b/contracts/feature/ContractMetadata.sol index 70f9070d9..3478b74c0 100644 --- a/contracts/feature/ContractMetadata.sol +++ b/contracts/feature/ContractMetadata.sol @@ -3,6 +3,13 @@ pragma solidity ^0.8.0; import "./interface/IContractMetadata.sol"; +/** + * Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI + * for you contract. + * + * Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea. + */ + abstract contract ContractMetadata is IContractMetadata { /// @dev Contract level metadata. string public override contractURI; diff --git a/contracts/feature/DelayedReveal.sol b/contracts/feature/DelayedReveal.sol index 82aeb0943..e8ea6580a 100644 --- a/contracts/feature/DelayedReveal.sol +++ b/contracts/feature/DelayedReveal.sol @@ -3,6 +3,11 @@ pragma solidity ^0.8.0; import "./interface/IDelayedReveal.sol"; +/** + * Thirdweb's `DelayedReveal` is a contract extension for base NFT contracts. It lets you create batches of + * 'delayed-reveal' NFTs. You can learn more about the usage of delayed reveal NFTs here - https://blog.thirdweb.com/delayed-reveal-nfts + */ + abstract contract DelayedReveal is IDelayedReveal { /// @dev Mapping from id of a batch of tokens => to encrypted base URI for the respective batch of tokens. mapping(uint256 => bytes) public encryptedBaseURI; diff --git a/contracts/feature/LazyMint.sol b/contracts/feature/LazyMint.sol index 46762492e..6916296d4 100644 --- a/contracts/feature/LazyMint.sol +++ b/contracts/feature/LazyMint.sol @@ -3,6 +3,12 @@ pragma solidity ^0.8.0; import "./interface/ILazyMint.sol"; +/** + * Thirdweb's `LazyMint` is a contract extension for any base NFT contract. It lets you 'lazy mint' any number of NFTs + * at once. Here, 'lazy mint' means defining the metadata for particular tokenIds of your NFT contract, without actually + * minting a non-zero balance of NFTs of those tokenIds. + */ + abstract contract LazyMint is ILazyMint { /// @dev Largest tokenId of each batch of tokens with the same baseURI. uint256[] private batchIds; diff --git a/contracts/feature/Ownable.sol b/contracts/feature/Ownable.sol index d1ad3fc36..3a23699f6 100644 --- a/contracts/feature/Ownable.sol +++ b/contracts/feature/Ownable.sol @@ -3,6 +3,12 @@ pragma solidity ^0.8.0; import "./interface/IOwnable.sol"; +/** + * Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses + * information about who the contract's owner is. + */ + abstract contract Ownable is IOwnable { /// @dev Owner of the contract (purpose: OpenSea compatibility) address public override owner; diff --git a/contracts/feature/PlatformFee.sol b/contracts/feature/PlatformFee.sol index f2669a34d..f3c0f4837 100644 --- a/contracts/feature/PlatformFee.sol +++ b/contracts/feature/PlatformFee.sol @@ -3,6 +3,12 @@ pragma solidity ^0.8.0; import "./interface/IPlatformFee.sol"; +/** + * Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * the recipient of platform fee and the platform fee basis points, and lets the inheriting contract perform conditional logic + * that uses information about platform fees, if desired. + */ + abstract contract PlatformFee is IPlatformFee { /// @dev The address that receives all platform fees from all sales. address private platformFeeRecipient; diff --git a/contracts/feature/PrimarySale.sol b/contracts/feature/PrimarySale.sol index 4f5cc543c..44358b81a 100644 --- a/contracts/feature/PrimarySale.sol +++ b/contracts/feature/PrimarySale.sol @@ -3,6 +3,12 @@ pragma solidity ^0.8.0; import "./interface/IPrimarySale.sol"; +/** + * Thirdweb's `Primary` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * the recipient of primary sales, and lets the inheriting contract perform conditional logic that uses information about + * primary sales, if desired. + */ + abstract contract PrimarySale is IPrimarySale { /// @dev The address that receives all primary sales value. address private recipient; diff --git a/contracts/feature/Royalty.sol b/contracts/feature/Royalty.sol index 4986fde2a..47235c671 100644 --- a/contracts/feature/Royalty.sol +++ b/contracts/feature/Royalty.sol @@ -3,6 +3,14 @@ pragma solidity ^0.8.0; import "./interface/IRoyalty.sol"; +/** + * Thirdweb's `Royalty` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * the recipient of royalty fee and the royalty fee basis points, and lets the inheriting contract perform conditional logic + * that uses information about royalty fees, if desired. + * + * The `Royalty` contract is ERC2981 compliant. + */ + abstract contract Royalty is IRoyalty { /// @dev The (default) address that receives all royalty value. address private royaltyRecipient; diff --git a/contracts/feature/interface/IContractMetadata.sol b/contracts/feature/interface/IContractMetadata.sol index bf61c4979..b4200ea9b 100644 --- a/contracts/feature/interface/IContractMetadata.sol +++ b/contracts/feature/interface/IContractMetadata.sol @@ -1,6 +1,13 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; +/** + * Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI + * for you contract. + * + * Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea. + */ + interface IContractMetadata { /// @dev Returns the metadata URI of the contract. function contractURI() external view returns (string memory); @@ -11,5 +18,6 @@ interface IContractMetadata { */ function setContractURI(string calldata _uri) external; + /// @dev Emitted when the contract URI is updated. event ContractURIUpdated(string prevURI, string newURI); } diff --git a/contracts/feature/interface/IDelayedReveal.sol b/contracts/feature/interface/IDelayedReveal.sol index 51d96ff7f..50795c645 100644 --- a/contracts/feature/interface/IDelayedReveal.sol +++ b/contracts/feature/interface/IDelayedReveal.sol @@ -1,8 +1,29 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; +/** + * Thirdweb's `DelayedReveal` is a contract extension for base NFT contracts. It lets you create batches of + * 'delayed-reveal' NFTs. You can learn more about the usage of delayed reveal NFTs here - https://blog.thirdweb.com/delayed-reveal-nfts + */ + interface IDelayedReveal { + + /** + * @notice Reveals a batch of delayed reveal NFTs. + * + * @param identifier The ID for the batch of delayed-reveal NFTs to reveal. + * + * @param key The key with which the base URI for the relevant batch of NFTs was encrypted. + */ function reveal(uint256 identifier, bytes calldata key) external returns (string memory revealedURI); + /** + * @notice Performs XOR encryption/decryption. + * + * @param data The data to encrypt. In the case of delayed-reveal NFTs, this is the "revealed" state + * base URI of the relevant batch of NFTs. + * + * @param key The key with which to encrypt data + */ function encryptDecrypt(bytes memory data, bytes calldata key) external pure returns (bytes memory result); } diff --git a/contracts/feature/interface/IDropSinglePhase.sol b/contracts/feature/interface/IDropSinglePhase.sol index 1bcd18902..82d71e69c 100644 --- a/contracts/feature/interface/IDropSinglePhase.sol +++ b/contracts/feature/interface/IDropSinglePhase.sol @@ -9,6 +9,7 @@ interface IDropSinglePhase is IClaimCondition { uint256 maxQuantityInAllowlist; } + /// @dev Emitted when tokens are claimed via `claim`. event TokensClaimed( address indexed claimer, address indexed receiver, @@ -16,6 +17,7 @@ interface IDropSinglePhase is IClaimCondition { uint256 quantityClaimed ); + /// @dev Emitted when the contract's claim conditions are updated. event ClaimConditionUpdated(ClaimCondition condition, bool resetEligibility); /** diff --git a/contracts/feature/interface/ILazyMint.sol b/contracts/feature/interface/ILazyMint.sol index 924268c97..bc5eda7f0 100644 --- a/contracts/feature/interface/ILazyMint.sol +++ b/contracts/feature/interface/ILazyMint.sol @@ -1,7 +1,26 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; +/** + * Thirdweb's `LazyMint` is a contract extension for any base NFT contract. It lets you 'lazy mint' any number of NFTs + * at once. Here, 'lazy mint' means defining the metadata for particular tokenIds of your NFT contract, without actually + * minting a non-zero balance of NFTs of those tokenIds. + */ + interface ILazyMint { + + /** + * @notice Lazy mints a given amount of NFTs. + * + * @param amount The number of NFTs to lazy mint. + * + * @param baseURIForTokens The base URI for the 'n' number of NFTs being lazy minted, where the metadata for each + * of those NFTs is `${baseURIForTokens}/${tokenId}`. + * + * @param extraData Additional bytes data to be used at the discretion of the consumer of the contract. + * + * @return batchId A unique integer identifier for the batch of NFTs lazy minted together. + */ function lazyMint( uint256 amount, string calldata baseURIForTokens, diff --git a/contracts/feature/interface/IOwnable.sol b/contracts/feature/interface/IOwnable.sol index 82a6677db..f983e2649 100644 --- a/contracts/feature/interface/IOwnable.sol +++ b/contracts/feature/interface/IOwnable.sol @@ -1,6 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; +/** + * Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses + * information about who the contract's owner is. + */ + interface IOwnable { /// @dev Returns the owner of the contract. function owner() external view returns (address); diff --git a/contracts/feature/interface/IPermissions.sol b/contracts/feature/interface/IPermissions.sol index bee59b57d..097209a26 100644 --- a/contracts/feature/interface/IPermissions.sol +++ b/contracts/feature/interface/IPermissions.sol @@ -37,6 +37,12 @@ interface IPermissions { */ function hasRole(bytes32 role, address account) external view returns (bool); + /** + * @dev Returns `true` if either (1) `account` has been granted `role`, or (2) the relevant role restrictions + * do not apply at the time of calling this function. + */ + function hasRoleWithSwitch(bytes32 role, address account) external view returns (bool); + /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. diff --git a/contracts/feature/interface/IPlatformFee.sol b/contracts/feature/interface/IPlatformFee.sol index 2d60b9a60..4b65aa30d 100644 --- a/contracts/feature/interface/IPlatformFee.sol +++ b/contracts/feature/interface/IPlatformFee.sol @@ -1,6 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; +/** + * Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * the recipient of platform fee and the platform fee basis points, and lets the inheriting contract perform conditional logic + * that uses information about platform fees, if desired. + */ + interface IPlatformFee { /// @dev Returns the platform fee bps and recipient. function getPlatformFeeInfo() external view returns (address, uint16); diff --git a/contracts/feature/interface/IPrimarySale.sol b/contracts/feature/interface/IPrimarySale.sol index af9de95cf..6a28e9e93 100644 --- a/contracts/feature/interface/IPrimarySale.sol +++ b/contracts/feature/interface/IPrimarySale.sol @@ -1,6 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; +/** + * Thirdweb's `Primary` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * the recipient of primary sales, and lets the inheriting contract perform conditional logic that uses information about + * primary sales, if desired. + */ + interface IPrimarySale { /// @dev The adress that receives all primary sales value. function primarySaleRecipient() external view returns (address); diff --git a/contracts/feature/interface/IRoyalty.sol b/contracts/feature/interface/IRoyalty.sol index e1c91c7e1..33cfd082e 100644 --- a/contracts/feature/interface/IRoyalty.sol +++ b/contracts/feature/interface/IRoyalty.sol @@ -1,6 +1,14 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; +/** + * Thirdweb's `Royalty` is a contract extension to be used with any base contract. It exposes functions for setting and reading + * the recipient of royalty fee and the royalty fee basis points, and lets the inheriting contract perform conditional logic + * that uses information about royalty fees, if desired. + * + * The `Royalty` contract is ERC2981 compliant. + */ + interface IRoyalty { struct RoyaltyInfo { address recipient; From 0480543f56fb66af0063ac53db71053a32e8998c Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Fri, 17 Jun 2022 17:42:58 -0400 Subject: [PATCH 14/41] [Q-3] test fixes --- lib/forge-std | 2 +- src/test/SignatureDrop.t.sol | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/forge-std b/lib/forge-std index 0d0485bde..1680d7fb3 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 0d0485bdea9f9455bd684acb0ba88548a104d99b +Subproject commit 1680d7fb3e00b7b197a7336e7c88e838c7e6a3ec diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index fa250fb03..7d21abed6 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -118,8 +118,8 @@ contract SignatureDropBenchmarkTest is BaseTest { contract SignatureDropTest is BaseTest { using StringsUpgradeable for uint256; - event TokensLazyMinted(uint256 startTokenId, uint256 endTokenId, string baseURI, bytes encryptedBaseURI); - event TokenURIRevealed(uint256 index, string revealedURI); + event TokensLazyMinted(uint256 indexed startTokenId, uint256 endTokenId, string baseURI, bytes encryptedBaseURI); + event TokenURIRevealed(uint256 indexed index, string revealedURI); event TokensMintedWithSignature( address indexed signer, address indexed mintedTo, @@ -351,7 +351,7 @@ contract SignatureDropTest is BaseTest { function test_event_lazyMint_TokensLazyMinted() public { vm.startPrank(deployerSigner); - vm.expectEmit(false, false, false, true); + vm.expectEmit(true, false, false, true); emit TokensLazyMinted(0, 99, "ipfs://", ""); sigdrop.lazyMint(100, "ipfs://", ""); @@ -563,7 +563,7 @@ contract SignatureDropTest is BaseTest { bytes memory encryptedURI = sigdrop.encryptDecrypt("ipfs://", "key"); sigdrop.lazyMint(100, "", encryptedURI); - vm.expectEmit(false, false, false, true); + vm.expectEmit(true, false, false, true); emit TokenURIRevealed(0, "ipfs://"); sigdrop.reveal(0, "key"); From ae883c26b481caedb985c8a47022bc3398b38cc3 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Fri, 17 Jun 2022 17:44:15 -0400 Subject: [PATCH 15/41] forge updates --- lib/forge-std | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/forge-std b/lib/forge-std index 1680d7fb3..0d0485bde 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 1680d7fb3e00b7b197a7336e7c88e838c7e6a3ec +Subproject commit 0d0485bdea9f9455bd684acb0ba88548a104d99b From 83b8fd97b54f3983174e78d7ce22478b0bc0e9c4 Mon Sep 17 00:00:00 2001 From: Yash Date: Tue, 21 Jun 2022 15:36:27 +0530 Subject: [PATCH 16/41] fix claim quantity limit --- .DS_Store | Bin 0 -> 8196 bytes contracts/feature/DropSinglePhase.sol | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..12b3a78626ddcd7cc21bbfb67c76e8ae16773236 GIT binary patch literal 8196 zcmeHM&2AGh5dPdG&@F#0Tq-1_eE}lz21!W|k$?kz0LWj{kZl6VMxqy#JMX|N@MhdO z!8c=rY;X34M5Nl0J=@*+X2ze#yBZgOIoph10H**B*+m}TwZzuPB#(*iGjpGVjwY)7}y5}_|2AfSo7VtPt%wfNDSOc2IT#avy1FFxwTSX z9UQa-pltHCHeRz1P)zP*$H}dg3Z+e3Js1ZyuEa1F&gZ$PQ+Ax(T4~`h77pV)8&{zi z^-f%_>M$KE)0h}Y3{)AA+C5{{zGBrr^XvEJXjm+Vd@38N%ijK_jaR^+os@hN-0))8KzkC!;d8(eT~Gq!Pr5&nEkMxB8&K2t_k z@fsx)b#3MxnJ0M8*klFf^!I@o!SxG$f_#{V0gs`D8l2=&fXncfv+AOU*EO?a zJ_U#)vOZya6UHjJ+U9r_MrX)KfH_voCv3>Lps(2_BiBTi_>3~d3qJw=E;UC)&d5_` zWhJM~7mtf4)Rwg^Wp@x2=Vd*kzLf^8tS|~AQ~rFd7QF}$^LV#NCPh)neC=NRvqOf; zNWm verifyClaimMerkleProof will verify the maxQuantityInAllowlist value with hashed leaf in the allowlist + // when there's no allowlist, this check is true --> verifyClaim will check for _quantity being equal/less than the limit + bool toVerifyMaxQuantityPerTransaction = _allowlistProof.maxQuantityInAllowlist == 0 || claimCondition.merkleRoot == bytes32(0); verifyClaim(_dropMsgSender(), _quantity, _currency, _pricePerToken, toVerifyMaxQuantityPerTransaction); From bc93d4f1286f504ccaa472eface614d88e16d581 Mon Sep 17 00:00:00 2001 From: Yash Date: Tue, 21 Jun 2022 15:55:55 +0530 Subject: [PATCH 17/41] add test --- src/test/SignatureDrop.t.sol | 45 +++++++++++++++++++++++++++++--- src/test/scripts/generateRoot.ts | 4 ++- src/test/scripts/getProof.ts | 6 +++-- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 7d21abed6..2ed78416d 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -933,14 +933,52 @@ contract SignatureDropTest is BaseTest { sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } + /** + * note: Testing quantity limit restriction when no allowlist present. + */ + function test_fuzz_claim_noAllowlist(uint256 x) public { + vm.assume(x != 0); + vm.warp(1); + + address receiver = getActor(0); + bytes32[] memory proofs = new bytes32[](0); + + SignatureDrop.AllowlistProof memory alp; + alp.proof = proofs; + alp.maxQuantityInAllowlist = x; + + SignatureDrop.ClaimCondition[] memory conditions = new SignatureDrop.ClaimCondition[](1); + conditions[0].maxClaimableSupply = 500; + conditions[0].quantityLimitPerTransaction = 100; + conditions[0].waitTimeInSecondsBetweenClaims = type(uint256).max; + + vm.prank(deployerSigner); + sigdrop.lazyMint(500, "ipfs://", bytes("")); + + vm.prank(deployerSigner); + sigdrop.setClaimConditions(conditions[0], false); + + vm.prank(getActor(5)); + vm.expectRevert("invalid quantity."); + sigdrop.claim(receiver, 101, address(0), 0, alp, ""); + + vm.prank(deployerSigner); + sigdrop.setClaimConditions(conditions[0], true); + + vm.prank(getActor(5)); + vm.expectRevert("invalid quantity."); + sigdrop.claim(receiver, 101, address(0), 0, alp, ""); + } + /** * note: Testing revert condition; can't claim if not in whitelist. */ function test_revert_claimCondition_merkleProof() public { - string[] memory inputs = new string[](2); + string[] memory inputs = new string[](3); inputs[0] = "node"; inputs[1] = "src/test/scripts/generateRoot.ts"; + inputs[2] = "1"; bytes memory result = vm.ffi(inputs); bytes32 root = abi.decode(result, (bytes32)); @@ -955,6 +993,7 @@ contract SignatureDropTest is BaseTest { SignatureDrop.AllowlistProof memory alp; alp.proof = proofs; + alp.maxQuantityInAllowlist = 1; SignatureDrop.ClaimCondition[] memory conditions = new SignatureDrop.ClaimCondition[](1); conditions[0].maxClaimableSupply = 100; @@ -969,11 +1008,11 @@ contract SignatureDropTest is BaseTest { // vm.prank(getActor(5), getActor(5)); vm.prank(receiver); - sigdrop.claim(receiver, 100, address(0), 0, alp, ""); + sigdrop.claim(receiver, 1, address(0), 0, alp, ""); vm.prank(address(4)); vm.expectRevert("not in whitelist."); - sigdrop.claim(receiver, 100, address(0), 0, alp, ""); + sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } /** diff --git a/src/test/scripts/generateRoot.ts b/src/test/scripts/generateRoot.ts index 5626bf4d9..e337af0cc 100644 --- a/src/test/scripts/generateRoot.ts +++ b/src/test/scripts/generateRoot.ts @@ -8,7 +8,9 @@ const members = [ "0xFD78F7E2dF2B8c3D5bff0413c96f3237500898B3", ]; -const hashedLeafs = members.map(l => ethers.utils.solidityKeccak256(["address", "uint256"], [l, 0])); +let val = process.argv[2]; + +const hashedLeafs = members.map(l => ethers.utils.solidityKeccak256(["address", "uint256"], [l, val])); const tree = new MerkleTree(hashedLeafs, keccak256, { sort: true, diff --git a/src/test/scripts/getProof.ts b/src/test/scripts/getProof.ts index e4c32afbe..b7c450fce 100644 --- a/src/test/scripts/getProof.ts +++ b/src/test/scripts/getProof.ts @@ -8,7 +8,9 @@ const members = [ "0xFD78F7E2dF2B8c3D5bff0413c96f3237500898B3", ]; -const hashedLeafs = members.map(l => ethers.utils.solidityKeccak256(["address", "uint256"], [l, 0])); +let val = process.argv[2]; + +const hashedLeafs = members.map(l => ethers.utils.solidityKeccak256(["address", "uint256"], [l, val])); const tree = new MerkleTree(hashedLeafs, keccak256, { sort: true, @@ -16,6 +18,6 @@ const tree = new MerkleTree(hashedLeafs, keccak256, { sortPairs: true, }); -const expectedProof = tree.getHexProof(ethers.utils.solidityKeccak256(["address", "uint256"], [members[0], 0])); +const expectedProof = tree.getHexProof(ethers.utils.solidityKeccak256(["address", "uint256"], [members[0], val])); process.stdout.write(ethers.utils.defaultAbiCoder.encode(["bytes32[]"], [expectedProof])); From 3109c5a0cd757a2a88b7afa29d64c71c16f61ffc Mon Sep 17 00:00:00 2001 From: Yash Date: Tue, 21 Jun 2022 15:57:18 +0530 Subject: [PATCH 18/41] run prettier --- contracts/feature/DropSinglePhase.sol | 10 +++++++--- contracts/feature/interface/IDelayedReveal.sol | 1 - contracts/feature/interface/ILazyMint.sol | 3 +-- src/test/SignatureDrop.t.sol | 3 +-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index c24514dcf..575588d37 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -47,7 +47,6 @@ abstract contract DropSinglePhase is IDropSinglePhase { AllowlistProof calldata _allowlistProof, bytes memory _data ) public payable virtual override { - _beforeClaim(_receiver, _quantity, _currency, _pricePerToken, _allowlistProof, _data); bytes32 activeConditionId = conditionId; @@ -69,7 +68,8 @@ abstract contract DropSinglePhase is IDropSinglePhase { // Verify claim validity. If not valid, revert. // when there's allowlist present --> verifyClaimMerkleProof will verify the maxQuantityInAllowlist value with hashed leaf in the allowlist // when there's no allowlist, this check is true --> verifyClaim will check for _quantity being equal/less than the limit - bool toVerifyMaxQuantityPerTransaction = _allowlistProof.maxQuantityInAllowlist == 0 || claimCondition.merkleRoot == bytes32(0); + bool toVerifyMaxQuantityPerTransaction = _allowlistProof.maxQuantityInAllowlist == 0 || + claimCondition.merkleRoot == bytes32(0); verifyClaim(_dropMsgSender(), _quantity, _currency, _pricePerToken, toVerifyMaxQuantityPerTransaction); @@ -152,7 +152,11 @@ abstract contract DropSinglePhase is IDropSinglePhase { ); (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); - require(claimCondition.startTimestamp < block.timestamp && (lastClaimedAt == 0 || block.timestamp >= nextValidClaimTimestamp), "cannot claim yet."); + require( + claimCondition.startTimestamp < block.timestamp && + (lastClaimedAt == 0 || block.timestamp >= nextValidClaimTimestamp), + "cannot claim yet." + ); } /// @dev Checks whether a claimer meets the claim condition's allowlist criteria. diff --git a/contracts/feature/interface/IDelayedReveal.sol b/contracts/feature/interface/IDelayedReveal.sol index 50795c645..34cf16498 100644 --- a/contracts/feature/interface/IDelayedReveal.sol +++ b/contracts/feature/interface/IDelayedReveal.sol @@ -7,7 +7,6 @@ pragma solidity ^0.8.0; */ interface IDelayedReveal { - /** * @notice Reveals a batch of delayed reveal NFTs. * diff --git a/contracts/feature/interface/ILazyMint.sol b/contracts/feature/interface/ILazyMint.sol index bc5eda7f0..1dbfe0a1f 100644 --- a/contracts/feature/interface/ILazyMint.sol +++ b/contracts/feature/interface/ILazyMint.sol @@ -8,7 +8,6 @@ pragma solidity ^0.8.0; */ interface ILazyMint { - /** * @notice Lazy mints a given amount of NFTs. * @@ -20,7 +19,7 @@ interface ILazyMint { * @param extraData Additional bytes data to be used at the discretion of the consumer of the contract. * * @return batchId A unique integer identifier for the batch of NFTs lazy minted together. - */ + */ function lazyMint( uint256 amount, string calldata baseURIForTokens, diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 2ed78416d..5809ba13c 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -164,7 +164,6 @@ contract SignatureDropTest is BaseTest { * note: Tests whether contract reverts when a non-holder renounces a role. */ function test_revert_nonHolder_renounceRole() public { - address caller = address(0x123); bytes32 role = keccak256("MINTER_ROLE"); @@ -436,7 +435,7 @@ contract SignatureDropTest is BaseTest { vm.assume(x > 0); vm.startPrank(deployerSigner); - if(x == 0) { + if (x == 0) { vm.expectRevert("Zero amount"); } sigdrop.lazyMint(x, "ipfs://", ""); From f298591fc0b3e3303ea35748c83f8f632a151ce0 Mon Sep 17 00:00:00 2001 From: yash Date: Wed, 15 Jun 2022 21:37:23 +0530 Subject: [PATCH 19/41] replace requires with custom errors replace requires with custom errors --- contracts/feature/ContractMetadata.sol | 6 +- contracts/feature/DelayedReveal.sol | 6 +- contracts/feature/Drop.sol | 1 + contracts/feature/DropSinglePhase.sol | 59 ++++-- contracts/feature/Errors.sol | 6 + contracts/feature/LazyMint.sol | 1 + contracts/feature/Ownable.sol | 4 +- contracts/feature/Permissions.sol | 5 +- contracts/feature/PlatformFee.sol | 7 +- contracts/feature/PrimarySale.sol | 4 +- contracts/feature/Royalty.sol | 15 +- contracts/feature/SignatureMintERC721.sol | 16 +- .../SignatureMintERC721Upgradeable.sol | 16 +- contracts/signature-drop/SignatureDrop.sol | 40 +++- docs/ContractMetadata.md | 14 ++ docs/DelayedReveal.md | 14 ++ docs/DropSinglePhase.md | 80 +++++++ docs/Multiwrap.md | 36 ++++ docs/Ownable.md | 14 ++ docs/Permissions.md | 14 ++ docs/PermissionsEnumerable.md | 14 ++ docs/PlatformFee.md | 25 +++ docs/PrimarySale.md | 14 ++ docs/Royalty.md | 25 +++ docs/SignatureDrop.md | 198 ++++++++++++++++++ docs/SignatureMintERC721.md | 25 +++ docs/SignatureMintERC721Upgradeable.md | 25 +++ docs/ThirdwebContract.md | 14 ++ lib/forge-std | 2 +- 29 files changed, 653 insertions(+), 47 deletions(-) create mode 100644 contracts/feature/Errors.sol diff --git a/contracts/feature/ContractMetadata.sol b/contracts/feature/ContractMetadata.sol index 3478b74c0..585e5b77f 100644 --- a/contracts/feature/ContractMetadata.sol +++ b/contracts/feature/ContractMetadata.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./interface/IContractMetadata.sol"; +import "./Errors.sol"; /** * Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI @@ -16,7 +17,10 @@ abstract contract ContractMetadata is IContractMetadata { /// @dev Lets a contract admin set the URI for contract-level metadata. function setContractURI(string memory _uri) external override { - require(_canSetContractURI(), "Not authorized"); + // require(_canSetContractURI(), "Not authorized"); + if(!_canSetContractURI()) { + revert NotAuthorized(); + } _setupContractURI(_uri); } diff --git a/contracts/feature/DelayedReveal.sol b/contracts/feature/DelayedReveal.sol index e8ea6580a..a190b1992 100644 --- a/contracts/feature/DelayedReveal.sol +++ b/contracts/feature/DelayedReveal.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./interface/IDelayedReveal.sol"; +import "./Errors.sol"; /** * Thirdweb's `DelayedReveal` is a contract extension for base NFT contracts. It lets you create batches of @@ -20,7 +21,10 @@ abstract contract DelayedReveal is IDelayedReveal { /// @dev Returns the decrypted i.e. revealed URI for a batch of tokens. function getRevealURI(uint256 _batchId, bytes calldata _key) public view returns (string memory revealedURI) { bytes memory encryptedURI = encryptedBaseURI[_batchId]; - require(encryptedURI.length != 0, "nothing to reveal."); + // require(encryptedURI.length != 0, "nothing to reveal."); + if(encryptedURI.length == 0) { + revert NothingToReveal(); + } revealedURI = string(encryptDecrypt(encryptedURI, _key)); } diff --git a/contracts/feature/Drop.sol b/contracts/feature/Drop.sol index 7194ff439..b973b5c70 100644 --- a/contracts/feature/Drop.sol +++ b/contracts/feature/Drop.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import "./interface/IDrop.sol"; import "../lib/MerkleProof.sol"; import "../lib/TWBitMaps.sol"; +import "./Errors.sol"; abstract contract Drop is IDrop { using TWBitMaps for TWBitMaps.BitMap; diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index 575588d37..7b0e416ff 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.0; import "./interface/IDropSinglePhase.sol"; import "../lib/MerkleProof.sol"; import "../lib/TWBitMaps.sol"; +import "./Errors.sol"; abstract contract DropSinglePhase is IDropSinglePhase { using TWBitMaps for TWBitMaps.BitMap; @@ -34,6 +35,17 @@ abstract contract DropSinglePhase is IDropSinglePhase { */ mapping(bytes32 => TWBitMaps.BitMap) private usedAllowlistSpot; + /*/////////////////////////////////////////////////////////////// + Errors + //////////////////////////////////////////////////////////////*/ + error InvalidCurrencyOrPrice(); + error InvalidQuantity(); + error ExceedMaxClaimableSupply(); + error CannotClaim(); + error NotInWhitelist(); + error ProofClaimed(); + error InvalidQuantityProof(); + /*/////////////////////////////////////////////////////////////// Drop logic //////////////////////////////////////////////////////////////*/ @@ -135,21 +147,25 @@ abstract contract DropSinglePhase is IDropSinglePhase { ) public view { ClaimCondition memory currentClaimPhase = claimCondition; - require( - _currency == currentClaimPhase.currency && _pricePerToken == currentClaimPhase.pricePerToken, - "invalid currency or price." - ); + // require( + // _currency == currentClaimPhase.currency && _pricePerToken == currentClaimPhase.pricePerToken, + // "invalid currency or price." + // ); + if(_currency != currentClaimPhase.currency || _pricePerToken != currentClaimPhase.pricePerToken) revert InvalidCurrencyOrPrice(); // If we're checking for an allowlist quantity restriction, ignore the general quantity restriction. - require( - _quantity > 0 && - (!verifyMaxQuantityPerTransaction || _quantity <= currentClaimPhase.quantityLimitPerTransaction), - "invalid quantity." - ); - require( - currentClaimPhase.supplyClaimed + _quantity <= currentClaimPhase.maxClaimableSupply, - "exceed max claimable supply." - ); + // require( + // _quantity > 0 && + // (!verifyMaxQuantityPerTransaction || _quantity <= currentClaimPhase.quantityLimitPerTransaction), + // "invalid quantity." + // ); + if(_quantity == 0 || (verifyMaxQuantityPerTransaction && _quantity > currentClaimPhase.quantityLimitPerTransaction)) revert InvalidQuantity(); + + // require( + // currentClaimPhase.supplyClaimed + _quantity <= currentClaimPhase.maxClaimableSupply, + // "exceed max claimable supply." + // ); + if(currentClaimPhase.supplyClaimed + _quantity > currentClaimPhase.maxClaimableSupply) revert ExceedMaxClaimableSupply(); (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); require( @@ -173,12 +189,17 @@ abstract contract DropSinglePhase is IDropSinglePhase { currentClaimPhase.merkleRoot, keccak256(abi.encodePacked(_claimer, _allowlistProof.maxQuantityInAllowlist)) ); - require(validMerkleProof, "not in whitelist."); - require(!usedAllowlistSpot[conditionId].get(merkleProofIndex), "proof claimed."); - require( - _allowlistProof.maxQuantityInAllowlist == 0 || _quantity <= _allowlistProof.maxQuantityInAllowlist, - "invalid quantity proof." - ); + // require(validMerkleProof, "not in whitelist."); + if(!validMerkleProof) revert NotInWhitelist(); + + // require(!usedAllowlistSpot[conditionId].get(merkleProofIndex), "proof claimed."); + if(usedAllowlistSpot[conditionId].get(merkleProofIndex)) revert ProofClaimed(); + + // require( + // _allowlistProof.maxQuantityInAllowlist == 0 || _quantity <= _allowlistProof.maxQuantityInAllowlist, + // "invalid quantity proof." + // ); + if(_allowlistProof.maxQuantityInAllowlist != 0 && _quantity > _allowlistProof.maxQuantityInAllowlist) revert InvalidQuantityProof(); } } diff --git a/contracts/feature/Errors.sol b/contracts/feature/Errors.sol new file mode 100644 index 000000000..a5e88a441 --- /dev/null +++ b/contracts/feature/Errors.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +error NotAuthorized(); +error NothingToReveal(); +error ExceedsMaxBps(); \ No newline at end of file diff --git a/contracts/feature/LazyMint.sol b/contracts/feature/LazyMint.sol index 6916296d4..073e5bc8c 100644 --- a/contracts/feature/LazyMint.sol +++ b/contracts/feature/LazyMint.sol @@ -66,6 +66,7 @@ abstract contract LazyMint is ILazyMint { uint256 _amountToMint, string calldata _baseURIForTokens ) internal returns (uint256 nextTokenIdToMint, uint256 batchId) { + batchId = _startId + _amountToMint; nextTokenIdToMint = batchId; diff --git a/contracts/feature/Ownable.sol b/contracts/feature/Ownable.sol index 3a23699f6..297e4ca4c 100644 --- a/contracts/feature/Ownable.sol +++ b/contracts/feature/Ownable.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./interface/IOwnable.sol"; +import "./Errors.sol"; /** * Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading @@ -15,7 +16,8 @@ abstract contract Ownable is IOwnable { /// @dev Lets a contract admin set a new owner for the contract. The new owner must be a contract admin. function setOwner(address _newOwner) external override { - require(_canSetOwner(), "Not authorized"); + // require(_canSetOwner(), "Not authorized"); + if(!_canSetOwner()) revert NotAuthorized(); _setupOwner(_newOwner); } diff --git a/contracts/feature/Permissions.sol b/contracts/feature/Permissions.sol index a00d02d51..8c4ece317 100644 --- a/contracts/feature/Permissions.sol +++ b/contracts/feature/Permissions.sol @@ -10,6 +10,8 @@ contract Permissions is IPermissions { bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + error CanOnlyRenounceForSelf(); + modifier onlyRole(bytes32 role) { _checkRole(role, msg.sender); _; @@ -43,7 +45,8 @@ contract Permissions is IPermissions { } function renounceRole(bytes32 role, address account) public virtual override { - require(msg.sender == account, "Can only renounce for self"); + // require(msg.sender == account, "Can only renounce for self"); + if(msg.sender != account) revert CanOnlyRenounceForSelf(); _revokeRole(role, account); } diff --git a/contracts/feature/PlatformFee.sol b/contracts/feature/PlatformFee.sol index f3c0f4837..0fe3dee42 100644 --- a/contracts/feature/PlatformFee.sol +++ b/contracts/feature/PlatformFee.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./interface/IPlatformFee.sol"; +import "./Errors.sol"; /** * Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading @@ -23,13 +24,15 @@ abstract contract PlatformFee is IPlatformFee { /// @dev Lets a contract admin update the platform fee recipient and bps function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external override { - require(_canSetPlatformFeeInfo(), "Not authorized"); + // require(_canSetPlatformFeeInfo(), "Not authorized"); + if(!_canSetPlatformFeeInfo()) revert NotAuthorized(); _setupPlatformFeeInfo(_platformFeeRecipient, _platformFeeBps); } /// @dev Lets a contract admin update the platform fee recipient and bps function _setupPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) internal { - require(_platformFeeBps <= 10_000, "Exceeds max bps"); + // require(_platformFeeBps <= 10_000, "Exceeds max bps"); + if(_platformFeeBps > 10_000) revert ExceedsMaxBps(); platformFeeBps = uint16(_platformFeeBps); platformFeeRecipient = _platformFeeRecipient; diff --git a/contracts/feature/PrimarySale.sol b/contracts/feature/PrimarySale.sol index 44358b81a..732da12b4 100644 --- a/contracts/feature/PrimarySale.sol +++ b/contracts/feature/PrimarySale.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./interface/IPrimarySale.sol"; +import "./Errors.sol"; /** * Thirdweb's `Primary` is a contract extension to be used with any base contract. It exposes functions for setting and reading @@ -19,7 +20,8 @@ abstract contract PrimarySale is IPrimarySale { /// @dev Lets a contract admin set the recipient for all primary sales. function setPrimarySaleRecipient(address _saleRecipient) external override { - require(_canSetPrimarySaleRecipient(), "Not authorized"); + // require(_canSetPrimarySaleRecipient(), "Not authorized"); + if(!_canSetPrimarySaleRecipient()) revert NotAuthorized(); _setupPrimarySaleRecipient(_saleRecipient); } diff --git a/contracts/feature/Royalty.sol b/contracts/feature/Royalty.sol index 47235c671..ca2f97cea 100644 --- a/contracts/feature/Royalty.sol +++ b/contracts/feature/Royalty.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./interface/IRoyalty.sol"; +import "./Errors.sol"; /** * Thirdweb's `Royalty` is a contract extension to be used with any base contract. It exposes functions for setting and reading @@ -51,13 +52,16 @@ abstract contract Royalty is IRoyalty { /// @dev Lets a contract admin update the default royalty recipient and bps. function setDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) external override { - require(_canSetRoyaltyInfo(), "Not authorized"); + // require(_canSetRoyaltyInfo(), "Not authorized"); + if(!_canSetRoyaltyInfo()) revert NotAuthorized(); + _setupDefaultRoyaltyInfo(_royaltyRecipient, _royaltyBps); } /// @dev Lets a contract admin update the default royalty recipient and bps. function _setupDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) internal { - require(_royaltyBps <= 10_000, "Exceeds max bps"); + // require(_royaltyBps <= 10_000, "Exceeds max bps"); + if(_royaltyBps > 10_000) revert ExceedsMaxBps(); royaltyRecipient = _royaltyRecipient; royaltyBps = uint16(_royaltyBps); @@ -71,7 +75,9 @@ abstract contract Royalty is IRoyalty { address _recipient, uint256 _bps ) external override { - require(_canSetRoyaltyInfo(), "Not authorized"); + // require(_canSetRoyaltyInfo(), "Not authorized"); + if(!_canSetRoyaltyInfo()) revert NotAuthorized(); + _setupRoyaltyInfoForToken(_tokenId, _recipient, _bps); } @@ -81,7 +87,8 @@ abstract contract Royalty is IRoyalty { address _recipient, uint256 _bps ) internal { - require(_bps <= 10_000, "Exceeds max bps"); + // require(_bps <= 10_000, "Exceeds max bps"); + if(_bps > 10_000) revert ExceedsMaxBps(); royaltyInfoForToken[_tokenId] = RoyaltyInfo({ recipient: _recipient, bps: _bps }); diff --git a/contracts/feature/SignatureMintERC721.sol b/contracts/feature/SignatureMintERC721.sol index 2e8728b83..c02a67488 100644 --- a/contracts/feature/SignatureMintERC721.sol +++ b/contracts/feature/SignatureMintERC721.sol @@ -17,6 +17,9 @@ abstract contract SignatureMintERC721 is EIP712, ISignatureMintERC721 { /// @dev Mapping from mint request UID => whether the mint request is processed. mapping(bytes32 => bool) private minted; + error InvalidRequest(); + error RequestExpired(); + constructor() EIP712("SignatureMintERC721", "1") {} /// @dev Verifies that a mint request is signed by an authorized account. @@ -38,11 +41,14 @@ abstract contract SignatureMintERC721 is EIP712, ISignatureMintERC721 { bool success; (success, signer) = verify(_req, _signature); - require(success, "Invalid request"); - require( - _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, - "Request expired" - ); + // require(success, "Invalid request"); + if(!success) revert InvalidRequest(); + + // require( + // _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, + // "Request expired" + // ); + if(_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) revert RequestExpired(); minted[_req.uid] = true; } diff --git a/contracts/feature/SignatureMintERC721Upgradeable.sol b/contracts/feature/SignatureMintERC721Upgradeable.sol index 587d9c99f..7ed548cf6 100644 --- a/contracts/feature/SignatureMintERC721Upgradeable.sol +++ b/contracts/feature/SignatureMintERC721Upgradeable.sol @@ -17,6 +17,9 @@ abstract contract SignatureMintERC721Upgradeable is Initializable, EIP712Upgrade /// @dev Mapping from mint request UID => whether the mint request is processed. mapping(bytes32 => bool) private minted; + error InvalidRequest(); + error RequestExpired(); + function __SignatureMintERC721_init() internal onlyInitializing { __EIP712_init("SignatureMintERC721", "1"); } @@ -42,11 +45,14 @@ abstract contract SignatureMintERC721Upgradeable is Initializable, EIP712Upgrade bool success; (success, signer) = verify(_req, _signature); - require(success, "Invalid request"); - require( - _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, - "Request expired" - ); + // require(success, "Invalid request"); + if(!success) revert InvalidRequest(); + + // require( + // _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, + // "Request expired" + // ); + if(_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) revert RequestExpired(); minted[_req.uid] = true; } diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index 69d920755..82afe8b84 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -63,6 +63,16 @@ contract SignatureDrop is /// @dev The tokenId of the next NFT that will be minted / lazy minted. uint256 public nextTokenIdToMint; + /*/////////////////////////////////////////////////////////////// + Errors + //////////////////////////////////////////////////////////////*/ + + error NotEnoughMintedTokens(); + error MintingZeroTokens(); + error ZeroAmount(); + error MustSendTotalPrice(); + error NotTransferRole(); + /*/////////////////////////////////////////////////////////////// Events //////////////////////////////////////////////////////////////*/ @@ -153,7 +163,10 @@ contract SignatureDrop is string calldata _baseURIForTokens, bytes calldata _encryptedBaseURI ) external onlyRole(MINTER_ROLE) returns (uint256 batchId) { - require(_amount != 0, "Zero amount"); + if(_amount == 0) { + revert ZeroAmount(); + } + uint256 startId = nextTokenIdToMint; (nextTokenIdToMint, batchId) = _batchMint(startId, _amount, _baseURIForTokens); @@ -190,10 +203,16 @@ contract SignatureDrop is payable returns (address signer) { - require(_req.quantity > 0, "minting zero tokens"); + // require(_req.quantity > 0, "minting zero tokens"); + if(_req.quantity == 0) { + revert MintingZeroTokens(); + } uint256 tokenIdToMint = _currentIndex; - require(tokenIdToMint + _req.quantity <= nextTokenIdToMint, "not enough minted tokens."); + // require(tokenIdToMint + _req.quantity <= nextTokenIdToMint, "not enough minted tokens."); + if(tokenIdToMint + _req.quantity > nextTokenIdToMint) { + revert NotEnoughMintedTokens(); + } // Verify and process payload. signer = _processRequest(_req, _signature); @@ -229,7 +248,10 @@ contract SignatureDrop is AllowlistProof calldata, bytes memory ) internal view override { - require(_currentIndex + _quantity <= nextTokenIdToMint, "not enough minted tokens."); + // require(_currentIndex + _quantity <= nextTokenIdToMint, "not enough minted tokens."); + if(_currentIndex + _quantity > nextTokenIdToMint) { + revert NotEnoughMintedTokens(); + } } /// @dev Collects and distributes the primary sale value of NFTs being claimed. @@ -248,7 +270,10 @@ contract SignatureDrop is uint256 platformFees = (totalPrice * platformFeeBps) / MAX_BPS; if (_currency == CurrencyTransferLib.NATIVE_TOKEN) { - require(msg.value == totalPrice, "must send total price."); + // require(msg.value == totalPrice, "must send total price."); + if(msg.value != totalPrice) { + revert MustSendTotalPrice(); + } } CurrencyTransferLib.transferCurrency(_currency, _msgSender(), platformFeeRecipient, platformFees); @@ -326,7 +351,10 @@ contract SignatureDrop is // if transfer is restricted on the contract, we still want to allow burning and minting if (!hasRole(TRANSFER_ROLE, address(0)) && from != address(0) && to != address(0)) { - require(hasRole(TRANSFER_ROLE, from) || hasRole(TRANSFER_ROLE, to), "!TRANSFER_ROLE"); + // require(hasRole(TRANSFER_ROLE, from) || hasRole(TRANSFER_ROLE, to), "!TRANSFER_ROLE"); + if(!hasRole(TRANSFER_ROLE, from) && !hasRole(TRANSFER_ROLE, to)) { + revert NotTransferRole(); + } } } diff --git a/docs/ContractMetadata.md b/docs/ContractMetadata.md index fb1e1fdec..9fc660a7d 100644 --- a/docs/ContractMetadata.md +++ b/docs/ContractMetadata.md @@ -66,3 +66,17 @@ event ContractURIUpdated(string prevURI, string newURI) +## Errors + +### NotAuthorized + +```solidity +error NotAuthorized() +``` + + + + + + + diff --git a/docs/DelayedReveal.md b/docs/DelayedReveal.md index 8f2aeac85..39070edb0 100644 --- a/docs/DelayedReveal.md +++ b/docs/DelayedReveal.md @@ -126,3 +126,17 @@ function reveal(uint256 identifier, bytes key) external nonpayable returns (stri +## Errors + +### NothingToReveal + +```solidity +error NothingToReveal() +``` + + + + + + + diff --git a/docs/DropSinglePhase.md b/docs/DropSinglePhase.md index 897538369..3503ab703 100644 --- a/docs/DropSinglePhase.md +++ b/docs/DropSinglePhase.md @@ -182,3 +182,83 @@ event TokensClaimed(address indexed claimer, address indexed receiver, uint256 s +## Errors + +### CannotClaim + +```solidity +error CannotClaim() +``` + + + + + + +### ExceedMaxClaimableSupply + +```solidity +error ExceedMaxClaimableSupply() +``` + + + + + + +### InvalidCurrencyOrPrice + +```solidity +error InvalidCurrencyOrPrice() +``` + + + + + + +### InvalidQuantity + +```solidity +error InvalidQuantity() +``` + + + + + + +### InvalidQuantityProof + +```solidity +error InvalidQuantityProof() +``` + + + + + + +### NotInWhitelist + +```solidity +error NotInWhitelist() +``` + + + + + + +### ProofClaimed + +```solidity +error ProofClaimed() +``` + + + + + + + diff --git a/docs/Multiwrap.md b/docs/Multiwrap.md index a2a5678b3..8d531a802 100644 --- a/docs/Multiwrap.md +++ b/docs/Multiwrap.md @@ -1139,3 +1139,39 @@ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId +## Errors + +### CanOnlyRenounceForSelf + +```solidity +error CanOnlyRenounceForSelf() +``` + + + + + + +### ExceedsMaxBps + +```solidity +error ExceedsMaxBps() +``` + + + + + + +### NotAuthorized + +```solidity +error NotAuthorized() +``` + + + + + + + diff --git a/docs/Ownable.md b/docs/Ownable.md index 82988ff33..80eed0ba9 100644 --- a/docs/Ownable.md +++ b/docs/Ownable.md @@ -66,3 +66,17 @@ event OwnerUpdated(address prevOwner, address newOwner) +## Errors + +### NotAuthorized + +```solidity +error NotAuthorized() +``` + + + + + + + diff --git a/docs/Permissions.md b/docs/Permissions.md index 56b39fc63..775c7f70e 100644 --- a/docs/Permissions.md +++ b/docs/Permissions.md @@ -206,3 +206,17 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed +## Errors + +### CanOnlyRenounceForSelf + +```solidity +error CanOnlyRenounceForSelf() +``` + + + + + + + diff --git a/docs/PermissionsEnumerable.md b/docs/PermissionsEnumerable.md index e7c2ccd45..7475dbdc8 100644 --- a/docs/PermissionsEnumerable.md +++ b/docs/PermissionsEnumerable.md @@ -251,3 +251,17 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed +## Errors + +### CanOnlyRenounceForSelf + +```solidity +error CanOnlyRenounceForSelf() +``` + + + + + + + diff --git a/docs/PlatformFee.md b/docs/PlatformFee.md index 7c53f7063..b020fa427 100644 --- a/docs/PlatformFee.md +++ b/docs/PlatformFee.md @@ -68,3 +68,28 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp +## Errors + +### ExceedsMaxBps + +```solidity +error ExceedsMaxBps() +``` + + + + + + +### NotAuthorized + +```solidity +error NotAuthorized() +``` + + + + + + + diff --git a/docs/PrimarySale.md b/docs/PrimarySale.md index 00684208c..11a300b1a 100644 --- a/docs/PrimarySale.md +++ b/docs/PrimarySale.md @@ -65,3 +65,17 @@ event PrimarySaleRecipientUpdated(address indexed recipient) +## Errors + +### NotAuthorized + +```solidity +error NotAuthorized() +``` + + + + + + + diff --git a/docs/Royalty.md b/docs/Royalty.md index e1abd57b5..33f52616c 100644 --- a/docs/Royalty.md +++ b/docs/Royalty.md @@ -151,3 +151,28 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 +## Errors + +### ExceedsMaxBps + +```solidity +error ExceedsMaxBps() +``` + + + + + + +### NotAuthorized + +```solidity +error NotAuthorized() +``` + + + + + + + diff --git a/docs/SignatureDrop.md b/docs/SignatureDrop.md index 6820e2ac5..2d6772855 100644 --- a/docs/SignatureDrop.md +++ b/docs/SignatureDrop.md @@ -1533,6 +1533,94 @@ Cannot query the balance for the zero address. +### CanOnlyRenounceForSelf + +```solidity +error CanOnlyRenounceForSelf() +``` + + + + + + +### CannotClaim + +```solidity +error CannotClaim() +``` + + + + + + +### ExceedMaxClaimableSupply + +```solidity +error ExceedMaxClaimableSupply() +``` + + + + + + +### ExceedsMaxBps + +```solidity +error ExceedsMaxBps() +``` + + + + + + +### InvalidCurrencyOrPrice + +```solidity +error InvalidCurrencyOrPrice() +``` + + + + + + +### InvalidQuantity + +```solidity +error InvalidQuantity() +``` + + + + + + +### InvalidQuantityProof + +```solidity +error InvalidQuantityProof() +``` + + + + + + +### InvalidRequest + +```solidity +error InvalidRequest() +``` + + + + + + ### MintToZeroAddress ```solidity @@ -1555,6 +1643,83 @@ The quantity of tokens minted must be more than zero. +### MintingZeroTokens + +```solidity +error MintingZeroTokens() +``` + + + + + + +### MustSendTotalPrice + +```solidity +error MustSendTotalPrice() +``` + + + + + + +### NotAuthorized + +```solidity +error NotAuthorized() +``` + + + + + + +### NotEnoughMintedTokens + +```solidity +error NotEnoughMintedTokens() +``` + + + + + + +### NotInWhitelist + +```solidity +error NotInWhitelist() +``` + + + + + + +### NotTransferRole + +```solidity +error NotTransferRole() +``` + + + + + + +### NothingToReveal + +```solidity +error NothingToReveal() +``` + + + + + + ### OwnerQueryForNonexistentToken ```solidity @@ -1566,6 +1731,28 @@ The token does not exist. +### ProofClaimed + +```solidity +error ProofClaimed() +``` + + + + + + +### RequestExpired + +```solidity +error RequestExpired() +``` + + + + + + ### TransferCallerNotOwnerNorApproved ```solidity @@ -1621,4 +1808,15 @@ The token does not exist. +### ZeroAmount + +```solidity +error ZeroAmount() +``` + + + + + + diff --git a/docs/SignatureMintERC721.md b/docs/SignatureMintERC721.md index cdaf51432..aaaec85aa 100644 --- a/docs/SignatureMintERC721.md +++ b/docs/SignatureMintERC721.md @@ -82,3 +82,28 @@ event TokensMintedWithSignature(address indexed signer, address indexed mintedTo +## Errors + +### InvalidRequest + +```solidity +error InvalidRequest() +``` + + + + + + +### RequestExpired + +```solidity +error RequestExpired() +``` + + + + + + + diff --git a/docs/SignatureMintERC721Upgradeable.md b/docs/SignatureMintERC721Upgradeable.md index 8c7dc170d..4b6ab1fe1 100644 --- a/docs/SignatureMintERC721Upgradeable.md +++ b/docs/SignatureMintERC721Upgradeable.md @@ -82,3 +82,28 @@ event TokensMintedWithSignature(address indexed signer, address indexed mintedTo +## Errors + +### InvalidRequest + +```solidity +error InvalidRequest() +``` + + + + + + +### RequestExpired + +```solidity +error RequestExpired() +``` + + + + + + + diff --git a/docs/ThirdwebContract.md b/docs/ThirdwebContract.md index b67d6792b..e912eed58 100644 --- a/docs/ThirdwebContract.md +++ b/docs/ThirdwebContract.md @@ -82,3 +82,17 @@ event OwnerUpdated(address prevOwner, address newOwner) +## Errors + +### NotAuthorized + +```solidity +error NotAuthorized() +``` + + + + + + + diff --git a/lib/forge-std b/lib/forge-std index 0d0485bde..9a538e315 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 0d0485bdea9f9455bd684acb0ba88548a104d99b +Subproject commit 9a538e31562a6323a1fb36e838417e72047b5de7 From 3a60e1ff05cd64733366451cb0dd8fdc45cc704e Mon Sep 17 00:00:00 2001 From: Yash Date: Fri, 24 Jun 2022 17:00:56 +0530 Subject: [PATCH 20/41] standardize errors --- contracts/feature/ContractMetadata.sol | 4 +- contracts/feature/DelayedReveal.sol | 4 +- contracts/feature/DropSinglePhase.sol | 32 ++- contracts/feature/Errors.sol | 64 +++++- contracts/feature/Ownable.sol | 2 +- contracts/feature/Permissions.sol | 5 +- contracts/feature/PlatformFee.sol | 4 +- contracts/feature/PrimarySale.sol | 2 +- contracts/feature/Royalty.sol | 8 +- contracts/feature/SignatureMintERC721.sol | 8 +- .../SignatureMintERC721Upgradeable.sol | 8 +- contracts/signature-drop/SignatureDrop.sol | 36 +--- docs/ContractMetadata.md | 6 +- docs/DelayedReveal.md | 12 +- docs/DropERC1155.md | 18 +- docs/DropERC20.md | 4 +- docs/DropERC721.md | 18 +- docs/DropSinglePhase.md | 32 +-- docs/IContractMetadata.md | 4 +- docs/IDelayedReveal.md | 14 +- docs/IDropSinglePhase.md | 8 +- docs/ILazyMint.md | 12 +- docs/IMarketplace.md | 4 +- docs/IOwnable.md | 8 +- docs/IPack.md | 14 +- docs/IPermissions.md | 23 +++ docs/IPermissionsEnumerable.md | 23 +++ docs/IPlatformFee.md | 6 +- docs/IPrimarySale.md | 2 +- docs/IRoyalty.md | 10 +- docs/LazyMint.md | 12 +- docs/LazyMintERC721.md | 4 +- docs/Marketplace.md | 4 +- docs/Multiwrap.md | 50 +++-- docs/Ownable.md | 12 +- docs/Pack.md | 14 +- docs/Permissions.md | 6 +- docs/PermissionsEnumerable.md | 6 +- docs/PlatformFee.md | 14 +- docs/PrimarySale.md | 6 +- docs/Royalty.md | 18 +- docs/SignatureDrop.md | 183 ++++++++++++------ docs/SignatureMintERC721.md | 25 --- docs/SignatureMintERC721Upgradeable.md | 25 --- docs/ThirdwebContract.md | 10 +- docs/TokenERC1155.md | 18 +- docs/TokenERC20.md | 4 +- docs/TokenERC721.md | 18 +- src/test/SignatureDrop.t.sol | 2 +- 49 files changed, 463 insertions(+), 363 deletions(-) diff --git a/contracts/feature/ContractMetadata.sol b/contracts/feature/ContractMetadata.sol index 585e5b77f..c3dd9f87a 100644 --- a/contracts/feature/ContractMetadata.sol +++ b/contracts/feature/ContractMetadata.sol @@ -18,9 +18,7 @@ abstract contract ContractMetadata is IContractMetadata { /// @dev Lets a contract admin set the URI for contract-level metadata. function setContractURI(string memory _uri) external override { // require(_canSetContractURI(), "Not authorized"); - if(!_canSetContractURI()) { - revert NotAuthorized(); - } + if(!_canSetContractURI()) revert NotAuthorized__SetContractURI(); _setupContractURI(_uri); } diff --git a/contracts/feature/DelayedReveal.sol b/contracts/feature/DelayedReveal.sol index a190b1992..21b309ef6 100644 --- a/contracts/feature/DelayedReveal.sol +++ b/contracts/feature/DelayedReveal.sol @@ -22,9 +22,7 @@ abstract contract DelayedReveal is IDelayedReveal { function getRevealURI(uint256 _batchId, bytes calldata _key) public view returns (string memory revealedURI) { bytes memory encryptedURI = encryptedBaseURI[_batchId]; // require(encryptedURI.length != 0, "nothing to reveal."); - if(encryptedURI.length == 0) { - revert NothingToReveal(); - } + if(encryptedURI.length == 0) revert DelayedReveal__NothingToReveal(); revealedURI = string(encryptDecrypt(encryptedURI, _key)); } diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index 7b0e416ff..1f15a5772 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -38,13 +38,7 @@ abstract contract DropSinglePhase is IDropSinglePhase { /*/////////////////////////////////////////////////////////////// Errors //////////////////////////////////////////////////////////////*/ - error InvalidCurrencyOrPrice(); - error InvalidQuantity(); - error ExceedMaxClaimableSupply(); - error CannotClaim(); - error NotInWhitelist(); - error ProofClaimed(); - error InvalidQuantityProof(); + /*/////////////////////////////////////////////////////////////// Drop logic @@ -151,7 +145,7 @@ abstract contract DropSinglePhase is IDropSinglePhase { // _currency == currentClaimPhase.currency && _pricePerToken == currentClaimPhase.pricePerToken, // "invalid currency or price." // ); - if(_currency != currentClaimPhase.currency || _pricePerToken != currentClaimPhase.pricePerToken) revert InvalidCurrencyOrPrice(); + if(_currency != currentClaimPhase.currency || _pricePerToken != currentClaimPhase.pricePerToken) revert DropSinglePhase__InvalidCurrencyOrPrice(); // If we're checking for an allowlist quantity restriction, ignore the general quantity restriction. // require( @@ -159,20 +153,22 @@ abstract contract DropSinglePhase is IDropSinglePhase { // (!verifyMaxQuantityPerTransaction || _quantity <= currentClaimPhase.quantityLimitPerTransaction), // "invalid quantity." // ); - if(_quantity == 0 || (verifyMaxQuantityPerTransaction && _quantity > currentClaimPhase.quantityLimitPerTransaction)) revert InvalidQuantity(); + if(_quantity == 0 || (verifyMaxQuantityPerTransaction && _quantity > currentClaimPhase.quantityLimitPerTransaction)) revert DropSinglePhase__InvalidQuantity(); // require( // currentClaimPhase.supplyClaimed + _quantity <= currentClaimPhase.maxClaimableSupply, // "exceed max claimable supply." // ); - if(currentClaimPhase.supplyClaimed + _quantity > currentClaimPhase.maxClaimableSupply) revert ExceedMaxClaimableSupply(); + if(currentClaimPhase.supplyClaimed + _quantity > currentClaimPhase.maxClaimableSupply) revert DropSinglePhase__ExceedMaxClaimableSupply(); (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); - require( - claimCondition.startTimestamp < block.timestamp && - (lastClaimedAt == 0 || block.timestamp >= nextValidClaimTimestamp), - "cannot claim yet." - ); + // require( + // claimCondition.startTimestamp < block.timestamp && + // (lastClaimedAt == 0 || block.timestamp >= nextValidClaimTimestamp), + // "cannot claim yet." + // ); + if(claimCondition.startTimestamp >= block.timestamp || + (lastClaimedAt != 0 && block.timestamp < nextValidClaimTimestamp)) revert DropSinglePhase__CannotClaimYet(); } /// @dev Checks whether a claimer meets the claim condition's allowlist criteria. @@ -190,16 +186,16 @@ abstract contract DropSinglePhase is IDropSinglePhase { keccak256(abi.encodePacked(_claimer, _allowlistProof.maxQuantityInAllowlist)) ); // require(validMerkleProof, "not in whitelist."); - if(!validMerkleProof) revert NotInWhitelist(); + if(!validMerkleProof) revert DropSinglePhase__NotInWhitelist(); // require(!usedAllowlistSpot[conditionId].get(merkleProofIndex), "proof claimed."); - if(usedAllowlistSpot[conditionId].get(merkleProofIndex)) revert ProofClaimed(); + if(usedAllowlistSpot[conditionId].get(merkleProofIndex)) revert DropSinglePhase__ProofClaimed(); // require( // _allowlistProof.maxQuantityInAllowlist == 0 || _quantity <= _allowlistProof.maxQuantityInAllowlist, // "invalid quantity proof." // ); - if(_allowlistProof.maxQuantityInAllowlist != 0 && _quantity > _allowlistProof.maxQuantityInAllowlist) revert InvalidQuantityProof(); + if(_allowlistProof.maxQuantityInAllowlist != 0 && _quantity > _allowlistProof.maxQuantityInAllowlist) revert DropSinglePhase__InvalidQuantityProof(); } } diff --git a/contracts/feature/Errors.sol b/contracts/feature/Errors.sol index a5e88a441..b9fa5c65b 100644 --- a/contracts/feature/Errors.sol +++ b/contracts/feature/Errors.sol @@ -1,6 +1,66 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; +/*/////////////////////////////////////////////////////////////// + Common Errors +//////////////////////////////////////////////////////////////*/ + +error NotAuthorized__SetContractURI(); +error NotAuthorized__SetOwner(); +error NotAuthorized__SetPlatformFeeInfo(); +error NotAuthorized__SetPrimarySaleRecipient(); +error NotAuthorized__SetRoyaltyInfo(); error NotAuthorized(); -error NothingToReveal(); -error ExceedsMaxBps(); \ No newline at end of file + +/*/////////////////////////////////////////////////////////////// + Contract Specific Errors +//////////////////////////////////////////////////////////////*/ + +/* +* Contract: DelayedReveal.sol +*/ +error DelayedReveal__NothingToReveal(); + +/* +* Contract: DropSinglePhase.sol +*/ +error DropSinglePhase__InvalidCurrencyOrPrice(); +error DropSinglePhase__InvalidQuantity(); +error DropSinglePhase__ExceedMaxClaimableSupply(); +error DropSinglePhase__CannotClaimYet(); +error DropSinglePhase__NotInWhitelist(); +error DropSinglePhase__ProofClaimed(); +error DropSinglePhase__InvalidQuantityProof(); + +/* +* Contract: Permissions.sol +*/ +error Permissions__CanOnlyRenounceForSelf(); + +/* +* Contract: PlatformFee.sol +*/ +error PlatformFee__ExceedsMaxBps(); + +/* +* Contract: Royalty.sol +*/ +error Royalty__ExceedsMaxBps(); + +/* +* Contract: SignatureMintERC721.sol +* Contract: SignatureMintERC721Upgradeable.sol +*/ +error SignatureMintERC721__InvalidRequest(); +error SignatureMintERC721__RequestExpired(); +error SignatureMintERC721Upgradeable__InvalidRequest(); +error SignatureMintERC721Upgradeable__RequestExpired(); + +/* +* Contract: SignatureDrop.sol +*/ +error SignatureDrop__NotEnoughMintedTokens(); +error SignatureDrop__MintingZeroTokens(); +error SignatureDrop__ZeroAmount(); +error SignatureDrop__MustSendTotalPrice(); +error SignatureDrop__NotTransferRole(); \ No newline at end of file diff --git a/contracts/feature/Ownable.sol b/contracts/feature/Ownable.sol index 297e4ca4c..38635c628 100644 --- a/contracts/feature/Ownable.sol +++ b/contracts/feature/Ownable.sol @@ -17,7 +17,7 @@ abstract contract Ownable is IOwnable { /// @dev Lets a contract admin set a new owner for the contract. The new owner must be a contract admin. function setOwner(address _newOwner) external override { // require(_canSetOwner(), "Not authorized"); - if(!_canSetOwner()) revert NotAuthorized(); + if(!_canSetOwner()) revert NotAuthorized__SetOwner(); _setupOwner(_newOwner); } diff --git a/contracts/feature/Permissions.sol b/contracts/feature/Permissions.sol index 8c4ece317..c6d3b2b30 100644 --- a/contracts/feature/Permissions.sol +++ b/contracts/feature/Permissions.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.0; import "./interface/IPermissions.sol"; import "../lib/TWStrings.sol"; +import "./Errors.sol"; contract Permissions is IPermissions { mapping(bytes32 => mapping(address => bool)) private _hasRole; @@ -10,8 +11,6 @@ contract Permissions is IPermissions { bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; - error CanOnlyRenounceForSelf(); - modifier onlyRole(bytes32 role) { _checkRole(role, msg.sender); _; @@ -46,7 +45,7 @@ contract Permissions is IPermissions { function renounceRole(bytes32 role, address account) public virtual override { // require(msg.sender == account, "Can only renounce for self"); - if(msg.sender != account) revert CanOnlyRenounceForSelf(); + if(msg.sender != account) revert Permissions__CanOnlyRenounceForSelf(); _revokeRole(role, account); } diff --git a/contracts/feature/PlatformFee.sol b/contracts/feature/PlatformFee.sol index 0fe3dee42..f29e8bf65 100644 --- a/contracts/feature/PlatformFee.sol +++ b/contracts/feature/PlatformFee.sol @@ -25,14 +25,14 @@ abstract contract PlatformFee is IPlatformFee { /// @dev Lets a contract admin update the platform fee recipient and bps function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external override { // require(_canSetPlatformFeeInfo(), "Not authorized"); - if(!_canSetPlatformFeeInfo()) revert NotAuthorized(); + if(!_canSetPlatformFeeInfo()) revert NotAuthorized__SetPlatformFeeInfo(); _setupPlatformFeeInfo(_platformFeeRecipient, _platformFeeBps); } /// @dev Lets a contract admin update the platform fee recipient and bps function _setupPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) internal { // require(_platformFeeBps <= 10_000, "Exceeds max bps"); - if(_platformFeeBps > 10_000) revert ExceedsMaxBps(); + if(_platformFeeBps > 10_000) revert PlatformFee__ExceedsMaxBps(); platformFeeBps = uint16(_platformFeeBps); platformFeeRecipient = _platformFeeRecipient; diff --git a/contracts/feature/PrimarySale.sol b/contracts/feature/PrimarySale.sol index 732da12b4..0b3b4c276 100644 --- a/contracts/feature/PrimarySale.sol +++ b/contracts/feature/PrimarySale.sol @@ -21,7 +21,7 @@ abstract contract PrimarySale is IPrimarySale { /// @dev Lets a contract admin set the recipient for all primary sales. function setPrimarySaleRecipient(address _saleRecipient) external override { // require(_canSetPrimarySaleRecipient(), "Not authorized"); - if(!_canSetPrimarySaleRecipient()) revert NotAuthorized(); + if(!_canSetPrimarySaleRecipient()) revert NotAuthorized__SetPrimarySaleRecipient(); _setupPrimarySaleRecipient(_saleRecipient); } diff --git a/contracts/feature/Royalty.sol b/contracts/feature/Royalty.sol index ca2f97cea..2a657cb56 100644 --- a/contracts/feature/Royalty.sol +++ b/contracts/feature/Royalty.sol @@ -53,7 +53,7 @@ abstract contract Royalty is IRoyalty { /// @dev Lets a contract admin update the default royalty recipient and bps. function setDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) external override { // require(_canSetRoyaltyInfo(), "Not authorized"); - if(!_canSetRoyaltyInfo()) revert NotAuthorized(); + if(!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); _setupDefaultRoyaltyInfo(_royaltyRecipient, _royaltyBps); } @@ -61,7 +61,7 @@ abstract contract Royalty is IRoyalty { /// @dev Lets a contract admin update the default royalty recipient and bps. function _setupDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) internal { // require(_royaltyBps <= 10_000, "Exceeds max bps"); - if(_royaltyBps > 10_000) revert ExceedsMaxBps(); + if(_royaltyBps > 10_000) revert Royalty__ExceedsMaxBps(); royaltyRecipient = _royaltyRecipient; royaltyBps = uint16(_royaltyBps); @@ -76,7 +76,7 @@ abstract contract Royalty is IRoyalty { uint256 _bps ) external override { // require(_canSetRoyaltyInfo(), "Not authorized"); - if(!_canSetRoyaltyInfo()) revert NotAuthorized(); + if(!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); _setupRoyaltyInfoForToken(_tokenId, _recipient, _bps); } @@ -88,7 +88,7 @@ abstract contract Royalty is IRoyalty { uint256 _bps ) internal { // require(_bps <= 10_000, "Exceeds max bps"); - if(_bps > 10_000) revert ExceedsMaxBps(); + if(_bps > 10_000) revert Royalty__ExceedsMaxBps(); royaltyInfoForToken[_tokenId] = RoyaltyInfo({ recipient: _recipient, bps: _bps }); diff --git a/contracts/feature/SignatureMintERC721.sol b/contracts/feature/SignatureMintERC721.sol index c02a67488..0ebbd0759 100644 --- a/contracts/feature/SignatureMintERC721.sol +++ b/contracts/feature/SignatureMintERC721.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./interface/ISignatureMintERC721.sol"; +import "./Errors.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; @@ -17,9 +18,6 @@ abstract contract SignatureMintERC721 is EIP712, ISignatureMintERC721 { /// @dev Mapping from mint request UID => whether the mint request is processed. mapping(bytes32 => bool) private minted; - error InvalidRequest(); - error RequestExpired(); - constructor() EIP712("SignatureMintERC721", "1") {} /// @dev Verifies that a mint request is signed by an authorized account. @@ -42,13 +40,13 @@ abstract contract SignatureMintERC721 is EIP712, ISignatureMintERC721 { (success, signer) = verify(_req, _signature); // require(success, "Invalid request"); - if(!success) revert InvalidRequest(); + if(!success) revert SignatureMintERC721__InvalidRequest(); // require( // _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, // "Request expired" // ); - if(_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) revert RequestExpired(); + if(_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) revert SignatureMintERC721__RequestExpired(); minted[_req.uid] = true; } diff --git a/contracts/feature/SignatureMintERC721Upgradeable.sol b/contracts/feature/SignatureMintERC721Upgradeable.sol index 7ed548cf6..c670d1f7f 100644 --- a/contracts/feature/SignatureMintERC721Upgradeable.sol +++ b/contracts/feature/SignatureMintERC721Upgradeable.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.0; import "./interface/ISignatureMintERC721.sol"; +import "./Errors.sol"; import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol"; @@ -17,9 +18,6 @@ abstract contract SignatureMintERC721Upgradeable is Initializable, EIP712Upgrade /// @dev Mapping from mint request UID => whether the mint request is processed. mapping(bytes32 => bool) private minted; - error InvalidRequest(); - error RequestExpired(); - function __SignatureMintERC721_init() internal onlyInitializing { __EIP712_init("SignatureMintERC721", "1"); } @@ -46,13 +44,13 @@ abstract contract SignatureMintERC721Upgradeable is Initializable, EIP712Upgrade (success, signer) = verify(_req, _signature); // require(success, "Invalid request"); - if(!success) revert InvalidRequest(); + if(!success) revert SignatureMintERC721Upgradeable__InvalidRequest(); // require( // _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, // "Request expired" // ); - if(_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) revert RequestExpired(); + if(_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) revert SignatureMintERC721Upgradeable__RequestExpired(); minted[_req.uid] = true; } diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index 82afe8b84..359a34470 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -27,6 +27,8 @@ import "../feature/PermissionsEnumerable.sol"; import "../feature/DropSinglePhase.sol"; import "../feature/SignatureMintERC721Upgradeable.sol"; +import "../feature/Errors.sol"; + contract SignatureDrop is Initializable, ContractMetadata, @@ -63,16 +65,6 @@ contract SignatureDrop is /// @dev The tokenId of the next NFT that will be minted / lazy minted. uint256 public nextTokenIdToMint; - /*/////////////////////////////////////////////////////////////// - Errors - //////////////////////////////////////////////////////////////*/ - - error NotEnoughMintedTokens(); - error MintingZeroTokens(); - error ZeroAmount(); - error MustSendTotalPrice(); - error NotTransferRole(); - /*/////////////////////////////////////////////////////////////// Events //////////////////////////////////////////////////////////////*/ @@ -163,9 +155,7 @@ contract SignatureDrop is string calldata _baseURIForTokens, bytes calldata _encryptedBaseURI ) external onlyRole(MINTER_ROLE) returns (uint256 batchId) { - if(_amount == 0) { - revert ZeroAmount(); - } + if(_amount == 0) revert SignatureDrop__ZeroAmount(); uint256 startId = nextTokenIdToMint; @@ -204,15 +194,11 @@ contract SignatureDrop is returns (address signer) { // require(_req.quantity > 0, "minting zero tokens"); - if(_req.quantity == 0) { - revert MintingZeroTokens(); - } + if(_req.quantity == 0) revert SignatureDrop__MintingZeroTokens(); uint256 tokenIdToMint = _currentIndex; // require(tokenIdToMint + _req.quantity <= nextTokenIdToMint, "not enough minted tokens."); - if(tokenIdToMint + _req.quantity > nextTokenIdToMint) { - revert NotEnoughMintedTokens(); - } + if(tokenIdToMint + _req.quantity > nextTokenIdToMint) revert SignatureDrop__NotEnoughMintedTokens(); // Verify and process payload. signer = _processRequest(_req, _signature); @@ -249,9 +235,7 @@ contract SignatureDrop is bytes memory ) internal view override { // require(_currentIndex + _quantity <= nextTokenIdToMint, "not enough minted tokens."); - if(_currentIndex + _quantity > nextTokenIdToMint) { - revert NotEnoughMintedTokens(); - } + if(_currentIndex + _quantity > nextTokenIdToMint) revert SignatureDrop__NotEnoughMintedTokens(); } /// @dev Collects and distributes the primary sale value of NFTs being claimed. @@ -271,9 +255,7 @@ contract SignatureDrop is if (_currency == CurrencyTransferLib.NATIVE_TOKEN) { // require(msg.value == totalPrice, "must send total price."); - if(msg.value != totalPrice) { - revert MustSendTotalPrice(); - } + if(msg.value != totalPrice) revert SignatureDrop__MustSendTotalPrice(); } CurrencyTransferLib.transferCurrency(_currency, _msgSender(), platformFeeRecipient, platformFees); @@ -352,9 +334,7 @@ contract SignatureDrop is // if transfer is restricted on the contract, we still want to allow burning and minting if (!hasRole(TRANSFER_ROLE, address(0)) && from != address(0) && to != address(0)) { // require(hasRole(TRANSFER_ROLE, from) || hasRole(TRANSFER_ROLE, to), "!TRANSFER_ROLE"); - if(!hasRole(TRANSFER_ROLE, from) && !hasRole(TRANSFER_ROLE, to)) { - revert NotTransferRole(); - } + if(!hasRole(TRANSFER_ROLE, from) && !hasRole(TRANSFER_ROLE, to)) revert SignatureDrop__NotTransferRole(); } } diff --git a/docs/ContractMetadata.md b/docs/ContractMetadata.md index 9fc660a7d..837017834 100644 --- a/docs/ContractMetadata.md +++ b/docs/ContractMetadata.md @@ -4,7 +4,7 @@ - +Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI for you contract. Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea. @@ -68,10 +68,10 @@ event ContractURIUpdated(string prevURI, string newURI) ## Errors -### NotAuthorized +### NotAuthorized__SetContractURI ```solidity -error NotAuthorized() +error NotAuthorized__SetContractURI() ``` diff --git a/docs/DelayedReveal.md b/docs/DelayedReveal.md index 39070edb0..6aec9730e 100644 --- a/docs/DelayedReveal.md +++ b/docs/DelayedReveal.md @@ -4,7 +4,7 @@ - +Thirdweb's `DelayedReveal` is a contract extension for base NFT contracts. It lets you create batches of 'delayed-reveal' NFTs. You can learn more about the usage of delayed reveal NFTs here - https://blog.thirdweb.com/delayed-reveal-nfts @@ -106,7 +106,7 @@ function isEncryptedBatch(uint256 _batchId) external view returns (bool) function reveal(uint256 identifier, bytes key) external nonpayable returns (string revealedURI) ``` - +Reveals a batch of delayed reveal NFTs. @@ -114,8 +114,8 @@ function reveal(uint256 identifier, bytes key) external nonpayable returns (stri | Name | Type | Description | |---|---|---| -| identifier | uint256 | undefined -| key | bytes | undefined +| identifier | uint256 | The ID for the batch of delayed-reveal NFTs to reveal. +| key | bytes | The key with which the base URI for the relevant batch of NFTs was encrypted. #### Returns @@ -128,10 +128,10 @@ function reveal(uint256 identifier, bytes key) external nonpayable returns (stri ## Errors -### NothingToReveal +### DelayedReveal__NothingToReveal ```solidity -error NothingToReveal() +error DelayedReveal__NothingToReveal() ``` diff --git a/docs/DropERC1155.md b/docs/DropERC1155.md index ff2b2d5fa..9ff96f4a1 100644 --- a/docs/DropERC1155.md +++ b/docs/DropERC1155.md @@ -1167,7 +1167,7 @@ event ClaimConditionsUpdated(uint256 indexed tokenId, IDropClaimCondition.ClaimC ### DefaultRoyalty ```solidity -event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) +event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps) ``` @@ -1178,7 +1178,7 @@ event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) | Name | Type | Description | |---|---|---| -| newRoyaltyRecipient | address | undefined | +| newRoyaltyRecipient `indexed` | address | undefined | | newRoyaltyBps | uint256 | undefined | ### MaxTotalSupplyUpdated @@ -1218,7 +1218,7 @@ event MaxWalletClaimCountUpdated(uint256 tokenId, uint256 count) ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -1229,13 +1229,13 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ### PlatformFeeInfoUpdated ```solidity -event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps) +event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps) ``` @@ -1246,7 +1246,7 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp | Name | Type | Description | |---|---|---| -| platformFeeRecipient | address | undefined | +| platformFeeRecipient `indexed` | address | undefined | | platformFeeBps | uint256 | undefined | ### PrimarySaleRecipientUpdated @@ -1322,7 +1322,7 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed ### RoyaltyForToken ```solidity -event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 royaltyBps) +event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps) ``` @@ -1334,7 +1334,7 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 | Name | Type | Description | |---|---|---| | tokenId `indexed` | uint256 | undefined | -| royaltyRecipient | address | undefined | +| royaltyRecipient `indexed` | address | undefined | | royaltyBps | uint256 | undefined | ### TokensClaimed diff --git a/docs/DropERC20.md b/docs/DropERC20.md index 2ff35eb39..5962a5173 100644 --- a/docs/DropERC20.md +++ b/docs/DropERC20.md @@ -1267,7 +1267,7 @@ event MaxWalletClaimCountUpdated(uint256 count) ### PlatformFeeInfoUpdated ```solidity -event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps) +event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps) ``` @@ -1278,7 +1278,7 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp | Name | Type | Description | |---|---|---| -| platformFeeRecipient | address | undefined | +| platformFeeRecipient `indexed` | address | undefined | | platformFeeBps | uint256 | undefined | ### PrimarySaleRecipientUpdated diff --git a/docs/DropERC721.md b/docs/DropERC721.md index b3abe591e..6518abd99 100644 --- a/docs/DropERC721.md +++ b/docs/DropERC721.md @@ -1311,7 +1311,7 @@ event ClaimConditionsUpdated(IDropClaimCondition.ClaimCondition[] claimCondition ### DefaultRoyalty ```solidity -event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) +event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps) ``` @@ -1322,7 +1322,7 @@ event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) | Name | Type | Description | |---|---|---| -| newRoyaltyRecipient | address | undefined | +| newRoyaltyRecipient `indexed` | address | undefined | | newRoyaltyBps | uint256 | undefined | ### MaxTotalSupplyUpdated @@ -1377,7 +1377,7 @@ event NFTRevealed(uint256 endTokenId, string revealedURI) ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -1388,13 +1388,13 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ### PlatformFeeInfoUpdated ```solidity -event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps) +event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps) ``` @@ -1405,7 +1405,7 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp | Name | Type | Description | |---|---|---| -| platformFeeRecipient | address | undefined | +| platformFeeRecipient `indexed` | address | undefined | | platformFeeBps | uint256 | undefined | ### PrimarySaleRecipientUpdated @@ -1481,7 +1481,7 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed ### RoyaltyForToken ```solidity -event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 royaltyBps) +event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps) ``` @@ -1493,7 +1493,7 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 | Name | Type | Description | |---|---|---| | tokenId `indexed` | uint256 | undefined | -| royaltyRecipient | address | undefined | +| royaltyRecipient `indexed` | address | undefined | | royaltyBps | uint256 | undefined | ### TokensClaimed diff --git a/docs/DropSinglePhase.md b/docs/DropSinglePhase.md index 3503ab703..edb8ec6d4 100644 --- a/docs/DropSinglePhase.md +++ b/docs/DropSinglePhase.md @@ -164,7 +164,7 @@ event ClaimConditionUpdated(IClaimCondition.ClaimCondition condition, bool reset ### TokensClaimed ```solidity -event TokensClaimed(address indexed claimer, address indexed receiver, uint256 startTokenId, uint256 quantityClaimed) +event TokensClaimed(address indexed claimer, address indexed receiver, uint256 indexed startTokenId, uint256 quantityClaimed) ``` @@ -177,17 +177,17 @@ event TokensClaimed(address indexed claimer, address indexed receiver, uint256 s |---|---|---| | claimer `indexed` | address | undefined | | receiver `indexed` | address | undefined | -| startTokenId | uint256 | undefined | +| startTokenId `indexed` | uint256 | undefined | | quantityClaimed | uint256 | undefined | ## Errors -### CannotClaim +### DropSinglePhase__CannotClaimYet ```solidity -error CannotClaim() +error DropSinglePhase__CannotClaimYet() ``` @@ -195,10 +195,10 @@ error CannotClaim() -### ExceedMaxClaimableSupply +### DropSinglePhase__ExceedMaxClaimableSupply ```solidity -error ExceedMaxClaimableSupply() +error DropSinglePhase__ExceedMaxClaimableSupply() ``` @@ -206,10 +206,10 @@ error ExceedMaxClaimableSupply() -### InvalidCurrencyOrPrice +### DropSinglePhase__InvalidCurrencyOrPrice ```solidity -error InvalidCurrencyOrPrice() +error DropSinglePhase__InvalidCurrencyOrPrice() ``` @@ -217,10 +217,10 @@ error InvalidCurrencyOrPrice() -### InvalidQuantity +### DropSinglePhase__InvalidQuantity ```solidity -error InvalidQuantity() +error DropSinglePhase__InvalidQuantity() ``` @@ -228,10 +228,10 @@ error InvalidQuantity() -### InvalidQuantityProof +### DropSinglePhase__InvalidQuantityProof ```solidity -error InvalidQuantityProof() +error DropSinglePhase__InvalidQuantityProof() ``` @@ -239,10 +239,10 @@ error InvalidQuantityProof() -### NotInWhitelist +### DropSinglePhase__NotInWhitelist ```solidity -error NotInWhitelist() +error DropSinglePhase__NotInWhitelist() ``` @@ -250,10 +250,10 @@ error NotInWhitelist() -### ProofClaimed +### DropSinglePhase__ProofClaimed ```solidity -error ProofClaimed() +error DropSinglePhase__ProofClaimed() ``` diff --git a/docs/IContractMetadata.md b/docs/IContractMetadata.md index 720d81fcc..1165fc5a7 100644 --- a/docs/IContractMetadata.md +++ b/docs/IContractMetadata.md @@ -4,7 +4,7 @@ - +Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI for you contract. Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea. @@ -55,7 +55,7 @@ event ContractURIUpdated(string prevURI, string newURI) - +*Emitted when the contract URI is updated.* #### Parameters diff --git a/docs/IDelayedReveal.md b/docs/IDelayedReveal.md index 78027e2fd..8ae0b8097 100644 --- a/docs/IDelayedReveal.md +++ b/docs/IDelayedReveal.md @@ -4,7 +4,7 @@ - +Thirdweb's `DelayedReveal` is a contract extension for base NFT contracts. It lets you create batches of 'delayed-reveal' NFTs. You can learn more about the usage of delayed reveal NFTs here - https://blog.thirdweb.com/delayed-reveal-nfts @@ -16,7 +16,7 @@ function encryptDecrypt(bytes data, bytes key) external pure returns (bytes result) ``` - +Performs XOR encryption/decryption. @@ -24,8 +24,8 @@ function encryptDecrypt(bytes data, bytes key) external pure returns (bytes resu | Name | Type | Description | |---|---|---| -| data | bytes | undefined -| key | bytes | undefined +| data | bytes | The data to encrypt. In the case of delayed-reveal NFTs, this is the "revealed" state base URI of the relevant batch of NFTs. +| key | bytes | The key with which to encrypt data #### Returns @@ -39,7 +39,7 @@ function encryptDecrypt(bytes data, bytes key) external pure returns (bytes resu function reveal(uint256 identifier, bytes key) external nonpayable returns (string revealedURI) ``` - +Reveals a batch of delayed reveal NFTs. @@ -47,8 +47,8 @@ function reveal(uint256 identifier, bytes key) external nonpayable returns (stri | Name | Type | Description | |---|---|---| -| identifier | uint256 | undefined -| key | bytes | undefined +| identifier | uint256 | The ID for the batch of delayed-reveal NFTs to reveal. +| key | bytes | The key with which the base URI for the relevant batch of NFTs was encrypted. #### Returns diff --git a/docs/IDropSinglePhase.md b/docs/IDropSinglePhase.md index 360ec69a8..fe4c82132 100644 --- a/docs/IDropSinglePhase.md +++ b/docs/IDropSinglePhase.md @@ -60,7 +60,7 @@ event ClaimConditionUpdated(IClaimCondition.ClaimCondition condition, bool reset - +*Emitted when the contract's claim conditions are updated.* #### Parameters @@ -72,12 +72,12 @@ event ClaimConditionUpdated(IClaimCondition.ClaimCondition condition, bool reset ### TokensClaimed ```solidity -event TokensClaimed(address indexed claimer, address indexed receiver, uint256 startTokenId, uint256 quantityClaimed) +event TokensClaimed(address indexed claimer, address indexed receiver, uint256 indexed startTokenId, uint256 quantityClaimed) ``` - +*Emitted when tokens are claimed via `claim`.* #### Parameters @@ -85,7 +85,7 @@ event TokensClaimed(address indexed claimer, address indexed receiver, uint256 s |---|---|---| | claimer `indexed` | address | undefined | | receiver `indexed` | address | undefined | -| startTokenId | uint256 | undefined | +| startTokenId `indexed` | uint256 | undefined | | quantityClaimed | uint256 | undefined | diff --git a/docs/ILazyMint.md b/docs/ILazyMint.md index de1b76b89..1ab6f65e1 100644 --- a/docs/ILazyMint.md +++ b/docs/ILazyMint.md @@ -4,7 +4,7 @@ - +Thirdweb's `LazyMint` is a contract extension for any base NFT contract. It lets you 'lazy mint' any number of NFTs at once. Here, 'lazy mint' means defining the metadata for particular tokenIds of your NFT contract, without actually minting a non-zero balance of NFTs of those tokenIds. @@ -16,7 +16,7 @@ function lazyMint(uint256 amount, string baseURIForTokens, bytes extraData) external nonpayable returns (uint256 batchId) ``` - +Lazy mints a given amount of NFTs. @@ -24,15 +24,15 @@ function lazyMint(uint256 amount, string baseURIForTokens, bytes extraData) exte | Name | Type | Description | |---|---|---| -| amount | uint256 | undefined -| baseURIForTokens | string | undefined -| extraData | bytes | undefined +| amount | uint256 | The number of NFTs to lazy mint. +| baseURIForTokens | string | The base URI for the 'n' number of NFTs being lazy minted, where the metadata for each of those NFTs is `${baseURIForTokens}/${tokenId}`. +| extraData | bytes | Additional bytes data to be used at the discretion of the consumer of the contract. #### Returns | Name | Type | Description | |---|---|---| -| batchId | uint256 | undefined +| batchId | uint256 | A unique integer identifier for the batch of NFTs lazy minted together. diff --git a/docs/IMarketplace.md b/docs/IMarketplace.md index ecd04d5c7..d5c535caf 100644 --- a/docs/IMarketplace.md +++ b/docs/IMarketplace.md @@ -381,7 +381,7 @@ event NewSale(uint256 indexed listingId, address indexed assetContract, address ### PlatformFeeInfoUpdated ```solidity -event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps) +event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps) ``` @@ -392,7 +392,7 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp | Name | Type | Description | |---|---|---| -| platformFeeRecipient | address | undefined | +| platformFeeRecipient `indexed` | address | undefined | | platformFeeBps | uint256 | undefined | diff --git a/docs/IOwnable.md b/docs/IOwnable.md index 7539d99c9..aa21d97c2 100644 --- a/docs/IOwnable.md +++ b/docs/IOwnable.md @@ -4,7 +4,7 @@ - +Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses information about who the contract's owner is. @@ -50,7 +50,7 @@ function setOwner(address _newOwner) external nonpayable ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -61,8 +61,8 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | diff --git a/docs/IPack.md b/docs/IPack.md index 4bbe435e3..9c14b3c91 100644 --- a/docs/IPack.md +++ b/docs/IPack.md @@ -253,7 +253,7 @@ function setRoyaltyInfoForToken(uint256 tokenId, address recipient, uint256 bps) ### DefaultRoyalty ```solidity -event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) +event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps) ``` @@ -264,13 +264,13 @@ event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) | Name | Type | Description | |---|---|---| -| newRoyaltyRecipient | address | undefined | +| newRoyaltyRecipient `indexed` | address | undefined | | newRoyaltyBps | uint256 | undefined | ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -281,13 +281,13 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ### RoyaltyForToken ```solidity -event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 royaltyBps) +event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps) ``` @@ -299,7 +299,7 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 | Name | Type | Description | |---|---|---| | tokenId `indexed` | uint256 | undefined | -| royaltyRecipient | address | undefined | +| royaltyRecipient `indexed` | address | undefined | | royaltyBps | uint256 | undefined | diff --git a/docs/IPermissions.md b/docs/IPermissions.md index 3156847c8..8490b4c54 100644 --- a/docs/IPermissions.md +++ b/docs/IPermissions.md @@ -72,6 +72,29 @@ function hasRole(bytes32 role, address account) external view returns (bool) |---|---|---| | _0 | bool | undefined +### hasRoleWithSwitch + +```solidity +function hasRoleWithSwitch(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if either (1) `account` has been granted `role`, or (2) the relevant role restrictions do not apply at the time of calling this function.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined +| account | address | undefined + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined + ### renounceRole ```solidity diff --git a/docs/IPermissionsEnumerable.md b/docs/IPermissionsEnumerable.md index aba66bbfb..00bd39312 100644 --- a/docs/IPermissionsEnumerable.md +++ b/docs/IPermissionsEnumerable.md @@ -117,6 +117,29 @@ function hasRole(bytes32 role, address account) external view returns (bool) |---|---|---| | _0 | bool | undefined +### hasRoleWithSwitch + +```solidity +function hasRoleWithSwitch(bytes32 role, address account) external view returns (bool) +``` + + + +*Returns `true` if either (1) `account` has been granted `role`, or (2) the relevant role restrictions do not apply at the time of calling this function.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| role | bytes32 | undefined +| account | address | undefined + +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | bool | undefined + ### renounceRole ```solidity diff --git a/docs/IPlatformFee.md b/docs/IPlatformFee.md index 7568c4b76..2ccaa430f 100644 --- a/docs/IPlatformFee.md +++ b/docs/IPlatformFee.md @@ -4,7 +4,7 @@ - +Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading the recipient of platform fee and the platform fee basis points, and lets the inheriting contract perform conditional logic that uses information about platform fees, if desired. @@ -52,7 +52,7 @@ function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeB ### PlatformFeeInfoUpdated ```solidity -event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps) +event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps) ``` @@ -63,7 +63,7 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp | Name | Type | Description | |---|---|---| -| platformFeeRecipient | address | undefined | +| platformFeeRecipient `indexed` | address | undefined | | platformFeeBps | uint256 | undefined | diff --git a/docs/IPrimarySale.md b/docs/IPrimarySale.md index 5d8bd2075..e0ecea162 100644 --- a/docs/IPrimarySale.md +++ b/docs/IPrimarySale.md @@ -4,7 +4,7 @@ - +Thirdweb's `Primary` is a contract extension to be used with any base contract. It exposes functions for setting and reading the recipient of primary sales, and lets the inheriting contract perform conditional logic that uses information about primary sales, if desired. diff --git a/docs/IRoyalty.md b/docs/IRoyalty.md index b781dd20e..81e48f97d 100644 --- a/docs/IRoyalty.md +++ b/docs/IRoyalty.md @@ -4,7 +4,7 @@ - +Thirdweb's `Royalty` is a contract extension to be used with any base contract. It exposes functions for setting and reading the recipient of royalty fee and the royalty fee basis points, and lets the inheriting contract perform conditional logic that uses information about royalty fees, if desired. The `Royalty` contract is ERC2981 compliant. @@ -117,7 +117,7 @@ function setRoyaltyInfoForToken(uint256 tokenId, address recipient, uint256 bps) ### DefaultRoyalty ```solidity -event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) +event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps) ``` @@ -128,13 +128,13 @@ event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) | Name | Type | Description | |---|---|---| -| newRoyaltyRecipient | address | undefined | +| newRoyaltyRecipient `indexed` | address | undefined | | newRoyaltyBps | uint256 | undefined | ### RoyaltyForToken ```solidity -event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 royaltyBps) +event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps) ``` @@ -146,7 +146,7 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 | Name | Type | Description | |---|---|---| | tokenId `indexed` | uint256 | undefined | -| royaltyRecipient | address | undefined | +| royaltyRecipient `indexed` | address | undefined | | royaltyBps | uint256 | undefined | diff --git a/docs/LazyMint.md b/docs/LazyMint.md index f9fe22cd8..f68175f87 100644 --- a/docs/LazyMint.md +++ b/docs/LazyMint.md @@ -4,7 +4,7 @@ - +Thirdweb's `LazyMint` is a contract extension for any base NFT contract. It lets you 'lazy mint' any number of NFTs at once. Here, 'lazy mint' means defining the metadata for particular tokenIds of your NFT contract, without actually minting a non-zero balance of NFTs of those tokenIds. @@ -55,7 +55,7 @@ function getBatchIdAtIndex(uint256 _index) external view returns (uint256) function lazyMint(uint256 amount, string baseURIForTokens, bytes extraData) external nonpayable returns (uint256 batchId) ``` - +Lazy mints a given amount of NFTs. @@ -63,15 +63,15 @@ function lazyMint(uint256 amount, string baseURIForTokens, bytes extraData) exte | Name | Type | Description | |---|---|---| -| amount | uint256 | undefined -| baseURIForTokens | string | undefined -| extraData | bytes | undefined +| amount | uint256 | The number of NFTs to lazy mint. +| baseURIForTokens | string | The base URI for the 'n' number of NFTs being lazy minted, where the metadata for each of those NFTs is `${baseURIForTokens}/${tokenId}`. +| extraData | bytes | Additional bytes data to be used at the discretion of the consumer of the contract. #### Returns | Name | Type | Description | |---|---|---| -| batchId | uint256 | undefined +| batchId | uint256 | A unique integer identifier for the batch of NFTs lazy minted together. diff --git a/docs/LazyMintERC721.md b/docs/LazyMintERC721.md index b08cba43e..457946fbb 100644 --- a/docs/LazyMintERC721.md +++ b/docs/LazyMintERC721.md @@ -119,7 +119,7 @@ function tokenURI(uint256 _tokenId) external view returns (string) ### TokensLazyMinted ```solidity -event TokensLazyMinted(uint256 startTokenId, uint256 endTokenId, string baseURI, bytes extraData) +event TokensLazyMinted(uint256 indexed startTokenId, uint256 endTokenId, string baseURI, bytes extraData) ``` @@ -130,7 +130,7 @@ event TokensLazyMinted(uint256 startTokenId, uint256 endTokenId, string baseURI, | Name | Type | Description | |---|---|---| -| startTokenId | uint256 | undefined | +| startTokenId `indexed` | uint256 | undefined | | endTokenId | uint256 | undefined | | baseURI | string | undefined | | extraData | bytes | undefined | diff --git a/docs/Marketplace.md b/docs/Marketplace.md index 13ba8652e..841b875e6 100644 --- a/docs/Marketplace.md +++ b/docs/Marketplace.md @@ -892,7 +892,7 @@ event NewSale(uint256 indexed listingId, address indexed assetContract, address ### PlatformFeeInfoUpdated ```solidity -event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps) +event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps) ``` @@ -903,7 +903,7 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp | Name | Type | Description | |---|---|---| -| platformFeeRecipient | address | undefined | +| platformFeeRecipient `indexed` | address | undefined | | platformFeeBps | uint256 | undefined | ### RoleAdminChanged diff --git a/docs/Multiwrap.md b/docs/Multiwrap.md index 8d531a802..f3826b77a 100644 --- a/docs/Multiwrap.md +++ b/docs/Multiwrap.md @@ -384,7 +384,7 @@ function hasRoleWithSwitch(bytes32 role, address account) external view returns - +*Returns `true` if either (1) `account` has been granted `role`, or (2) the relevant role restrictions do not apply at the time of calling this function.* #### Parameters @@ -979,7 +979,7 @@ event ContractURIUpdated(string prevURI, string newURI) ### DefaultRoyalty ```solidity -event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) +event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps) ``` @@ -990,13 +990,13 @@ event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) | Name | Type | Description | |---|---|---| -| newRoyaltyRecipient | address | undefined | +| newRoyaltyRecipient `indexed` | address | undefined | | newRoyaltyBps | uint256 | undefined | ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -1007,8 +1007,8 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ### RoleAdminChanged @@ -1067,7 +1067,7 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed ### RoyaltyForToken ```solidity -event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 royaltyBps) +event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps) ``` @@ -1079,7 +1079,7 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 | Name | Type | Description | |---|---|---| | tokenId `indexed` | uint256 | undefined | -| royaltyRecipient | address | undefined | +| royaltyRecipient `indexed` | address | undefined | | royaltyBps | uint256 | undefined | ### TokensUnwrapped @@ -1141,10 +1141,32 @@ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId ## Errors -### CanOnlyRenounceForSelf +### NotAuthorized__SetContractURI + +```solidity +error NotAuthorized__SetContractURI() +``` + + + + + + +### NotAuthorized__SetOwner + +```solidity +error NotAuthorized__SetOwner() +``` + + + + + + +### NotAuthorized__SetRoyaltyInfo ```solidity -error CanOnlyRenounceForSelf() +error NotAuthorized__SetRoyaltyInfo() ``` @@ -1152,10 +1174,10 @@ error CanOnlyRenounceForSelf() -### ExceedsMaxBps +### Permissions__CanOnlyRenounceForSelf ```solidity -error ExceedsMaxBps() +error Permissions__CanOnlyRenounceForSelf() ``` @@ -1163,10 +1185,10 @@ error ExceedsMaxBps() -### NotAuthorized +### Royalty__ExceedsMaxBps ```solidity -error NotAuthorized() +error Royalty__ExceedsMaxBps() ``` diff --git a/docs/Ownable.md b/docs/Ownable.md index 80eed0ba9..6da36dc34 100644 --- a/docs/Ownable.md +++ b/docs/Ownable.md @@ -4,7 +4,7 @@ - +Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading who the 'owner' of the inheriting smart contract is, and lets the inheriting contract perform conditional logic that uses information about who the contract's owner is. @@ -50,7 +50,7 @@ function setOwner(address _newOwner) external nonpayable ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -61,17 +61,17 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ## Errors -### NotAuthorized +### NotAuthorized__SetOwner ```solidity -error NotAuthorized() +error NotAuthorized__SetOwner() ``` diff --git a/docs/Pack.md b/docs/Pack.md index feb8f59c7..bb9a51641 100644 --- a/docs/Pack.md +++ b/docs/Pack.md @@ -1096,7 +1096,7 @@ event ApprovalForAll(address indexed account, address indexed operator, bool app ### DefaultRoyalty ```solidity -event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) +event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps) ``` @@ -1107,13 +1107,13 @@ event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) | Name | Type | Description | |---|---|---| -| newRoyaltyRecipient | address | undefined | +| newRoyaltyRecipient `indexed` | address | undefined | | newRoyaltyBps | uint256 | undefined | ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -1124,8 +1124,8 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ### PackAdded @@ -1259,7 +1259,7 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed ### RoyaltyForToken ```solidity -event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 royaltyBps) +event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps) ``` @@ -1271,7 +1271,7 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 | Name | Type | Description | |---|---|---| | tokenId `indexed` | uint256 | undefined | -| royaltyRecipient | address | undefined | +| royaltyRecipient `indexed` | address | undefined | | royaltyBps | uint256 | undefined | ### TransferBatch diff --git a/docs/Permissions.md b/docs/Permissions.md index 775c7f70e..7e323d533 100644 --- a/docs/Permissions.md +++ b/docs/Permissions.md @@ -97,7 +97,7 @@ function hasRoleWithSwitch(bytes32 role, address account) external view returns - +*Returns `true` if either (1) `account` has been granted `role`, or (2) the relevant role restrictions do not apply at the time of calling this function.* #### Parameters @@ -208,10 +208,10 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed ## Errors -### CanOnlyRenounceForSelf +### Permissions__CanOnlyRenounceForSelf ```solidity -error CanOnlyRenounceForSelf() +error Permissions__CanOnlyRenounceForSelf() ``` diff --git a/docs/PermissionsEnumerable.md b/docs/PermissionsEnumerable.md index 7475dbdc8..5c79f0c4c 100644 --- a/docs/PermissionsEnumerable.md +++ b/docs/PermissionsEnumerable.md @@ -142,7 +142,7 @@ function hasRoleWithSwitch(bytes32 role, address account) external view returns - +*Returns `true` if either (1) `account` has been granted `role`, or (2) the relevant role restrictions do not apply at the time of calling this function.* #### Parameters @@ -253,10 +253,10 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed ## Errors -### CanOnlyRenounceForSelf +### Permissions__CanOnlyRenounceForSelf ```solidity -error CanOnlyRenounceForSelf() +error Permissions__CanOnlyRenounceForSelf() ``` diff --git a/docs/PlatformFee.md b/docs/PlatformFee.md index b020fa427..8109c07d5 100644 --- a/docs/PlatformFee.md +++ b/docs/PlatformFee.md @@ -4,7 +4,7 @@ - +Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading the recipient of platform fee and the platform fee basis points, and lets the inheriting contract perform conditional logic that uses information about platform fees, if desired. @@ -52,7 +52,7 @@ function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeB ### PlatformFeeInfoUpdated ```solidity -event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps) +event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps) ``` @@ -63,17 +63,17 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp | Name | Type | Description | |---|---|---| -| platformFeeRecipient | address | undefined | +| platformFeeRecipient `indexed` | address | undefined | | platformFeeBps | uint256 | undefined | ## Errors -### ExceedsMaxBps +### NotAuthorized__SetPlatformFeeInfo ```solidity -error ExceedsMaxBps() +error NotAuthorized__SetPlatformFeeInfo() ``` @@ -81,10 +81,10 @@ error ExceedsMaxBps() -### NotAuthorized +### PlatformFee__ExceedsMaxBps ```solidity -error NotAuthorized() +error PlatformFee__ExceedsMaxBps() ``` diff --git a/docs/PrimarySale.md b/docs/PrimarySale.md index 11a300b1a..2e342a41f 100644 --- a/docs/PrimarySale.md +++ b/docs/PrimarySale.md @@ -4,7 +4,7 @@ - +Thirdweb's `Primary` is a contract extension to be used with any base contract. It exposes functions for setting and reading the recipient of primary sales, and lets the inheriting contract perform conditional logic that uses information about primary sales, if desired. @@ -67,10 +67,10 @@ event PrimarySaleRecipientUpdated(address indexed recipient) ## Errors -### NotAuthorized +### NotAuthorized__SetPrimarySaleRecipient ```solidity -error NotAuthorized() +error NotAuthorized__SetPrimarySaleRecipient() ``` diff --git a/docs/Royalty.md b/docs/Royalty.md index 33f52616c..7693af366 100644 --- a/docs/Royalty.md +++ b/docs/Royalty.md @@ -4,7 +4,7 @@ - +Thirdweb's `Royalty` is a contract extension to be used with any base contract. It exposes functions for setting and reading the recipient of royalty fee and the royalty fee basis points, and lets the inheriting contract perform conditional logic that uses information about royalty fees, if desired. The `Royalty` contract is ERC2981 compliant. @@ -117,7 +117,7 @@ function setRoyaltyInfoForToken(uint256 _tokenId, address _recipient, uint256 _b ### DefaultRoyalty ```solidity -event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) +event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps) ``` @@ -128,13 +128,13 @@ event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) | Name | Type | Description | |---|---|---| -| newRoyaltyRecipient | address | undefined | +| newRoyaltyRecipient `indexed` | address | undefined | | newRoyaltyBps | uint256 | undefined | ### RoyaltyForToken ```solidity -event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 royaltyBps) +event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps) ``` @@ -146,17 +146,17 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 | Name | Type | Description | |---|---|---| | tokenId `indexed` | uint256 | undefined | -| royaltyRecipient | address | undefined | +| royaltyRecipient `indexed` | address | undefined | | royaltyBps | uint256 | undefined | ## Errors -### ExceedsMaxBps +### NotAuthorized__SetRoyaltyInfo ```solidity -error ExceedsMaxBps() +error NotAuthorized__SetRoyaltyInfo() ``` @@ -164,10 +164,10 @@ error ExceedsMaxBps() -### NotAuthorized +### Royalty__ExceedsMaxBps ```solidity -error NotAuthorized() +error Royalty__ExceedsMaxBps() ``` diff --git a/docs/SignatureDrop.md b/docs/SignatureDrop.md index 2d6772855..848762804 100644 --- a/docs/SignatureDrop.md +++ b/docs/SignatureDrop.md @@ -504,7 +504,7 @@ function hasRoleWithSwitch(bytes32 role, address account) external view returns - +*Returns `true` if either (1) `account` has been granted `role`, or (2) the relevant role restrictions do not apply at the time of calling this function.* #### Parameters @@ -1246,7 +1246,7 @@ event ContractURIUpdated(string prevURI, string newURI) ### DefaultRoyalty ```solidity -event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) +event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps) ``` @@ -1257,13 +1257,13 @@ event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) | Name | Type | Description | |---|---|---| -| newRoyaltyRecipient | address | undefined | +| newRoyaltyRecipient `indexed` | address | undefined | | newRoyaltyBps | uint256 | undefined | ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -1274,13 +1274,13 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ### PlatformFeeInfoUpdated ```solidity -event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps) +event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps) ``` @@ -1291,7 +1291,7 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp | Name | Type | Description | |---|---|---| -| platformFeeRecipient | address | undefined | +| platformFeeRecipient `indexed` | address | undefined | | platformFeeBps | uint256 | undefined | ### PrimarySaleRecipientUpdated @@ -1367,7 +1367,7 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed ### RoyaltyForToken ```solidity -event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 royaltyBps) +event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps) ``` @@ -1379,13 +1379,13 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 | Name | Type | Description | |---|---|---| | tokenId `indexed` | uint256 | undefined | -| royaltyRecipient | address | undefined | +| royaltyRecipient `indexed` | address | undefined | | royaltyBps | uint256 | undefined | ### TokenURIRevealed ```solidity -event TokenURIRevealed(uint256 index, string revealedURI) +event TokenURIRevealed(uint256 indexed index, string revealedURI) ``` @@ -1396,13 +1396,13 @@ event TokenURIRevealed(uint256 index, string revealedURI) | Name | Type | Description | |---|---|---| -| index | uint256 | undefined | +| index `indexed` | uint256 | undefined | | revealedURI | string | undefined | ### TokensClaimed ```solidity -event TokensClaimed(address indexed claimer, address indexed receiver, uint256 startTokenId, uint256 quantityClaimed) +event TokensClaimed(address indexed claimer, address indexed receiver, uint256 indexed startTokenId, uint256 quantityClaimed) ``` @@ -1415,13 +1415,13 @@ event TokensClaimed(address indexed claimer, address indexed receiver, uint256 s |---|---|---| | claimer `indexed` | address | undefined | | receiver `indexed` | address | undefined | -| startTokenId | uint256 | undefined | +| startTokenId `indexed` | uint256 | undefined | | quantityClaimed | uint256 | undefined | ### TokensLazyMinted ```solidity -event TokensLazyMinted(uint256 startTokenId, uint256 endTokenId, string baseURI, bytes encryptedBaseURI) +event TokensLazyMinted(uint256 indexed startTokenId, uint256 endTokenId, string baseURI, bytes encryptedBaseURI) ``` @@ -1432,7 +1432,7 @@ event TokensLazyMinted(uint256 startTokenId, uint256 endTokenId, string baseURI, | Name | Type | Description | |---|---|---| -| startTokenId | uint256 | undefined | +| startTokenId `indexed` | uint256 | undefined | | endTokenId | uint256 | undefined | | baseURI | string | undefined | | encryptedBaseURI | bytes | undefined | @@ -1533,10 +1533,10 @@ Cannot query the balance for the zero address. -### CanOnlyRenounceForSelf +### DelayedReveal__NothingToReveal ```solidity -error CanOnlyRenounceForSelf() +error DelayedReveal__NothingToReveal() ``` @@ -1544,10 +1544,10 @@ error CanOnlyRenounceForSelf() -### CannotClaim +### DropSinglePhase__CannotClaimYet ```solidity -error CannotClaim() +error DropSinglePhase__CannotClaimYet() ``` @@ -1555,10 +1555,10 @@ error CannotClaim() -### ExceedMaxClaimableSupply +### DropSinglePhase__ExceedMaxClaimableSupply ```solidity -error ExceedMaxClaimableSupply() +error DropSinglePhase__ExceedMaxClaimableSupply() ``` @@ -1566,10 +1566,10 @@ error ExceedMaxClaimableSupply() -### ExceedsMaxBps +### DropSinglePhase__InvalidCurrencyOrPrice ```solidity -error ExceedsMaxBps() +error DropSinglePhase__InvalidCurrencyOrPrice() ``` @@ -1577,10 +1577,10 @@ error ExceedsMaxBps() -### InvalidCurrencyOrPrice +### DropSinglePhase__InvalidQuantity ```solidity -error InvalidCurrencyOrPrice() +error DropSinglePhase__InvalidQuantity() ``` @@ -1588,10 +1588,10 @@ error InvalidCurrencyOrPrice() -### InvalidQuantity +### DropSinglePhase__InvalidQuantityProof ```solidity -error InvalidQuantity() +error DropSinglePhase__InvalidQuantityProof() ``` @@ -1599,10 +1599,10 @@ error InvalidQuantity() -### InvalidQuantityProof +### DropSinglePhase__NotInWhitelist ```solidity -error InvalidQuantityProof() +error DropSinglePhase__NotInWhitelist() ``` @@ -1610,10 +1610,10 @@ error InvalidQuantityProof() -### InvalidRequest +### DropSinglePhase__ProofClaimed ```solidity -error InvalidRequest() +error DropSinglePhase__ProofClaimed() ``` @@ -1643,10 +1643,10 @@ The quantity of tokens minted must be more than zero. -### MintingZeroTokens +### NotAuthorized__SetContractURI ```solidity -error MintingZeroTokens() +error NotAuthorized__SetContractURI() ``` @@ -1654,10 +1654,10 @@ error MintingZeroTokens() -### MustSendTotalPrice +### NotAuthorized__SetOwner ```solidity -error MustSendTotalPrice() +error NotAuthorized__SetOwner() ``` @@ -1665,10 +1665,10 @@ error MustSendTotalPrice() -### NotAuthorized +### NotAuthorized__SetPlatformFeeInfo ```solidity -error NotAuthorized() +error NotAuthorized__SetPlatformFeeInfo() ``` @@ -1676,10 +1676,10 @@ error NotAuthorized() -### NotEnoughMintedTokens +### NotAuthorized__SetPrimarySaleRecipient ```solidity -error NotEnoughMintedTokens() +error NotAuthorized__SetPrimarySaleRecipient() ``` @@ -1687,10 +1687,10 @@ error NotEnoughMintedTokens() -### NotInWhitelist +### NotAuthorized__SetRoyaltyInfo ```solidity -error NotInWhitelist() +error NotAuthorized__SetRoyaltyInfo() ``` @@ -1698,10 +1698,21 @@ error NotInWhitelist() -### NotTransferRole +### OwnerQueryForNonexistentToken + +```solidity +error OwnerQueryForNonexistentToken() +``` + +The token does not exist. + + + + +### Permissions__CanOnlyRenounceForSelf ```solidity -error NotTransferRole() +error Permissions__CanOnlyRenounceForSelf() ``` @@ -1709,10 +1720,10 @@ error NotTransferRole() -### NothingToReveal +### PlatformFee__ExceedsMaxBps ```solidity -error NothingToReveal() +error PlatformFee__ExceedsMaxBps() ``` @@ -1720,21 +1731,65 @@ error NothingToReveal() -### OwnerQueryForNonexistentToken +### Royalty__ExceedsMaxBps ```solidity -error OwnerQueryForNonexistentToken() +error Royalty__ExceedsMaxBps() ``` -The token does not exist. -### ProofClaimed + +### SignatureDrop__MintingZeroTokens + +```solidity +error SignatureDrop__MintingZeroTokens() +``` + + + + + + +### SignatureDrop__MustSendTotalPrice + +```solidity +error SignatureDrop__MustSendTotalPrice() +``` + + + + + + +### SignatureDrop__NotEnoughMintedTokens + +```solidity +error SignatureDrop__NotEnoughMintedTokens() +``` + + + + + + +### SignatureDrop__NotTransferRole + +```solidity +error SignatureDrop__NotTransferRole() +``` + + + + + + +### SignatureDrop__ZeroAmount ```solidity -error ProofClaimed() +error SignatureDrop__ZeroAmount() ``` @@ -1742,10 +1797,21 @@ error ProofClaimed() -### RequestExpired +### SignatureMintERC721Upgradeable__InvalidRequest ```solidity -error RequestExpired() +error SignatureMintERC721Upgradeable__InvalidRequest() +``` + + + + + + +### SignatureMintERC721Upgradeable__RequestExpired + +```solidity +error SignatureMintERC721Upgradeable__RequestExpired() ``` @@ -1808,15 +1874,4 @@ The token does not exist. -### ZeroAmount - -```solidity -error ZeroAmount() -``` - - - - - - diff --git a/docs/SignatureMintERC721.md b/docs/SignatureMintERC721.md index aaaec85aa..cdaf51432 100644 --- a/docs/SignatureMintERC721.md +++ b/docs/SignatureMintERC721.md @@ -82,28 +82,3 @@ event TokensMintedWithSignature(address indexed signer, address indexed mintedTo -## Errors - -### InvalidRequest - -```solidity -error InvalidRequest() -``` - - - - - - -### RequestExpired - -```solidity -error RequestExpired() -``` - - - - - - - diff --git a/docs/SignatureMintERC721Upgradeable.md b/docs/SignatureMintERC721Upgradeable.md index 4b6ab1fe1..8c7dc170d 100644 --- a/docs/SignatureMintERC721Upgradeable.md +++ b/docs/SignatureMintERC721Upgradeable.md @@ -82,28 +82,3 @@ event TokensMintedWithSignature(address indexed signer, address indexed mintedTo -## Errors - -### InvalidRequest - -```solidity -error InvalidRequest() -``` - - - - - - -### RequestExpired - -```solidity -error RequestExpired() -``` - - - - - - - diff --git a/docs/ThirdwebContract.md b/docs/ThirdwebContract.md index e912eed58..89977cb18 100644 --- a/docs/ThirdwebContract.md +++ b/docs/ThirdwebContract.md @@ -66,7 +66,7 @@ function tw_initializeOwner(address deployer) external nonpayable ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -77,17 +77,17 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ## Errors -### NotAuthorized +### NotAuthorized__SetOwner ```solidity -error NotAuthorized() +error NotAuthorized__SetOwner() ``` diff --git a/docs/TokenERC1155.md b/docs/TokenERC1155.md index 288dc3350..483edbd5f 100644 --- a/docs/TokenERC1155.md +++ b/docs/TokenERC1155.md @@ -942,7 +942,7 @@ event ApprovalForAll(address indexed account, address indexed operator, bool app ### DefaultRoyalty ```solidity -event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) +event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps) ``` @@ -953,13 +953,13 @@ event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) | Name | Type | Description | |---|---|---| -| newRoyaltyRecipient | address | undefined | +| newRoyaltyRecipient `indexed` | address | undefined | | newRoyaltyBps | uint256 | undefined | ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -970,13 +970,13 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ### PlatformFeeInfoUpdated ```solidity -event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps) +event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps) ``` @@ -987,7 +987,7 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp | Name | Type | Description | |---|---|---| -| platformFeeRecipient | address | undefined | +| platformFeeRecipient `indexed` | address | undefined | | platformFeeBps | uint256 | undefined | ### PrimarySaleRecipientUpdated @@ -1063,7 +1063,7 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed ### RoyaltyForToken ```solidity -event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 royaltyBps) +event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps) ``` @@ -1075,7 +1075,7 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 | Name | Type | Description | |---|---|---| | tokenId `indexed` | uint256 | undefined | -| royaltyRecipient | address | undefined | +| royaltyRecipient `indexed` | address | undefined | | royaltyBps | uint256 | undefined | ### TokensMinted diff --git a/docs/TokenERC20.md b/docs/TokenERC20.md index 6831346e6..7de176d09 100644 --- a/docs/TokenERC20.md +++ b/docs/TokenERC20.md @@ -1060,7 +1060,7 @@ event Paused(address account) ### PlatformFeeInfoUpdated ```solidity -event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps) +event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps) ``` @@ -1071,7 +1071,7 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp | Name | Type | Description | |---|---|---| -| platformFeeRecipient | address | undefined | +| platformFeeRecipient `indexed` | address | undefined | | platformFeeBps | uint256 | undefined | ### PrimarySaleRecipientUpdated diff --git a/docs/TokenERC721.md b/docs/TokenERC721.md index 5b29e087b..87ff0f65a 100644 --- a/docs/TokenERC721.md +++ b/docs/TokenERC721.md @@ -1002,7 +1002,7 @@ event ApprovalForAll(address indexed owner, address indexed operator, bool appro ### DefaultRoyalty ```solidity -event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) +event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps) ``` @@ -1013,13 +1013,13 @@ event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) | Name | Type | Description | |---|---|---| -| newRoyaltyRecipient | address | undefined | +| newRoyaltyRecipient `indexed` | address | undefined | | newRoyaltyBps | uint256 | undefined | ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -1030,13 +1030,13 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ### PlatformFeeInfoUpdated ```solidity -event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBps) +event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps) ``` @@ -1047,7 +1047,7 @@ event PlatformFeeInfoUpdated(address platformFeeRecipient, uint256 platformFeeBp | Name | Type | Description | |---|---|---| -| platformFeeRecipient | address | undefined | +| platformFeeRecipient `indexed` | address | undefined | | platformFeeBps | uint256 | undefined | ### PrimarySaleRecipientUpdated @@ -1123,7 +1123,7 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed ### RoyaltyForToken ```solidity -event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 royaltyBps) +event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps) ``` @@ -1135,7 +1135,7 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 | Name | Type | Description | |---|---|---| | tokenId `indexed` | uint256 | undefined | -| royaltyRecipient | address | undefined | +| royaltyRecipient `indexed` | address | undefined | | royaltyBps | uint256 | undefined | ### TokensMinted diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 5809ba13c..0c76f5e02 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -258,7 +258,7 @@ contract SignatureDropTest is BaseTest { sigdrop.setClaimConditions(conditions[0], false); vm.prank(getActor(5), getActor(5)); - vm.expectRevert("cannot claim yet."); + vm.expectRevert(bytes4(abi.encodeWithSignature("CannotClaimYet()"))); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } From da4542c607bf87e642721155eed4c754e91552d6 Mon Sep 17 00:00:00 2001 From: Yash Date: Fri, 24 Jun 2022 17:25:27 +0530 Subject: [PATCH 21/41] update tests --- src/test/SignatureDrop.t.sol | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 0c76f5e02..571886802 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -258,7 +258,7 @@ contract SignatureDropTest is BaseTest { sigdrop.setClaimConditions(conditions[0], false); vm.prank(getActor(5), getActor(5)); - vm.expectRevert(bytes4(abi.encodeWithSignature("CannotClaimYet()"))); + vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__CannotClaimYet()"))); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } @@ -532,7 +532,7 @@ contract SignatureDropTest is BaseTest { sigdrop.lazyMint(100, "", encryptedURI); sigdrop.reveal(0, "key"); - vm.expectRevert("nothing to reveal."); + vm.expectRevert(bytes4(abi.encodeWithSignature("DelayedReveal__NothingToReveal()"))); sigdrop.reveal(0, "key"); vm.stopPrank(); @@ -682,7 +682,7 @@ contract SignatureDropTest is BaseTest { sigdrop.mintWithSignature(mintrequest, signature); signature = signMintRequest(mintrequest, 4321); - vm.expectRevert("Invalid request"); + vm.expectRevert(bytes4(abi.encodeWithSignature("SignatureMintERC721Upgradeable__InvalidRequest()"))); sigdrop.mintWithSignature(mintrequest, signature); } @@ -709,7 +709,7 @@ contract SignatureDropTest is BaseTest { bytes memory signature = signMintRequest(mintrequest, privateKey); vm.warp(1000); - vm.expectRevert("not enough minted tokens."); + vm.expectRevert(bytes4(abi.encodeWithSignature("SignatureDrop__NotEnoughMintedTokens()"))); sigdrop.mintWithSignature(mintrequest, signature); } @@ -738,7 +738,7 @@ contract SignatureDropTest is BaseTest { bytes memory signature = signMintRequest(mintrequest, privateKey); vm.startPrank(address(deployerSigner)); vm.warp(mintrequest.validityStartTimestamp); - vm.expectRevert("must send total price."); + vm.expectRevert(bytes4(abi.encodeWithSignature("SignatureDrop__MustSendTotalPrice()"))); sigdrop.mintWithSignature{ value: 2 }(mintrequest, signature); vm.stopPrank(); } @@ -870,7 +870,7 @@ contract SignatureDropTest is BaseTest { vm.prank(getActor(5), getActor(5)); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); - vm.expectRevert("cannot claim yet."); + vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__CannotClaimYet()"))); vm.prank(getActor(5), getActor(5)); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } @@ -897,7 +897,7 @@ contract SignatureDropTest is BaseTest { vm.prank(deployerSigner); sigdrop.setClaimConditions(conditions[0], false); - vm.expectRevert("not enough minted tokens."); + vm.expectRevert(bytes4(abi.encodeWithSignature("SignatureDrop__NotEnoughMintedTokens()"))); vm.prank(getActor(6), getActor(6)); sigdrop.claim(receiver, 101, address(0), 0, alp, ""); } @@ -927,7 +927,7 @@ contract SignatureDropTest is BaseTest { vm.prank(getActor(5), getActor(5)); sigdrop.claim(receiver, 100, address(0), 0, alp, ""); - vm.expectRevert("exceed max claimable supply."); + vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__ExceedMaxClaimableSupply()"))); vm.prank(getActor(6), getActor(6)); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } @@ -958,14 +958,14 @@ contract SignatureDropTest is BaseTest { sigdrop.setClaimConditions(conditions[0], false); vm.prank(getActor(5)); - vm.expectRevert("invalid quantity."); + vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__InvalidQuantity()"))); sigdrop.claim(receiver, 101, address(0), 0, alp, ""); vm.prank(deployerSigner); sigdrop.setClaimConditions(conditions[0], true); vm.prank(getActor(5)); - vm.expectRevert("invalid quantity."); + vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__InvalidQuantity()"))); sigdrop.claim(receiver, 101, address(0), 0, alp, ""); } @@ -1010,7 +1010,7 @@ contract SignatureDropTest is BaseTest { sigdrop.claim(receiver, 1, address(0), 0, alp, ""); vm.prank(address(4)); - vm.expectRevert("not in whitelist."); + vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__NotInWhitelist()"))); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } @@ -1076,7 +1076,7 @@ contract SignatureDropTest is BaseTest { assertEq(uri, string(abi.encodePacked("ipfs://", "1"))); bytes memory newEncryptedURI = sigdrop.encryptDecrypt("ipfs://secret", "key"); - vm.expectRevert("Zero amount"); + vm.expectRevert(bytes4(abi.encodeWithSignature("SignatureDrop__ZeroAmount()"))); sigdrop.lazyMint(0, "", newEncryptedURI); vm.stopPrank(); From f79abd31d36ca2333c0fa6941c71f3b358b21c16 Mon Sep 17 00:00:00 2001 From: Yash Date: Fri, 24 Jun 2022 17:26:44 +0530 Subject: [PATCH 22/41] run prettier --- contracts/feature/ContractMetadata.sol | 2 +- contracts/feature/DelayedReveal.sol | 2 +- contracts/feature/DropSinglePhase.sol | 25 +++++++++------ contracts/feature/Errors.sol | 32 +++++++++---------- contracts/feature/LazyMint.sol | 1 - contracts/feature/Ownable.sol | 2 +- contracts/feature/Permissions.sol | 2 +- contracts/feature/PlatformFee.sol | 4 +-- contracts/feature/PrimarySale.sol | 2 +- contracts/feature/Royalty.sol | 8 ++--- contracts/feature/SignatureMintERC721.sol | 5 +-- .../SignatureMintERC721Upgradeable.sol | 5 +-- contracts/signature-drop/SignatureDrop.sol | 12 +++---- 13 files changed, 55 insertions(+), 47 deletions(-) diff --git a/contracts/feature/ContractMetadata.sol b/contracts/feature/ContractMetadata.sol index c3dd9f87a..256dbc6b8 100644 --- a/contracts/feature/ContractMetadata.sol +++ b/contracts/feature/ContractMetadata.sol @@ -18,7 +18,7 @@ abstract contract ContractMetadata is IContractMetadata { /// @dev Lets a contract admin set the URI for contract-level metadata. function setContractURI(string memory _uri) external override { // require(_canSetContractURI(), "Not authorized"); - if(!_canSetContractURI()) revert NotAuthorized__SetContractURI(); + if (!_canSetContractURI()) revert NotAuthorized__SetContractURI(); _setupContractURI(_uri); } diff --git a/contracts/feature/DelayedReveal.sol b/contracts/feature/DelayedReveal.sol index 21b309ef6..cb20a15a9 100644 --- a/contracts/feature/DelayedReveal.sol +++ b/contracts/feature/DelayedReveal.sol @@ -22,7 +22,7 @@ abstract contract DelayedReveal is IDelayedReveal { function getRevealURI(uint256 _batchId, bytes calldata _key) public view returns (string memory revealedURI) { bytes memory encryptedURI = encryptedBaseURI[_batchId]; // require(encryptedURI.length != 0, "nothing to reveal."); - if(encryptedURI.length == 0) revert DelayedReveal__NothingToReveal(); + if (encryptedURI.length == 0) revert DelayedReveal__NothingToReveal(); revealedURI = string(encryptDecrypt(encryptedURI, _key)); } diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index 1f15a5772..eceae02d2 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -38,7 +38,6 @@ abstract contract DropSinglePhase is IDropSinglePhase { /*/////////////////////////////////////////////////////////////// Errors //////////////////////////////////////////////////////////////*/ - /*/////////////////////////////////////////////////////////////// Drop logic @@ -145,7 +144,8 @@ abstract contract DropSinglePhase is IDropSinglePhase { // _currency == currentClaimPhase.currency && _pricePerToken == currentClaimPhase.pricePerToken, // "invalid currency or price." // ); - if(_currency != currentClaimPhase.currency || _pricePerToken != currentClaimPhase.pricePerToken) revert DropSinglePhase__InvalidCurrencyOrPrice(); + if (_currency != currentClaimPhase.currency || _pricePerToken != currentClaimPhase.pricePerToken) + revert DropSinglePhase__InvalidCurrencyOrPrice(); // If we're checking for an allowlist quantity restriction, ignore the general quantity restriction. // require( @@ -153,13 +153,17 @@ abstract contract DropSinglePhase is IDropSinglePhase { // (!verifyMaxQuantityPerTransaction || _quantity <= currentClaimPhase.quantityLimitPerTransaction), // "invalid quantity." // ); - if(_quantity == 0 || (verifyMaxQuantityPerTransaction && _quantity > currentClaimPhase.quantityLimitPerTransaction)) revert DropSinglePhase__InvalidQuantity(); + if ( + _quantity == 0 || + (verifyMaxQuantityPerTransaction && _quantity > currentClaimPhase.quantityLimitPerTransaction) + ) revert DropSinglePhase__InvalidQuantity(); // require( // currentClaimPhase.supplyClaimed + _quantity <= currentClaimPhase.maxClaimableSupply, // "exceed max claimable supply." // ); - if(currentClaimPhase.supplyClaimed + _quantity > currentClaimPhase.maxClaimableSupply) revert DropSinglePhase__ExceedMaxClaimableSupply(); + if (currentClaimPhase.supplyClaimed + _quantity > currentClaimPhase.maxClaimableSupply) + revert DropSinglePhase__ExceedMaxClaimableSupply(); (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); // require( @@ -167,8 +171,10 @@ abstract contract DropSinglePhase is IDropSinglePhase { // (lastClaimedAt == 0 || block.timestamp >= nextValidClaimTimestamp), // "cannot claim yet." // ); - if(claimCondition.startTimestamp >= block.timestamp || - (lastClaimedAt != 0 && block.timestamp < nextValidClaimTimestamp)) revert DropSinglePhase__CannotClaimYet(); + if ( + claimCondition.startTimestamp >= block.timestamp || + (lastClaimedAt != 0 && block.timestamp < nextValidClaimTimestamp) + ) revert DropSinglePhase__CannotClaimYet(); } /// @dev Checks whether a claimer meets the claim condition's allowlist criteria. @@ -186,16 +192,17 @@ abstract contract DropSinglePhase is IDropSinglePhase { keccak256(abi.encodePacked(_claimer, _allowlistProof.maxQuantityInAllowlist)) ); // require(validMerkleProof, "not in whitelist."); - if(!validMerkleProof) revert DropSinglePhase__NotInWhitelist(); + if (!validMerkleProof) revert DropSinglePhase__NotInWhitelist(); // require(!usedAllowlistSpot[conditionId].get(merkleProofIndex), "proof claimed."); - if(usedAllowlistSpot[conditionId].get(merkleProofIndex)) revert DropSinglePhase__ProofClaimed(); + if (usedAllowlistSpot[conditionId].get(merkleProofIndex)) revert DropSinglePhase__ProofClaimed(); // require( // _allowlistProof.maxQuantityInAllowlist == 0 || _quantity <= _allowlistProof.maxQuantityInAllowlist, // "invalid quantity proof." // ); - if(_allowlistProof.maxQuantityInAllowlist != 0 && _quantity > _allowlistProof.maxQuantityInAllowlist) revert DropSinglePhase__InvalidQuantityProof(); + if (_allowlistProof.maxQuantityInAllowlist != 0 && _quantity > _allowlistProof.maxQuantityInAllowlist) + revert DropSinglePhase__InvalidQuantityProof(); } } diff --git a/contracts/feature/Errors.sol b/contracts/feature/Errors.sol index b9fa5c65b..5c8145751 100644 --- a/contracts/feature/Errors.sol +++ b/contracts/feature/Errors.sol @@ -17,13 +17,13 @@ error NotAuthorized(); //////////////////////////////////////////////////////////////*/ /* -* Contract: DelayedReveal.sol -*/ + * Contract: DelayedReveal.sol + */ error DelayedReveal__NothingToReveal(); /* -* Contract: DropSinglePhase.sol -*/ + * Contract: DropSinglePhase.sol + */ error DropSinglePhase__InvalidCurrencyOrPrice(); error DropSinglePhase__InvalidQuantity(); error DropSinglePhase__ExceedMaxClaimableSupply(); @@ -33,34 +33,34 @@ error DropSinglePhase__ProofClaimed(); error DropSinglePhase__InvalidQuantityProof(); /* -* Contract: Permissions.sol -*/ + * Contract: Permissions.sol + */ error Permissions__CanOnlyRenounceForSelf(); /* -* Contract: PlatformFee.sol -*/ + * Contract: PlatformFee.sol + */ error PlatformFee__ExceedsMaxBps(); /* -* Contract: Royalty.sol -*/ + * Contract: Royalty.sol + */ error Royalty__ExceedsMaxBps(); /* -* Contract: SignatureMintERC721.sol -* Contract: SignatureMintERC721Upgradeable.sol -*/ + * Contract: SignatureMintERC721.sol + * Contract: SignatureMintERC721Upgradeable.sol + */ error SignatureMintERC721__InvalidRequest(); error SignatureMintERC721__RequestExpired(); error SignatureMintERC721Upgradeable__InvalidRequest(); error SignatureMintERC721Upgradeable__RequestExpired(); /* -* Contract: SignatureDrop.sol -*/ + * Contract: SignatureDrop.sol + */ error SignatureDrop__NotEnoughMintedTokens(); error SignatureDrop__MintingZeroTokens(); error SignatureDrop__ZeroAmount(); error SignatureDrop__MustSendTotalPrice(); -error SignatureDrop__NotTransferRole(); \ No newline at end of file +error SignatureDrop__NotTransferRole(); diff --git a/contracts/feature/LazyMint.sol b/contracts/feature/LazyMint.sol index 073e5bc8c..6916296d4 100644 --- a/contracts/feature/LazyMint.sol +++ b/contracts/feature/LazyMint.sol @@ -66,7 +66,6 @@ abstract contract LazyMint is ILazyMint { uint256 _amountToMint, string calldata _baseURIForTokens ) internal returns (uint256 nextTokenIdToMint, uint256 batchId) { - batchId = _startId + _amountToMint; nextTokenIdToMint = batchId; diff --git a/contracts/feature/Ownable.sol b/contracts/feature/Ownable.sol index 38635c628..0391348ce 100644 --- a/contracts/feature/Ownable.sol +++ b/contracts/feature/Ownable.sol @@ -17,7 +17,7 @@ abstract contract Ownable is IOwnable { /// @dev Lets a contract admin set a new owner for the contract. The new owner must be a contract admin. function setOwner(address _newOwner) external override { // require(_canSetOwner(), "Not authorized"); - if(!_canSetOwner()) revert NotAuthorized__SetOwner(); + if (!_canSetOwner()) revert NotAuthorized__SetOwner(); _setupOwner(_newOwner); } diff --git a/contracts/feature/Permissions.sol b/contracts/feature/Permissions.sol index c6d3b2b30..936f00e6f 100644 --- a/contracts/feature/Permissions.sol +++ b/contracts/feature/Permissions.sol @@ -45,7 +45,7 @@ contract Permissions is IPermissions { function renounceRole(bytes32 role, address account) public virtual override { // require(msg.sender == account, "Can only renounce for self"); - if(msg.sender != account) revert Permissions__CanOnlyRenounceForSelf(); + if (msg.sender != account) revert Permissions__CanOnlyRenounceForSelf(); _revokeRole(role, account); } diff --git a/contracts/feature/PlatformFee.sol b/contracts/feature/PlatformFee.sol index f29e8bf65..9d3a9d1e9 100644 --- a/contracts/feature/PlatformFee.sol +++ b/contracts/feature/PlatformFee.sol @@ -25,14 +25,14 @@ abstract contract PlatformFee is IPlatformFee { /// @dev Lets a contract admin update the platform fee recipient and bps function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external override { // require(_canSetPlatformFeeInfo(), "Not authorized"); - if(!_canSetPlatformFeeInfo()) revert NotAuthorized__SetPlatformFeeInfo(); + if (!_canSetPlatformFeeInfo()) revert NotAuthorized__SetPlatformFeeInfo(); _setupPlatformFeeInfo(_platformFeeRecipient, _platformFeeBps); } /// @dev Lets a contract admin update the platform fee recipient and bps function _setupPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) internal { // require(_platformFeeBps <= 10_000, "Exceeds max bps"); - if(_platformFeeBps > 10_000) revert PlatformFee__ExceedsMaxBps(); + if (_platformFeeBps > 10_000) revert PlatformFee__ExceedsMaxBps(); platformFeeBps = uint16(_platformFeeBps); platformFeeRecipient = _platformFeeRecipient; diff --git a/contracts/feature/PrimarySale.sol b/contracts/feature/PrimarySale.sol index 0b3b4c276..c9a2800da 100644 --- a/contracts/feature/PrimarySale.sol +++ b/contracts/feature/PrimarySale.sol @@ -21,7 +21,7 @@ abstract contract PrimarySale is IPrimarySale { /// @dev Lets a contract admin set the recipient for all primary sales. function setPrimarySaleRecipient(address _saleRecipient) external override { // require(_canSetPrimarySaleRecipient(), "Not authorized"); - if(!_canSetPrimarySaleRecipient()) revert NotAuthorized__SetPrimarySaleRecipient(); + if (!_canSetPrimarySaleRecipient()) revert NotAuthorized__SetPrimarySaleRecipient(); _setupPrimarySaleRecipient(_saleRecipient); } diff --git a/contracts/feature/Royalty.sol b/contracts/feature/Royalty.sol index 2a657cb56..3c436e355 100644 --- a/contracts/feature/Royalty.sol +++ b/contracts/feature/Royalty.sol @@ -53,7 +53,7 @@ abstract contract Royalty is IRoyalty { /// @dev Lets a contract admin update the default royalty recipient and bps. function setDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) external override { // require(_canSetRoyaltyInfo(), "Not authorized"); - if(!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); + if (!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); _setupDefaultRoyaltyInfo(_royaltyRecipient, _royaltyBps); } @@ -61,7 +61,7 @@ abstract contract Royalty is IRoyalty { /// @dev Lets a contract admin update the default royalty recipient and bps. function _setupDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) internal { // require(_royaltyBps <= 10_000, "Exceeds max bps"); - if(_royaltyBps > 10_000) revert Royalty__ExceedsMaxBps(); + if (_royaltyBps > 10_000) revert Royalty__ExceedsMaxBps(); royaltyRecipient = _royaltyRecipient; royaltyBps = uint16(_royaltyBps); @@ -76,7 +76,7 @@ abstract contract Royalty is IRoyalty { uint256 _bps ) external override { // require(_canSetRoyaltyInfo(), "Not authorized"); - if(!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); + if (!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); _setupRoyaltyInfoForToken(_tokenId, _recipient, _bps); } @@ -88,7 +88,7 @@ abstract contract Royalty is IRoyalty { uint256 _bps ) internal { // require(_bps <= 10_000, "Exceeds max bps"); - if(_bps > 10_000) revert Royalty__ExceedsMaxBps(); + if (_bps > 10_000) revert Royalty__ExceedsMaxBps(); royaltyInfoForToken[_tokenId] = RoyaltyInfo({ recipient: _recipient, bps: _bps }); diff --git a/contracts/feature/SignatureMintERC721.sol b/contracts/feature/SignatureMintERC721.sol index 0ebbd0759..97321e537 100644 --- a/contracts/feature/SignatureMintERC721.sol +++ b/contracts/feature/SignatureMintERC721.sol @@ -40,13 +40,14 @@ abstract contract SignatureMintERC721 is EIP712, ISignatureMintERC721 { (success, signer) = verify(_req, _signature); // require(success, "Invalid request"); - if(!success) revert SignatureMintERC721__InvalidRequest(); + if (!success) revert SignatureMintERC721__InvalidRequest(); // require( // _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, // "Request expired" // ); - if(_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) revert SignatureMintERC721__RequestExpired(); + if (_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) + revert SignatureMintERC721__RequestExpired(); minted[_req.uid] = true; } diff --git a/contracts/feature/SignatureMintERC721Upgradeable.sol b/contracts/feature/SignatureMintERC721Upgradeable.sol index c670d1f7f..d8c750f52 100644 --- a/contracts/feature/SignatureMintERC721Upgradeable.sol +++ b/contracts/feature/SignatureMintERC721Upgradeable.sol @@ -44,13 +44,14 @@ abstract contract SignatureMintERC721Upgradeable is Initializable, EIP712Upgrade (success, signer) = verify(_req, _signature); // require(success, "Invalid request"); - if(!success) revert SignatureMintERC721Upgradeable__InvalidRequest(); + if (!success) revert SignatureMintERC721Upgradeable__InvalidRequest(); // require( // _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, // "Request expired" // ); - if(_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) revert SignatureMintERC721Upgradeable__RequestExpired(); + if (_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) + revert SignatureMintERC721Upgradeable__RequestExpired(); minted[_req.uid] = true; } diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index 359a34470..2a7360bda 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -155,7 +155,7 @@ contract SignatureDrop is string calldata _baseURIForTokens, bytes calldata _encryptedBaseURI ) external onlyRole(MINTER_ROLE) returns (uint256 batchId) { - if(_amount == 0) revert SignatureDrop__ZeroAmount(); + if (_amount == 0) revert SignatureDrop__ZeroAmount(); uint256 startId = nextTokenIdToMint; @@ -194,11 +194,11 @@ contract SignatureDrop is returns (address signer) { // require(_req.quantity > 0, "minting zero tokens"); - if(_req.quantity == 0) revert SignatureDrop__MintingZeroTokens(); + if (_req.quantity == 0) revert SignatureDrop__MintingZeroTokens(); uint256 tokenIdToMint = _currentIndex; // require(tokenIdToMint + _req.quantity <= nextTokenIdToMint, "not enough minted tokens."); - if(tokenIdToMint + _req.quantity > nextTokenIdToMint) revert SignatureDrop__NotEnoughMintedTokens(); + if (tokenIdToMint + _req.quantity > nextTokenIdToMint) revert SignatureDrop__NotEnoughMintedTokens(); // Verify and process payload. signer = _processRequest(_req, _signature); @@ -235,7 +235,7 @@ contract SignatureDrop is bytes memory ) internal view override { // require(_currentIndex + _quantity <= nextTokenIdToMint, "not enough minted tokens."); - if(_currentIndex + _quantity > nextTokenIdToMint) revert SignatureDrop__NotEnoughMintedTokens(); + if (_currentIndex + _quantity > nextTokenIdToMint) revert SignatureDrop__NotEnoughMintedTokens(); } /// @dev Collects and distributes the primary sale value of NFTs being claimed. @@ -255,7 +255,7 @@ contract SignatureDrop is if (_currency == CurrencyTransferLib.NATIVE_TOKEN) { // require(msg.value == totalPrice, "must send total price."); - if(msg.value != totalPrice) revert SignatureDrop__MustSendTotalPrice(); + if (msg.value != totalPrice) revert SignatureDrop__MustSendTotalPrice(); } CurrencyTransferLib.transferCurrency(_currency, _msgSender(), platformFeeRecipient, platformFees); @@ -334,7 +334,7 @@ contract SignatureDrop is // if transfer is restricted on the contract, we still want to allow burning and minting if (!hasRole(TRANSFER_ROLE, address(0)) && from != address(0) && to != address(0)) { // require(hasRole(TRANSFER_ROLE, from) || hasRole(TRANSFER_ROLE, to), "!TRANSFER_ROLE"); - if(!hasRole(TRANSFER_ROLE, from) && !hasRole(TRANSFER_ROLE, to)) revert SignatureDrop__NotTransferRole(); + if (!hasRole(TRANSFER_ROLE, from) && !hasRole(TRANSFER_ROLE, to)) revert SignatureDrop__NotTransferRole(); } } From 6ce18b8fdc0853ed24cf82f56807b7f5fbe64eec Mon Sep 17 00:00:00 2001 From: Yash Date: Fri, 24 Jun 2022 23:48:46 +0530 Subject: [PATCH 23/41] [L-6] claimCondition.startTimestamp is not enforced -- revised fix --- contracts/feature/DropSinglePhase.sol | 2 +- lib/forge-std | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index 575588d37..36a09ce78 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -153,7 +153,7 @@ abstract contract DropSinglePhase is IDropSinglePhase { (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); require( - claimCondition.startTimestamp < block.timestamp && + claimCondition.startTimestamp <= block.timestamp && (lastClaimedAt == 0 || block.timestamp >= nextValidClaimTimestamp), "cannot claim yet." ); diff --git a/lib/forge-std b/lib/forge-std index 0d0485bde..9a538e315 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 0d0485bdea9f9455bd684acb0ba88548a104d99b +Subproject commit 9a538e31562a6323a1fb36e838417e72047b5de7 From e7a11f95e767c1deaa053a09d496984bac022568 Mon Sep 17 00:00:00 2001 From: Yash Date: Sat, 25 Jun 2022 17:38:23 +0530 Subject: [PATCH 24/41] [L-6] claimCondition.startTimestamp is not enforced --- contracts/feature/DropSinglePhase.sol | 2 +- src/test/SignatureDrop.t.sol | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index 36a09ce78..debcb5270 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -153,7 +153,7 @@ abstract contract DropSinglePhase is IDropSinglePhase { (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); require( - claimCondition.startTimestamp <= block.timestamp && + currentClaimPhase.startTimestamp <= block.timestamp && (lastClaimedAt == 0 || block.timestamp >= nextValidClaimTimestamp), "cannot claim yet." ); diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 5809ba13c..54122f09f 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -257,6 +257,11 @@ contract SignatureDropTest is BaseTest { vm.prank(deployerSigner); sigdrop.setClaimConditions(conditions[0], false); + vm.warp(100); + vm.prank(getActor(4), getActor(4)); + sigdrop.claim(receiver, 1, address(0), 0, alp, ""); + + vm.warp(99); vm.prank(getActor(5), getActor(5)); vm.expectRevert("cannot claim yet."); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); From 826b577e5ba3294566d02d8dcd01cb42c329713e Mon Sep 17 00:00:00 2001 From: Yash Date: Sat, 25 Jun 2022 20:01:31 +0530 Subject: [PATCH 25/41] reorganize errors and checks --- contracts/feature/ContractMetadata.sol | 7 +- contracts/feature/DelayedReveal.sol | 5 +- contracts/feature/Drop.sol | 1 - contracts/feature/DropSinglePhase.sol | 44 ++++++--- contracts/feature/Errors.sol | 66 ------------- contracts/feature/LazyMint.sol | 9 +- contracts/feature/Ownable.sol | 8 +- contracts/feature/Permissions.sol | 10 +- contracts/feature/PlatformFee.sol | 12 ++- contracts/feature/PrimarySale.sol | 8 +- contracts/feature/Royalty.sol | 19 ++-- contracts/feature/SignatureMintERC721.sol | 10 +- .../SignatureMintERC721Upgradeable.sol | 10 +- .../feature/interface/IDelayedReveal.sol | 3 + .../feature/interface/IDropSinglePhase.sol | 24 +++++ contracts/feature/interface/ILazyMint.sol | 9 ++ contracts/feature/interface/IPermissions.sol | 6 ++ contracts/feature/interface/IPlatformFee.sol | 3 + contracts/feature/interface/IRoyalty.sol | 3 + .../interface/ISignatureMintERC721.sol | 6 ++ contracts/signature-drop/SignatureDrop.sol | 96 ++++++++++++++----- 21 files changed, 211 insertions(+), 148 deletions(-) delete mode 100644 contracts/feature/Errors.sol diff --git a/contracts/feature/ContractMetadata.sol b/contracts/feature/ContractMetadata.sol index 256dbc6b8..e5a8e7d10 100644 --- a/contracts/feature/ContractMetadata.sol +++ b/contracts/feature/ContractMetadata.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; import "./interface/IContractMetadata.sol"; -import "./Errors.sol"; /** * Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI @@ -18,7 +17,7 @@ abstract contract ContractMetadata is IContractMetadata { /// @dev Lets a contract admin set the URI for contract-level metadata. function setContractURI(string memory _uri) external override { // require(_canSetContractURI(), "Not authorized"); - if (!_canSetContractURI()) revert NotAuthorized__SetContractURI(); + _canSetContractURI(); _setupContractURI(_uri); } @@ -30,6 +29,6 @@ abstract contract ContractMetadata is IContractMetadata { emit ContractURIUpdated(prevURI, _uri); } - /// @dev Returns whether contract metadata can be set in the given execution context. - function _canSetContractURI() internal virtual returns (bool); + /// @dev Checks whether contract metadata can be set in the given execution context. + function _canSetContractURI() internal virtual; } diff --git a/contracts/feature/DelayedReveal.sol b/contracts/feature/DelayedReveal.sol index cb20a15a9..85a8915b1 100644 --- a/contracts/feature/DelayedReveal.sol +++ b/contracts/feature/DelayedReveal.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; import "./interface/IDelayedReveal.sol"; -import "./Errors.sol"; /** * Thirdweb's `DelayedReveal` is a contract extension for base NFT contracts. It lets you create batches of @@ -22,7 +21,9 @@ abstract contract DelayedReveal is IDelayedReveal { function getRevealURI(uint256 _batchId, bytes calldata _key) public view returns (string memory revealedURI) { bytes memory encryptedURI = encryptedBaseURI[_batchId]; // require(encryptedURI.length != 0, "nothing to reveal."); - if (encryptedURI.length == 0) revert DelayedReveal__NothingToReveal(); + if (encryptedURI.length == 0) { + revert DelayedReveal__NothingToReveal(_batchId); + } revealedURI = string(encryptDecrypt(encryptedURI, _key)); } diff --git a/contracts/feature/Drop.sol b/contracts/feature/Drop.sol index b973b5c70..7194ff439 100644 --- a/contracts/feature/Drop.sol +++ b/contracts/feature/Drop.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import "./interface/IDrop.sol"; import "../lib/MerkleProof.sol"; import "../lib/TWBitMaps.sol"; -import "./Errors.sol"; abstract contract Drop is IDrop { using TWBitMaps for TWBitMaps.BitMap; diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index eceae02d2..471cb83a3 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.0; import "./interface/IDropSinglePhase.sol"; import "../lib/MerkleProof.sol"; import "../lib/TWBitMaps.sol"; -import "./Errors.sol"; abstract contract DropSinglePhase is IDropSinglePhase { using TWBitMaps for TWBitMaps.BitMap; @@ -103,7 +102,8 @@ abstract contract DropSinglePhase is IDropSinglePhase { /// @dev Lets a contract admin set claim conditions. function setClaimConditions(ClaimCondition calldata _condition, bool _resetClaimEligibility) external override { - require(_canSetClaimConditions(), "Not authorized"); + // require(_canSetClaimConditions(), "Not authorized"); + _canSetClaimConditions(); bytes32 targetConditionId = conditionId; uint256 supplyClaimedAlready = claimCondition.supplyClaimed; @@ -113,7 +113,10 @@ abstract contract DropSinglePhase is IDropSinglePhase { targetConditionId = keccak256(abi.encodePacked(_dropMsgSender(), block.number)); } - require(supplyClaimedAlready <= _condition.maxClaimableSupply, "max supply claimed already"); + // require(supplyClaimedAlready <= _condition.maxClaimableSupply, "max supply claimed already"); + if(supplyClaimedAlready > _condition.maxClaimableSupply) { + revert DropSinglePhase__MaxSupplyClaimedAlready(supplyClaimedAlready); + } claimCondition = ClaimCondition({ startTimestamp: _condition.startTimestamp, @@ -144,8 +147,9 @@ abstract contract DropSinglePhase is IDropSinglePhase { // _currency == currentClaimPhase.currency && _pricePerToken == currentClaimPhase.pricePerToken, // "invalid currency or price." // ); - if (_currency != currentClaimPhase.currency || _pricePerToken != currentClaimPhase.pricePerToken) - revert DropSinglePhase__InvalidCurrencyOrPrice(); + if (_currency != currentClaimPhase.currency || _pricePerToken != currentClaimPhase.pricePerToken) { + revert DropSinglePhase__InvalidCurrencyOrPrice(_currency, currentClaimPhase.currency, _pricePerToken, currentClaimPhase.pricePerToken); + } // If we're checking for an allowlist quantity restriction, ignore the general quantity restriction. // require( @@ -156,14 +160,17 @@ abstract contract DropSinglePhase is IDropSinglePhase { if ( _quantity == 0 || (verifyMaxQuantityPerTransaction && _quantity > currentClaimPhase.quantityLimitPerTransaction) - ) revert DropSinglePhase__InvalidQuantity(); + ) { + revert DropSinglePhase__InvalidQuantity(); + } // require( // currentClaimPhase.supplyClaimed + _quantity <= currentClaimPhase.maxClaimableSupply, // "exceed max claimable supply." // ); - if (currentClaimPhase.supplyClaimed + _quantity > currentClaimPhase.maxClaimableSupply) - revert DropSinglePhase__ExceedMaxClaimableSupply(); + if (currentClaimPhase.supplyClaimed + _quantity > currentClaimPhase.maxClaimableSupply) { + revert DropSinglePhase__ExceedMaxClaimableSupply(currentClaimPhase.supplyClaimed, currentClaimPhase.maxClaimableSupply); + } (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); // require( @@ -172,9 +179,11 @@ abstract contract DropSinglePhase is IDropSinglePhase { // "cannot claim yet." // ); if ( - claimCondition.startTimestamp >= block.timestamp || + currentClaimPhase.startTimestamp >= block.timestamp || (lastClaimedAt != 0 && block.timestamp < nextValidClaimTimestamp) - ) revert DropSinglePhase__CannotClaimYet(); + ) { + revert DropSinglePhase__CannotClaimYet(block.timestamp, currentClaimPhase.startTimestamp, lastClaimedAt, nextValidClaimTimestamp); + } } /// @dev Checks whether a claimer meets the claim condition's allowlist criteria. @@ -192,17 +201,22 @@ abstract contract DropSinglePhase is IDropSinglePhase { keccak256(abi.encodePacked(_claimer, _allowlistProof.maxQuantityInAllowlist)) ); // require(validMerkleProof, "not in whitelist."); - if (!validMerkleProof) revert DropSinglePhase__NotInWhitelist(); + if (!validMerkleProof) { + revert DropSinglePhase__NotInWhitelist(); + } // require(!usedAllowlistSpot[conditionId].get(merkleProofIndex), "proof claimed."); - if (usedAllowlistSpot[conditionId].get(merkleProofIndex)) revert DropSinglePhase__ProofClaimed(); + if (usedAllowlistSpot[conditionId].get(merkleProofIndex)) { + revert DropSinglePhase__ProofClaimed(); + } // require( // _allowlistProof.maxQuantityInAllowlist == 0 || _quantity <= _allowlistProof.maxQuantityInAllowlist, // "invalid quantity proof." // ); - if (_allowlistProof.maxQuantityInAllowlist != 0 && _quantity > _allowlistProof.maxQuantityInAllowlist) - revert DropSinglePhase__InvalidQuantityProof(); + if (_allowlistProof.maxQuantityInAllowlist != 0 && _quantity > _allowlistProof.maxQuantityInAllowlist) { + revert DropSinglePhase__InvalidQuantityProof(_allowlistProof.maxQuantityInAllowlist); + } } } @@ -265,5 +279,5 @@ abstract contract DropSinglePhase is IDropSinglePhase { virtual returns (uint256 startTokenId); - function _canSetClaimConditions() internal virtual returns (bool); + function _canSetClaimConditions() internal virtual; } diff --git a/contracts/feature/Errors.sol b/contracts/feature/Errors.sol deleted file mode 100644 index 5c8145751..000000000 --- a/contracts/feature/Errors.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.0; - -/*/////////////////////////////////////////////////////////////// - Common Errors -//////////////////////////////////////////////////////////////*/ - -error NotAuthorized__SetContractURI(); -error NotAuthorized__SetOwner(); -error NotAuthorized__SetPlatformFeeInfo(); -error NotAuthorized__SetPrimarySaleRecipient(); -error NotAuthorized__SetRoyaltyInfo(); -error NotAuthorized(); - -/*/////////////////////////////////////////////////////////////// - Contract Specific Errors -//////////////////////////////////////////////////////////////*/ - -/* - * Contract: DelayedReveal.sol - */ -error DelayedReveal__NothingToReveal(); - -/* - * Contract: DropSinglePhase.sol - */ -error DropSinglePhase__InvalidCurrencyOrPrice(); -error DropSinglePhase__InvalidQuantity(); -error DropSinglePhase__ExceedMaxClaimableSupply(); -error DropSinglePhase__CannotClaimYet(); -error DropSinglePhase__NotInWhitelist(); -error DropSinglePhase__ProofClaimed(); -error DropSinglePhase__InvalidQuantityProof(); - -/* - * Contract: Permissions.sol - */ -error Permissions__CanOnlyRenounceForSelf(); - -/* - * Contract: PlatformFee.sol - */ -error PlatformFee__ExceedsMaxBps(); - -/* - * Contract: Royalty.sol - */ -error Royalty__ExceedsMaxBps(); - -/* - * Contract: SignatureMintERC721.sol - * Contract: SignatureMintERC721Upgradeable.sol - */ -error SignatureMintERC721__InvalidRequest(); -error SignatureMintERC721__RequestExpired(); -error SignatureMintERC721Upgradeable__InvalidRequest(); -error SignatureMintERC721Upgradeable__RequestExpired(); - -/* - * Contract: SignatureDrop.sol - */ -error SignatureDrop__NotEnoughMintedTokens(); -error SignatureDrop__MintingZeroTokens(); -error SignatureDrop__ZeroAmount(); -error SignatureDrop__MustSendTotalPrice(); -error SignatureDrop__NotTransferRole(); diff --git a/contracts/feature/LazyMint.sol b/contracts/feature/LazyMint.sol index 6916296d4..03f12c883 100644 --- a/contracts/feature/LazyMint.sol +++ b/contracts/feature/LazyMint.sol @@ -23,7 +23,10 @@ abstract contract LazyMint is ILazyMint { /// @dev Returns the id for the batch of tokens the given tokenId belongs to. function getBatchIdAtIndex(uint256 _index) public view returns (uint256) { - require(_index < getBaseURICount(), "invalid index."); + // require(_index < getBaseURICount(), "invalid index."); + if(_index >= getBaseURICount()) { + revert LazyMint__InvalidIndex(_index); + } return batchIds[_index]; } @@ -38,7 +41,7 @@ abstract contract LazyMint is ILazyMint { } } - revert("No batch id for token."); + revert LazyMint__NoBatchIDForToken(_tokenId); } /// @dev Returns the baseURI for a token. The intended metadata URI for the token is baseURI + tokenId. @@ -52,7 +55,7 @@ abstract contract LazyMint is ILazyMint { } } - revert("No base URI for token."); + revert LazyMint__NoBaseURIForToken(_tokenId); } /// @dev Sets the base URI for the batch of tokens with the given batchId. diff --git a/contracts/feature/Ownable.sol b/contracts/feature/Ownable.sol index 0391348ce..42342a642 100644 --- a/contracts/feature/Ownable.sol +++ b/contracts/feature/Ownable.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; import "./interface/IOwnable.sol"; -import "./Errors.sol"; /** * Thirdweb's `Ownable` is a contract extension to be used with any base contract. It exposes functions for setting and reading @@ -17,7 +16,8 @@ abstract contract Ownable is IOwnable { /// @dev Lets a contract admin set a new owner for the contract. The new owner must be a contract admin. function setOwner(address _newOwner) external override { // require(_canSetOwner(), "Not authorized"); - if (!_canSetOwner()) revert NotAuthorized__SetOwner(); + // if (!_canSetOwner()) revert NotAuthorized__SetOwner(); + _canSetOwner(); _setupOwner(_newOwner); } @@ -29,6 +29,6 @@ abstract contract Ownable is IOwnable { emit OwnerUpdated(_prevOwner, _newOwner); } - /// @dev Returns whether owner can be set in the given execution context. - function _canSetOwner() internal virtual returns (bool); + /// @dev Checks whether owner can be set in the given execution context. + function _canSetOwner() internal virtual; } diff --git a/contracts/feature/Permissions.sol b/contracts/feature/Permissions.sol index 936f00e6f..95f4832d1 100644 --- a/contracts/feature/Permissions.sol +++ b/contracts/feature/Permissions.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.0; import "./interface/IPermissions.sol"; import "../lib/TWStrings.sol"; -import "./Errors.sol"; contract Permissions is IPermissions { mapping(bytes32 => mapping(address => bool)) private _hasRole; @@ -34,7 +33,10 @@ contract Permissions is IPermissions { function grantRole(bytes32 role, address account) public virtual override { _checkRole(_getRoleAdmin[role], msg.sender); - require(!_hasRole[role][account], "Can only grant to non holders"); + // require(!_hasRole[role][account], "Can only grant to non holders"); + if(_hasRole[role][account]) { + revert Permissions__CanOnlyGrantToNonHolders(account); + } _setupRole(role, account); } @@ -45,7 +47,9 @@ contract Permissions is IPermissions { function renounceRole(bytes32 role, address account) public virtual override { // require(msg.sender == account, "Can only renounce for self"); - if (msg.sender != account) revert Permissions__CanOnlyRenounceForSelf(); + if (msg.sender != account) { + revert Permissions__CanOnlyRenounceForSelf(msg.sender, account); + } _revokeRole(role, account); } diff --git a/contracts/feature/PlatformFee.sol b/contracts/feature/PlatformFee.sol index 9d3a9d1e9..7374410f5 100644 --- a/contracts/feature/PlatformFee.sol +++ b/contracts/feature/PlatformFee.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; import "./interface/IPlatformFee.sol"; -import "./Errors.sol"; /** * Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading @@ -25,14 +24,17 @@ abstract contract PlatformFee is IPlatformFee { /// @dev Lets a contract admin update the platform fee recipient and bps function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external override { // require(_canSetPlatformFeeInfo(), "Not authorized"); - if (!_canSetPlatformFeeInfo()) revert NotAuthorized__SetPlatformFeeInfo(); + // if (!_canSetPlatformFeeInfo()) revert NotAuthorized__SetPlatformFeeInfo(); + _canSetPlatformFeeInfo(); _setupPlatformFeeInfo(_platformFeeRecipient, _platformFeeBps); } /// @dev Lets a contract admin update the platform fee recipient and bps function _setupPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) internal { // require(_platformFeeBps <= 10_000, "Exceeds max bps"); - if (_platformFeeBps > 10_000) revert PlatformFee__ExceedsMaxBps(); + if (_platformFeeBps > 10_000) { + revert PlatformFee__ExceedsMaxBps(_platformFeeBps); + } platformFeeBps = uint16(_platformFeeBps); platformFeeRecipient = _platformFeeRecipient; @@ -40,6 +42,6 @@ abstract contract PlatformFee is IPlatformFee { emit PlatformFeeInfoUpdated(_platformFeeRecipient, _platformFeeBps); } - /// @dev Returns whether platform fee info can be set in the given execution context. - function _canSetPlatformFeeInfo() internal virtual returns (bool); + /// @dev Checks whether platform fee info can be set in the given execution context. + function _canSetPlatformFeeInfo() internal virtual; } diff --git a/contracts/feature/PrimarySale.sol b/contracts/feature/PrimarySale.sol index c9a2800da..d645b5189 100644 --- a/contracts/feature/PrimarySale.sol +++ b/contracts/feature/PrimarySale.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; import "./interface/IPrimarySale.sol"; -import "./Errors.sol"; /** * Thirdweb's `Primary` is a contract extension to be used with any base contract. It exposes functions for setting and reading @@ -21,7 +20,8 @@ abstract contract PrimarySale is IPrimarySale { /// @dev Lets a contract admin set the recipient for all primary sales. function setPrimarySaleRecipient(address _saleRecipient) external override { // require(_canSetPrimarySaleRecipient(), "Not authorized"); - if (!_canSetPrimarySaleRecipient()) revert NotAuthorized__SetPrimarySaleRecipient(); + // if (!_canSetPrimarySaleRecipient()) revert NotAuthorized__SetPrimarySaleRecipient(); + _canSetPrimarySaleRecipient(); _setupPrimarySaleRecipient(_saleRecipient); } @@ -31,6 +31,6 @@ abstract contract PrimarySale is IPrimarySale { emit PrimarySaleRecipientUpdated(_saleRecipient); } - /// @dev Returns whether primary sale recipient can be set in the given execution context. - function _canSetPrimarySaleRecipient() internal virtual returns (bool); + /// @dev Checks whether primary sale recipient can be set in the given execution context. + function _canSetPrimarySaleRecipient() internal virtual; } diff --git a/contracts/feature/Royalty.sol b/contracts/feature/Royalty.sol index 3c436e355..21bf11d18 100644 --- a/contracts/feature/Royalty.sol +++ b/contracts/feature/Royalty.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; import "./interface/IRoyalty.sol"; -import "./Errors.sol"; /** * Thirdweb's `Royalty` is a contract extension to be used with any base contract. It exposes functions for setting and reading @@ -53,7 +52,8 @@ abstract contract Royalty is IRoyalty { /// @dev Lets a contract admin update the default royalty recipient and bps. function setDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) external override { // require(_canSetRoyaltyInfo(), "Not authorized"); - if (!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); + // if (!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); + _canSetRoyaltyInfo(); _setupDefaultRoyaltyInfo(_royaltyRecipient, _royaltyBps); } @@ -61,7 +61,9 @@ abstract contract Royalty is IRoyalty { /// @dev Lets a contract admin update the default royalty recipient and bps. function _setupDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) internal { // require(_royaltyBps <= 10_000, "Exceeds max bps"); - if (_royaltyBps > 10_000) revert Royalty__ExceedsMaxBps(); + if (_royaltyBps > 10_000) { + revert Royalty__ExceedsMaxBps(_royaltyBps); + } royaltyRecipient = _royaltyRecipient; royaltyBps = uint16(_royaltyBps); @@ -76,7 +78,8 @@ abstract contract Royalty is IRoyalty { uint256 _bps ) external override { // require(_canSetRoyaltyInfo(), "Not authorized"); - if (!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); + // if (!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); + _canSetRoyaltyInfo(); _setupRoyaltyInfoForToken(_tokenId, _recipient, _bps); } @@ -88,13 +91,15 @@ abstract contract Royalty is IRoyalty { uint256 _bps ) internal { // require(_bps <= 10_000, "Exceeds max bps"); - if (_bps > 10_000) revert Royalty__ExceedsMaxBps(); + if (_bps > 10_000) { + revert Royalty__ExceedsMaxBps(_bps); + } royaltyInfoForToken[_tokenId] = RoyaltyInfo({ recipient: _recipient, bps: _bps }); emit RoyaltyForToken(_tokenId, _recipient, _bps); } - /// @dev Returns whether royalty info can be set in the given execution context. - function _canSetRoyaltyInfo() internal virtual returns (bool); + /// @dev Checks whether royalty info can be set in the given execution context. + function _canSetRoyaltyInfo() internal virtual; } diff --git a/contracts/feature/SignatureMintERC721.sol b/contracts/feature/SignatureMintERC721.sol index 97321e537..d0bf37ec3 100644 --- a/contracts/feature/SignatureMintERC721.sol +++ b/contracts/feature/SignatureMintERC721.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; import "./interface/ISignatureMintERC721.sol"; -import "./Errors.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; @@ -40,14 +39,17 @@ abstract contract SignatureMintERC721 is EIP712, ISignatureMintERC721 { (success, signer) = verify(_req, _signature); // require(success, "Invalid request"); - if (!success) revert SignatureMintERC721__InvalidRequest(); + if (!success) { + revert SignatureMintERC721__InvalidRequest(); + } // require( // _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, // "Request expired" // ); - if (_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) - revert SignatureMintERC721__RequestExpired(); + if (_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) { + revert SignatureMintERC721__RequestExpired(block.timestamp); + } minted[_req.uid] = true; } diff --git a/contracts/feature/SignatureMintERC721Upgradeable.sol b/contracts/feature/SignatureMintERC721Upgradeable.sol index d8c750f52..d779da5a0 100644 --- a/contracts/feature/SignatureMintERC721Upgradeable.sol +++ b/contracts/feature/SignatureMintERC721Upgradeable.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.0; import "./interface/ISignatureMintERC721.sol"; -import "./Errors.sol"; import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol"; @@ -44,14 +43,17 @@ abstract contract SignatureMintERC721Upgradeable is Initializable, EIP712Upgrade (success, signer) = verify(_req, _signature); // require(success, "Invalid request"); - if (!success) revert SignatureMintERC721Upgradeable__InvalidRequest(); + if (!success) { + revert SignatureMintERC721__InvalidRequest(); + } // require( // _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, // "Request expired" // ); - if (_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) - revert SignatureMintERC721Upgradeable__RequestExpired(); + if (_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) { + revert SignatureMintERC721__RequestExpired(block.timestamp); + } minted[_req.uid] = true; } diff --git a/contracts/feature/interface/IDelayedReveal.sol b/contracts/feature/interface/IDelayedReveal.sol index 34cf16498..25e4e3b55 100644 --- a/contracts/feature/interface/IDelayedReveal.sol +++ b/contracts/feature/interface/IDelayedReveal.sol @@ -7,6 +7,9 @@ pragma solidity ^0.8.0; */ interface IDelayedReveal { + /// @notice Emitted when encrypted URI for a given batch is empty. + error DelayedReveal__NothingToReveal(uint256 batchId); + /** * @notice Reveals a batch of delayed reveal NFTs. * diff --git a/contracts/feature/interface/IDropSinglePhase.sol b/contracts/feature/interface/IDropSinglePhase.sol index 82d71e69c..c7629656d 100644 --- a/contracts/feature/interface/IDropSinglePhase.sol +++ b/contracts/feature/interface/IDropSinglePhase.sol @@ -9,6 +9,30 @@ interface IDropSinglePhase is IClaimCondition { uint256 maxQuantityInAllowlist; } + /// @notice Emitted when given currency or price is invalid. + error DropSinglePhase__InvalidCurrencyOrPrice(address givenCurrency, address requiredCurrency, uint256 givenPricePerToken, uint256 requiredPricePerToken); + + /// @notice Emitted when claiming invalid quantity of tokens. + error DropSinglePhase__InvalidQuantity(); + + /// @notice Emitted when claiming given quantity will exceed max claimable supply. + error DropSinglePhase__ExceedMaxClaimableSupply(uint256 supplyClaimed, uint256 maxClaimableSupply); + + /// @notice Emitted when the current timestamp is invalid for claim. + error DropSinglePhase__CannotClaimYet(uint256 blockTimestamp, uint256 startTimestamp, uint256 lastClaimedAt, uint256 nextValidClaimTimestamp); + + /// @notice Emitted when given allowlist proof is invalid. + error DropSinglePhase__NotInWhitelist(); + + /// @notice Emitted when allowlist spot is already used. + error DropSinglePhase__ProofClaimed(); + + /// @notice Emitted when claiming more than allowed quantity in allowlist. + error DropSinglePhase__InvalidQuantityProof(uint256 maxQuantityInAllowlist); + + /// @notice Emitted when max claimable supply in given condition is less than supply claimed already. + error DropSinglePhase__MaxSupplyClaimedAlready(uint256 supplyClaimedAlready); + /// @dev Emitted when tokens are claimed via `claim`. event TokensClaimed( address indexed claimer, diff --git a/contracts/feature/interface/ILazyMint.sol b/contracts/feature/interface/ILazyMint.sol index 1dbfe0a1f..a17653ae5 100644 --- a/contracts/feature/interface/ILazyMint.sol +++ b/contracts/feature/interface/ILazyMint.sol @@ -8,6 +8,15 @@ pragma solidity ^0.8.0; */ interface ILazyMint { + /// @notice Emitted when the given index is equal to or higher than total number of batches. + error LazyMint__InvalidIndex(uint256 index); + + /// @notice Emitted when the given token ID doesn't belong to any batch. + error LazyMint__NoBatchIDForToken(uint256 tokenId); + + /// @notice Emitted when there's no Base URI set for the given token ID. + error LazyMint__NoBaseURIForToken(uint256 tokenId); + /** * @notice Lazy mints a given amount of NFTs. * diff --git a/contracts/feature/interface/IPermissions.sol b/contracts/feature/interface/IPermissions.sol index 097209a26..74ff3f108 100644 --- a/contracts/feature/interface/IPermissions.sol +++ b/contracts/feature/interface/IPermissions.sol @@ -5,6 +5,12 @@ pragma solidity ^0.8.0; * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IPermissions { + /// @notice Emitted when calling address is different from the specified account. + error Permissions__CanOnlyRenounceForSelf(address caller, address account); + + /// @notice Emitted when specified account already has the role. + error Permissions__CanOnlyGrantToNonHolders(address account); + /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * diff --git a/contracts/feature/interface/IPlatformFee.sol b/contracts/feature/interface/IPlatformFee.sol index 4b65aa30d..fa833ed65 100644 --- a/contracts/feature/interface/IPlatformFee.sol +++ b/contracts/feature/interface/IPlatformFee.sol @@ -8,6 +8,9 @@ pragma solidity ^0.8.0; */ interface IPlatformFee { + /// @notice Emitted when given platform-fee bps exceeds max bps. + error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps); + /// @dev Returns the platform fee bps and recipient. function getPlatformFeeInfo() external view returns (address, uint16); diff --git a/contracts/feature/interface/IRoyalty.sol b/contracts/feature/interface/IRoyalty.sol index 33cfd082e..e518b17de 100644 --- a/contracts/feature/interface/IRoyalty.sol +++ b/contracts/feature/interface/IRoyalty.sol @@ -15,6 +15,9 @@ interface IRoyalty { uint256 bps; } + /// @notice Emitted when the given bps exceeds max bps. + error Royalty__ExceedsMaxBps(uint256 royaltyBps); + /// @dev Returns the royalty recipient and fee bps. function getDefaultRoyaltyInfo() external view returns (address, uint16); diff --git a/contracts/feature/interface/ISignatureMintERC721.sol b/contracts/feature/interface/ISignatureMintERC721.sol index 0edfd9769..681890319 100644 --- a/contracts/feature/interface/ISignatureMintERC721.sol +++ b/contracts/feature/interface/ISignatureMintERC721.sol @@ -9,6 +9,12 @@ pragma solidity ^0.8.0; * minted by that external party. */ interface ISignatureMintERC721 { + /// @notice Emitted when either the signature or the request uid is invalid. + error SignatureMintERC721__InvalidRequest(); + + /// @notice Emitted when block-timestamp is outside of validity start and end range. + error SignatureMintERC721__RequestExpired(uint256 blockTimestamp); + /** * @notice The body of a request to mint tokens. * diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index 2a7360bda..e647efbb1 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -27,8 +27,6 @@ import "../feature/PermissionsEnumerable.sol"; import "../feature/DropSinglePhase.sol"; import "../feature/SignatureMintERC721Upgradeable.sol"; -import "../feature/Errors.sol"; - contract SignatureDrop is Initializable, ContractMetadata, @@ -72,6 +70,28 @@ contract SignatureDrop is event TokensLazyMinted(uint256 indexed startTokenId, uint256 endTokenId, string baseURI, bytes encryptedBaseURI); event TokenURIRevealed(uint256 indexed index, string revealedURI); + /*/////////////////////////////////////////////////////////////// + Custom Errors + //////////////////////////////////////////////////////////////*/ + + /// @notice Emitted when caller is not admin. + error SignatureDrop__NotAuthorized(address caller); + + /// @notice Emitted when minting the given quantity will exceed available quantity. + error SignatureDrop__NotEnoughMintedTokens(uint256 currentIndex, uint256 quantity); + + /// @notice Emitted when given quantity to mint is zero. + error SignatureDrop__MintingZeroTokens(); + + /// @notice Emitted when given amount for lazy-minting is zero. + error SignatureDrop__ZeroAmount(); + + /// @notice Emitted when sent value doesn't match the total price of tokens. + error SignatureDrop__MustSendTotalPrice(uint256 sentValue, uint256 totalPrice); + + /// @notice Emitted when given address doesn't have transfer role. + error SignatureDrop__NotTransferRole(); + /*/////////////////////////////////////////////////////////////// Constructor + initializer logic //////////////////////////////////////////////////////////////*/ @@ -155,7 +175,9 @@ contract SignatureDrop is string calldata _baseURIForTokens, bytes calldata _encryptedBaseURI ) external onlyRole(MINTER_ROLE) returns (uint256 batchId) { - if (_amount == 0) revert SignatureDrop__ZeroAmount(); + if (_amount == 0) { + revert SignatureDrop__ZeroAmount(); + } uint256 startId = nextTokenIdToMint; @@ -194,11 +216,15 @@ contract SignatureDrop is returns (address signer) { // require(_req.quantity > 0, "minting zero tokens"); - if (_req.quantity == 0) revert SignatureDrop__MintingZeroTokens(); + if (_req.quantity == 0) { + revert SignatureDrop__MintingZeroTokens(); + } uint256 tokenIdToMint = _currentIndex; // require(tokenIdToMint + _req.quantity <= nextTokenIdToMint, "not enough minted tokens."); - if (tokenIdToMint + _req.quantity > nextTokenIdToMint) revert SignatureDrop__NotEnoughMintedTokens(); + if (tokenIdToMint + _req.quantity > nextTokenIdToMint) { + revert SignatureDrop__NotEnoughMintedTokens(tokenIdToMint, _req.quantity); + } // Verify and process payload. signer = _processRequest(_req, _signature); @@ -235,7 +261,9 @@ contract SignatureDrop is bytes memory ) internal view override { // require(_currentIndex + _quantity <= nextTokenIdToMint, "not enough minted tokens."); - if (_currentIndex + _quantity > nextTokenIdToMint) revert SignatureDrop__NotEnoughMintedTokens(); + if (_currentIndex + _quantity > nextTokenIdToMint) { + revert SignatureDrop__NotEnoughMintedTokens(_currentIndex, _quantity); + } } /// @dev Collects and distributes the primary sale value of NFTs being claimed. @@ -255,7 +283,9 @@ contract SignatureDrop is if (_currency == CurrencyTransferLib.NATIVE_TOKEN) { // require(msg.value == totalPrice, "must send total price."); - if (msg.value != totalPrice) revert SignatureDrop__MustSendTotalPrice(); + if (msg.value != totalPrice) { + revert SignatureDrop__MustSendTotalPrice(msg.value, totalPrice); + } } CurrencyTransferLib.transferCurrency(_currency, _msgSender(), platformFeeRecipient, platformFees); @@ -282,34 +312,46 @@ contract SignatureDrop is return hasRole(MINTER_ROLE, _signer); } - /// @dev Returns whether platform fee info can be set in the given execution context. - function _canSetPlatformFeeInfo() internal view override returns (bool) { - return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); + /// @dev Checks whether platform fee info can be set in the given execution context. + function _canSetPlatformFeeInfo() internal view override { + if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { + revert SignatureDrop__NotAuthorized(_msgSender()); + } } - /// @dev Returns whether primary sale recipient can be set in the given execution context. - function _canSetPrimarySaleRecipient() internal view override returns (bool) { - return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); + /// @dev Checks whether primary sale recipient can be set in the given execution context. + function _canSetPrimarySaleRecipient() internal view override { + if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { + revert SignatureDrop__NotAuthorized(_msgSender()); + } } - /// @dev Returns whether owner can be set in the given execution context. - function _canSetOwner() internal view override returns (bool) { - return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); + /// @dev Checks whether owner can be set in the given execution context. + function _canSetOwner() internal view override { + if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { + revert SignatureDrop__NotAuthorized(_msgSender()); + } } - /// @dev Returns whether royalty info can be set in the given execution context. - function _canSetRoyaltyInfo() internal view override returns (bool) { - return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); + /// @dev Checks whether royalty info can be set in the given execution context. + function _canSetRoyaltyInfo() internal view override { + if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { + revert SignatureDrop__NotAuthorized(_msgSender()); + } } - /// @dev Returns whether contract metadata can be set in the given execution context. - function _canSetContractURI() internal view override returns (bool) { - return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); + /// @dev Checks whether contract metadata can be set in the given execution context. + function _canSetContractURI() internal view override { + if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { + revert SignatureDrop__NotAuthorized(_msgSender()); + } } - /// @dev Returns whether platform fee info can be set in the given execution context. - function _canSetClaimConditions() internal view override returns (bool) { - return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); + /// @dev Checks whether platform fee info can be set in the given execution context. + function _canSetClaimConditions() internal view override { + if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { + revert SignatureDrop__NotAuthorized(_msgSender()); + } } /*/////////////////////////////////////////////////////////////// @@ -334,7 +376,9 @@ contract SignatureDrop is // if transfer is restricted on the contract, we still want to allow burning and minting if (!hasRole(TRANSFER_ROLE, address(0)) && from != address(0) && to != address(0)) { // require(hasRole(TRANSFER_ROLE, from) || hasRole(TRANSFER_ROLE, to), "!TRANSFER_ROLE"); - if (!hasRole(TRANSFER_ROLE, from) && !hasRole(TRANSFER_ROLE, to)) revert SignatureDrop__NotTransferRole(); + if (!hasRole(TRANSFER_ROLE, from) && !hasRole(TRANSFER_ROLE, to)) { + revert SignatureDrop__NotTransferRole(); + } } } From 763f68525c58a63e308c47775cbadd9d98875aac Mon Sep 17 00:00:00 2001 From: nkrishang <62195808+nkrishang@users.noreply.github.com> Date: Sun, 26 Jun 2022 10:54:01 -0400 Subject: [PATCH 26/41] 0xMacro audit Jun '22: Multiwrap (#181) * [H-1] Wrapped ETH cannot be unwrapped * [L-1] Anyone can call renounceRole(), and delete the first valid entry from roleMembers for any role * [L-2] Incorrect supportsInterface implementation * [G-4] Require revert msg string length > 32 for Multiwrap: L176 (edited) * [G-3] Optimization done in CurrencyTransferLib for rare edge cases, increases gas costs for all other use cases. * [G-2] Improvements for _setBundle() * [L-7] Unsafe usage of msg.value within CurrencyTransfer library * [G-5] Return early in PermissionsEnumerable#getRoleMember Co-authored-by: Krishang Nadgauda --- contracts/feature/Permissions.sol | 1 + contracts/feature/PermissionsEnumerable.sol | 1 + contracts/feature/TokenBundle.sol | 19 +++- contracts/feature/TokenStore.sol | 22 +++- contracts/lib/CurrencyTransferLib.sol | 12 -- contracts/multiwrap/Multiwrap.sol | 10 +- src/test/Multiwrap.t.sol | 117 +++++++++++++++++++- 7 files changed, 156 insertions(+), 26 deletions(-) diff --git a/contracts/feature/Permissions.sol b/contracts/feature/Permissions.sol index d990737d6..b96365c7c 100644 --- a/contracts/feature/Permissions.sol +++ b/contracts/feature/Permissions.sol @@ -58,6 +58,7 @@ contract Permissions is IPermissions { } function _revokeRole(bytes32 role, address account) internal virtual { + _checkRole(role, account); delete _hasRole[role][account]; emit RoleRevoked(role, account, msg.sender); } diff --git a/contracts/feature/PermissionsEnumerable.sol b/contracts/feature/PermissionsEnumerable.sol index 035bb898f..9366b0e88 100644 --- a/contracts/feature/PermissionsEnumerable.sol +++ b/contracts/feature/PermissionsEnumerable.sol @@ -21,6 +21,7 @@ contract PermissionsEnumerable is IPermissionsEnumerable, Permissions { if (roleMembers[role].members[i] != address(0)) { if (check == index) { member = roleMembers[role].members[i]; + return member; } } else { check += 1; diff --git a/contracts/feature/TokenBundle.sol b/contracts/feature/TokenBundle.sol index d18b1c0a5..efd5ed3e6 100644 --- a/contracts/feature/TokenBundle.sol +++ b/contracts/feature/TokenBundle.sol @@ -22,8 +22,23 @@ abstract contract TokenBundle is ITokenBundle { return bundle[_bundleId].uri; } - /// @dev Lets the calling contract create/update a bundle, by passing in a list of tokens and a unique id. - function _setBundle(Token[] calldata _tokensToBind, uint256 _bundleId) internal { + /// @dev Lets the calling contract create a bundle, by passing in a list of tokens and a unique id. + function _createBundle(Token[] calldata _tokensToBind, uint256 _bundleId) internal { + + uint256 targetCount = _tokensToBind.length; + + require(targetCount > 0, "TokenBundle: no tokens to bind."); + require(bundle[_bundleId].count == 0, "TokenBundle: existent at bundleId"); + + for (uint256 i = 0; i < targetCount; i += 1) { + bundle[_bundleId].tokens[i] = _tokensToBind[i]; + } + + bundle[_bundleId].count = targetCount; + } + + /// @dev Lets the calling contract update a bundle, by passing in a list of tokens and a unique id. + function _updateBundle(Token[] calldata _tokensToBind, uint256 _bundleId) internal { require(_tokensToBind.length > 0, "TokenBundle: no tokens to bind."); uint256 currentCount = bundle[_bundleId].count; diff --git a/contracts/feature/TokenStore.sol b/contracts/feature/TokenStore.sol index 220a2a770..931029cc6 100644 --- a/contracts/feature/TokenStore.sol +++ b/contracts/feature/TokenStore.sol @@ -16,7 +16,7 @@ import "../lib/CurrencyTransferLib.sol"; contract TokenStore is TokenBundle, ERC721Holder, ERC1155Holder { /// @dev The address of the native token wrapper contract. - address private immutable nativeTokenWrapper; + address internal immutable nativeTokenWrapper; constructor(address _nativeTokenWrapper) { nativeTokenWrapper = _nativeTokenWrapper; @@ -29,7 +29,7 @@ contract TokenStore is TokenBundle, ERC721Holder, ERC1155Holder { string calldata _uriForTokens, uint256 _idForTokens ) internal { - _setBundle(_tokens, _idForTokens); + _createBundle(_tokens, _idForTokens); _setUriOfBundle(_uriForTokens, _idForTokens); _transferTokenBatch(_tokenOwner, address(this), _tokens); } @@ -75,8 +75,22 @@ contract TokenStore is TokenBundle, ERC721Holder, ERC1155Holder { address _to, Token[] memory _tokens ) internal { + uint256 nativeTokenValue; for (uint256 i = 0; i < _tokens.length; i += 1) { - _transferToken(_from, _to, _tokens[i]); + if (_tokens[i].assetContract == CurrencyTransferLib.NATIVE_TOKEN && _to == address(this)) { + nativeTokenValue += _tokens[i].totalAmount; + } else { + _transferToken(_from, _to, _tokens[i]); + } + } + if (nativeTokenValue != 0) { + Token memory _nativeToken = Token({ + assetContract: CurrencyTransferLib.NATIVE_TOKEN, + tokenType: ITokenBundle.TokenType.ERC20, + tokenId: 0, + totalAmount: nativeTokenValue + }); + _transferToken(_from, _to, _nativeToken); } } -} +} \ No newline at end of file diff --git a/contracts/lib/CurrencyTransferLib.sol b/contracts/lib/CurrencyTransferLib.sol index ca5de846e..549cff919 100644 --- a/contracts/lib/CurrencyTransferLib.sol +++ b/contracts/lib/CurrencyTransferLib.sol @@ -19,10 +19,6 @@ library CurrencyTransferLib { address _to, uint256 _amount ) internal { - if (_amount == 0) { - return; - } - if (_currency == NATIVE_TOKEN) { safeTransferNativeToken(_to, _amount); } else { @@ -38,10 +34,6 @@ library CurrencyTransferLib { uint256 _amount, address _nativeTokenWrapper ) internal { - if (_amount == 0) { - return; - } - if (_currency == NATIVE_TOKEN) { if (_from == address(this)) { // withdraw from weth then transfer withdrawn native token to recipient @@ -66,10 +58,6 @@ library CurrencyTransferLib { address _to, uint256 _amount ) internal { - if (_from == _to) { - return; - } - if (_from == address(this)) { IERC20Upgradeable(_currency).safeTransfer(_to, _amount); } else { diff --git a/contracts/multiwrap/Multiwrap.sol b/contracts/multiwrap/Multiwrap.sol index 699d073f4..37736c94c 100644 --- a/contracts/multiwrap/Multiwrap.sol +++ b/contracts/multiwrap/Multiwrap.sol @@ -116,6 +116,11 @@ contract Multiwrap is return uint8(VERSION); } + /// @dev Lets the contract receive ether to unwrap native tokens. + receive() external payable { + require(msg.sender == nativeTokenWrapper, "caller not native token wrapper."); + } + /*/////////////////////////////////////////////////////////////// ERC 165 / 721 / 2981 logic //////////////////////////////////////////////////////////////*/ @@ -136,6 +141,7 @@ contract Multiwrap is return super.supportsInterface(interfaceId) || interfaceId == type(IERC721Upgradeable).interfaceId || + interfaceId == type(IERC1155Receiver).interfaceId || interfaceId == type(IERC2981Upgradeable).interfaceId; } @@ -167,8 +173,8 @@ contract Multiwrap is /// @dev Unwrap a wrapped NFT to retrieve underlying ERC1155, ERC721, ERC20 tokens. function unwrap(uint256 _tokenId, address _recipient) external nonReentrant onlyRoleWithSwitch(UNWRAP_ROLE) { - require(_tokenId < nextTokenIdToMint, "Multiwrap: wrapped NFT DNE."); - require(_isApprovedOrOwner(_msgSender(), _tokenId), "Multiwrap: caller not approved for unwrapping."); + require(_tokenId < nextTokenIdToMint, "wrapped NFT DNE."); + require(_isApprovedOrOwner(_msgSender(), _tokenId), "caller not approved for unwrapping."); _burn(_tokenId); _releaseTokens(_recipient, _tokenId); diff --git a/src/test/Multiwrap.t.sol b/src/test/Multiwrap.t.sol index d3e84a90b..bf6699948 100644 --- a/src/test/Multiwrap.t.sol +++ b/src/test/Multiwrap.t.sol @@ -5,6 +5,7 @@ import { Multiwrap } from "contracts/multiwrap/Multiwrap.sol"; import { ITokenBundle } from "contracts/feature/interface/ITokenBundle.sol"; // Test imports +import "contracts/lib/TWStrings.sol"; import { MockERC20 } from "./mocks/MockERC20.sol"; import { Wallet } from "./utils/Wallet.sol"; import "./utils/BaseTest.sol"; @@ -13,7 +14,7 @@ contract MultiwrapReentrant is MockERC20, ITokenBundle { Multiwrap internal multiwrap; uint256 internal tokenIdOfWrapped = 0; - constructor(address _multiwrap) { + constructor(address payable _multiwrap) { multiwrap = Multiwrap(_multiwrap); } @@ -57,7 +58,7 @@ contract MultiwrapTest is BaseTest { super.setUp(); // Get target contract - multiwrap = Multiwrap(getContract("Multiwrap")); + multiwrap = Multiwrap(payable(getContract("Multiwrap"))); // Set test vars tokenOwner = getWallet(); @@ -103,6 +104,51 @@ contract MultiwrapTest is BaseTest { multiwrap.grantRole(keccak256("MINTER_ROLE"), address(tokenOwner)); } + /*/////////////////////////////////////////////////////////////// + Unit tests: misc. + //////////////////////////////////////////////////////////////*/ + + /** + * note: Tests whether contract revert when a non-holder renounces a role. + */ + function test_revert_nonHolder_renounceRole() public { + + address caller = address(0x123); + bytes32 role = keccak256("MINTER_ROLE"); + + vm.prank(caller); + vm.expectRevert( + abi.encodePacked( + "Permissions: account ", + TWStrings.toHexString(uint160(caller), 20), + " is missing role ", + TWStrings.toHexString(uint256(role), 32) + ) + ); + + multiwrap.renounceRole(role, caller); + } + + /** + * note: Tests whether contract revert when a role admin revokes a role for a non-holder. + */ + function test_revert_revokeRoleForNonHolder() public { + address target = address(0x123); + bytes32 role = keccak256("MINTER_ROLE"); + + vm.prank(deployer); + vm.expectRevert( + abi.encodePacked( + "Permissions: account ", + TWStrings.toHexString(uint160(target), 20), + " is missing role ", + TWStrings.toHexString(uint256(role), 32) + ) + ); + + multiwrap.revokeRole(role, target); + } + /** * Unit tests for relevant functions: * - `wrap` @@ -263,7 +309,7 @@ contract MultiwrapTest is BaseTest { * note: Testing revert condition; token owner calls `wrap` to wrap owned tokens. */ function test_revert_wrap_reentrancy() public { - MultiwrapReentrant reentrant = new MultiwrapReentrant(address(multiwrap)); + MultiwrapReentrant reentrant = new MultiwrapReentrant(payable(address(multiwrap))); ITokenBundle.Token[] memory reentrantContentToWrap = new ITokenBundle.Token[](1); reentrant.mint(address(tokenOwner), 10 ether); @@ -466,6 +512,33 @@ contract MultiwrapTest is BaseTest { multiwrap.wrap(emptyContent, uriForWrappedToken, recipient); } + function test_revert_wrap_nativeTokens_insufficientValueProvided_multipleInstances() public { + address recipient = address(0x123); + + ITokenBundle.Token[] memory nativeTokenContentToWrap = new ITokenBundle.Token[](2); + + vm.deal(address(tokenOwner), 100 ether); + vm.deal(address(multiwrap), 10 ether); + nativeTokenContentToWrap[0] = ITokenBundle.Token({ + assetContract: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, + tokenType: ITokenBundle.TokenType.ERC20, + tokenId: 0, + totalAmount: 10 ether + }); + nativeTokenContentToWrap[1] = ITokenBundle.Token({ + assetContract: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, + tokenType: ITokenBundle.TokenType.ERC20, + tokenId: 0, + totalAmount: 10 ether + }); + + vm.prank(address(tokenOwner)); + vm.expectRevert("msg.value != amount"); + multiwrap.wrap{ value: 10 ether }(nativeTokenContentToWrap, uriForWrappedToken, recipient); + + assertEq(address(multiwrap).balance, 10 ether); + } + /*/////////////////////////////////////////////////////////////// Unit tests: `unwrap` //////////////////////////////////////////////////////////////*/ @@ -496,6 +569,38 @@ contract MultiwrapTest is BaseTest { assertEq(contentsOfWrappedToken.length, 0); } + /** + * note: Testing state changes; wrapped token owner calls `unwrap` to unwrap native tokens. + */ +function test_state_unwrap_nativeTokens() public { + // ===== setup: wrap tokens ===== + uint256 expectedIdForWrappedToken = multiwrap.nextTokenIdToMint(); + address recipient = address(0x123); + + ITokenBundle.Token[] memory nativeTokenContentToWrap = new ITokenBundle.Token[](1); + + vm.deal(address(tokenOwner), 100 ether); + nativeTokenContentToWrap[0] = ITokenBundle.Token({ + assetContract: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, + tokenType: ITokenBundle.TokenType.ERC20, + tokenId: 0, + totalAmount: 10 ether + }); + + vm.prank(address(tokenOwner)); + multiwrap.wrap{ value: 10 ether }(nativeTokenContentToWrap, uriForWrappedToken, recipient); + + // ===== target test content ===== + + assertEq(address(recipient).balance, 0); + + vm.prank(recipient); + // it fails here and it shouldn't + multiwrap.unwrap(expectedIdForWrappedToken, recipient); + + assertEq(address(recipient).balance, 10 ether); +} + /** * note: Testing state changes; wrapped token owner calls `unwrap` to unwrap underlying tokens. */ @@ -592,7 +697,7 @@ contract MultiwrapTest is BaseTest { // ===== target test content ===== vm.prank(recipient); - vm.expectRevert("Multiwrap: wrapped NFT DNE."); + vm.expectRevert("wrapped NFT DNE."); multiwrap.unwrap(expectedIdForWrappedToken + 1, recipient); } @@ -607,7 +712,7 @@ contract MultiwrapTest is BaseTest { // ===== target test content ===== vm.prank(address(0x12)); - vm.expectRevert("Multiwrap: caller not approved for unwrapping."); + vm.expectRevert("caller not approved for unwrapping."); multiwrap.unwrap(expectedIdForWrappedToken, recipient); } @@ -625,7 +730,7 @@ contract MultiwrapTest is BaseTest { multiwrap.transferFrom(recipient, address(0x12), 0); vm.prank(recipient); - vm.expectRevert("Multiwrap: caller not approved for unwrapping."); + vm.expectRevert("caller not approved for unwrapping."); multiwrap.unwrap(expectedIdForWrappedToken, recipient); } From fe7bc85fa2fbbd7e71b818a78cfc5837f60ae1f0 Mon Sep 17 00:00:00 2001 From: nkrishang <62195808+nkrishang@users.noreply.github.com> Date: Sun, 26 Jun 2022 11:09:13 -0400 Subject: [PATCH 27/41] 0xMacro audit Jun '22: DropERC1155 (#182) * (Q-1) Unused variable * fix claim quantity limit fix claim quantity limit * cleanup * remove thirdwebfee remove thirdwebfee Co-authored-by: Krishang Nadgauda Co-authored-by: yash Co-authored-by: Krishang Nadgauda --- contracts/drop/DropERC1155.sol | 6 ++++ contracts/drop/DropERC20.sol | 9 ++++++ contracts/drop/DropERC721.sol | 9 ++++++ contracts/interfaces/drop/IDropERC1155.sol | 3 ++ docs/DropERC1155.md | 34 ++++++++++++++++++++++ docs/IDropERC1155.md | 17 +++++++++++ src/test/drop/DropERC721.t.sol | 1 + 7 files changed, 79 insertions(+) diff --git a/contracts/drop/DropERC1155.sol b/contracts/drop/DropERC1155.sol index f5fbefabd..4038104d8 100644 --- a/contracts/drop/DropERC1155.sol +++ b/contracts/drop/DropERC1155.sol @@ -597,6 +597,12 @@ contract DropERC1155 is emit PrimarySaleRecipientUpdated(_saleRecipient); } + /// @dev Lets a contract admin set the recipient for all primary sales. + function setSaleRecipientForToken(uint256 _tokenId, address _saleRecipient) external onlyRole(DEFAULT_ADMIN_ROLE) { + saleRecipient[_tokenId] = _saleRecipient; + emit SaleRecipientForTokenUpdated(_tokenId, _saleRecipient); + } + /// @dev Lets a contract admin update the default royalty recipient and bps. function setDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) external diff --git a/contracts/drop/DropERC20.sol b/contracts/drop/DropERC20.sol index 7e6359121..ac759c2e5 100644 --- a/contracts/drop/DropERC20.sol +++ b/contracts/drop/DropERC20.sol @@ -321,7 +321,16 @@ contract DropERC20 is } CurrencyTransferLib.transferCurrency(_currency, _msgSender(), platformFeeRecipient, platformFees); +<<<<<<< HEAD CurrencyTransferLib.transferCurrency(_currency, _msgSender(), primarySaleRecipient, totalPrice - platformFees); +======= + CurrencyTransferLib.transferCurrency( + _currency, + _msgSender(), + primarySaleRecipient, + totalPrice - platformFees + ); +>>>>>>> b00169bb4f25ccd10ebe36429d714cc5f919af63 } /// @dev Transfers the tokens being claimed. diff --git a/contracts/drop/DropERC721.sol b/contracts/drop/DropERC721.sol index a79f55473..c662f9643 100644 --- a/contracts/drop/DropERC721.sol +++ b/contracts/drop/DropERC721.sol @@ -461,7 +461,16 @@ contract DropERC721 is } CurrencyTransferLib.transferCurrency(_currency, _msgSender(), platformFeeRecipient, platformFees); +<<<<<<< HEAD CurrencyTransferLib.transferCurrency(_currency, _msgSender(), primarySaleRecipient, totalPrice - platformFees); +======= + CurrencyTransferLib.transferCurrency( + _currency, + _msgSender(), + primarySaleRecipient, + totalPrice - platformFees + ); +>>>>>>> b00169bb4f25ccd10ebe36429d714cc5f919af63 } /// @dev Transfers the NFTs being claimed. diff --git a/contracts/interfaces/drop/IDropERC1155.sol b/contracts/interfaces/drop/IDropERC1155.sol index 3f30dff71..bbd443d56 100644 --- a/contracts/interfaces/drop/IDropERC1155.sol +++ b/contracts/interfaces/drop/IDropERC1155.sol @@ -46,6 +46,9 @@ interface IDropERC1155 is IERC1155Upgradeable, IDropClaimCondition { /// @dev Emitted when the max wallet claim count for a given tokenId is updated. event MaxWalletClaimCountUpdated(uint256 tokenId, uint256 count); + /// @dev Emitted when the sale recipient for a particular tokenId is updated. + event SaleRecipientForTokenUpdated(uint256 indexed tokenId, address saleRecipient); + /** * @notice Lets an account with `MINTER_ROLE` lazy mint 'n' NFTs. * The URIs for each token is the provided `_baseURIForTokens` + `{tokenId}`. diff --git a/docs/DropERC1155.md b/docs/DropERC1155.md index ff2b2d5fa..a7edece62 100644 --- a/docs/DropERC1155.md +++ b/docs/DropERC1155.md @@ -951,6 +951,23 @@ function setRoyaltyInfoForToken(uint256 _tokenId, address _recipient, uint256 _b | _recipient | address | undefined | _bps | uint256 | undefined +### setSaleRecipientForToken + +```solidity +function setSaleRecipientForToken(uint256 _tokenId, address _saleRecipient) external nonpayable +``` + + + +*Lets a contract admin set the recipient for all primary sales.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _tokenId | uint256 | undefined +| _saleRecipient | address | undefined + ### setWalletClaimCount ```solidity @@ -1337,6 +1354,23 @@ event RoyaltyForToken(uint256 indexed tokenId, address royaltyRecipient, uint256 | royaltyRecipient | address | undefined | | royaltyBps | uint256 | undefined | +### SaleRecipientForTokenUpdated + +```solidity +event SaleRecipientForTokenUpdated(uint256 indexed tokenId, address saleRecipient) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenId `indexed` | uint256 | undefined | +| saleRecipient | address | undefined | + ### TokensClaimed ```solidity diff --git a/docs/IDropERC1155.md b/docs/IDropERC1155.md index e3fbe1642..0d19f09f4 100644 --- a/docs/IDropERC1155.md +++ b/docs/IDropERC1155.md @@ -288,6 +288,23 @@ event MaxWalletClaimCountUpdated(uint256 tokenId, uint256 count) | tokenId | uint256 | undefined | | count | uint256 | undefined | +### SaleRecipientForTokenUpdated + +```solidity +event SaleRecipientForTokenUpdated(uint256 indexed tokenId, address saleRecipient) +``` + + + +*Emitted when the sale recipient for a particular tokenId is updated.* + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenId `indexed` | uint256 | undefined | +| saleRecipient | address | undefined | + ### TokensClaimed ```solidity diff --git a/src/test/drop/DropERC721.t.sol b/src/test/drop/DropERC721.t.sol index ef6b85dfc..13529eaf5 100644 --- a/src/test/drop/DropERC721.t.sol +++ b/src/test/drop/DropERC721.t.sol @@ -10,6 +10,7 @@ import "../utils/BaseTest.sol"; contract SubExploitContract is ERC721Holder, ERC1155Holder { DropERC721 internal drop; address payable internal master; + // using Strings for uint256; // using Strings for uint256; From 23e2221fdd1f16ed485cb66eba8c800268da534a Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Sun, 26 Jun 2022 15:54:08 -0400 Subject: [PATCH 28/41] custom errors cleanup mega commit --- contracts/feature/ContractMetadata.sol | 10 +- contracts/feature/DropSinglePhase.sol | 28 ++- contracts/feature/LazyMint.sol | 2 +- contracts/feature/Ownable.sol | 10 +- contracts/feature/Permissions.sol | 2 +- contracts/feature/PlatformFee.sol | 10 +- contracts/feature/PrimarySale.sol | 10 +- contracts/feature/Royalty.sol | 10 +- .../feature/interface/IContractMetadata.sol | 3 + .../feature/interface/IDropSinglePhase.sol | 17 +- contracts/feature/interface/IOwnable.sol | 3 + contracts/feature/interface/IPlatformFee.sol | 3 + contracts/feature/interface/IPrimarySale.sol | 3 + contracts/feature/interface/IRoyalty.sol | 3 + contracts/signature-drop/SignatureDrop.sol | 39 +-- docs/ContractMetadata.md | 6 +- docs/DelayedReveal.md | 7 +- docs/DropERC1155.md | 79 ++++++ docs/DropERC20.md | 41 +++ docs/DropERC721.md | 79 ++++++ docs/DropSinglePhase.md | 68 ++++- docs/IContractMetadata.md | 14 ++ docs/IDelayedReveal.md | 19 ++ docs/IDropSinglePhase.md | 134 ++++++++++ docs/ILazyMint.md | 51 ++++ docs/IMarketplace.md | 30 +++ docs/IOwnable.md | 14 ++ docs/IPack.md | 41 +++ docs/IPermissions.md | 36 +++ docs/IPermissionsEnumerable.md | 36 +++ docs/IPlatformFee.md | 30 +++ docs/IPrimarySale.md | 14 ++ docs/IRoyalty.md | 30 +++ docs/ISignatureMintERC721.md | 30 +++ docs/LazyMint.md | 51 ++++ docs/LazyMintERC721.md | 51 ++++ docs/Marketplace.md | 30 +++ docs/Multiwrap.md | 47 +++- docs/Ownable.md | 6 +- docs/Pack.md | 41 +++ docs/Permissions.md | 24 +- docs/PermissionsEnumerable.md | 24 +- docs/PlatformFee.md | 15 +- docs/PrimarySale.md | 6 +- docs/Royalty.md | 15 +- docs/SignatureDrop.md | 236 +++++++++++++++--- docs/SignatureMintERC721.md | 30 +++ docs/SignatureMintERC721Upgradeable.md | 30 +++ docs/ThirdwebContract.md | 6 +- docs/TokenERC1155.md | 79 ++++++ docs/TokenERC20.md | 41 +++ docs/TokenERC721.md | 79 ++++++ lib/forge-std | 2 +- src/test/SignatureDrop.t.sol | 83 +++--- 54 files changed, 1632 insertions(+), 176 deletions(-) diff --git a/contracts/feature/ContractMetadata.sol b/contracts/feature/ContractMetadata.sol index e5a8e7d10..ccadd8fde 100644 --- a/contracts/feature/ContractMetadata.sol +++ b/contracts/feature/ContractMetadata.sol @@ -16,8 +16,10 @@ abstract contract ContractMetadata is IContractMetadata { /// @dev Lets a contract admin set the URI for contract-level metadata. function setContractURI(string memory _uri) external override { - // require(_canSetContractURI(), "Not authorized"); - _canSetContractURI(); + if (!_canSetContractURI()) { + revert ContractMetadata__NotAuthorized(); + } + _setupContractURI(_uri); } @@ -29,6 +31,6 @@ abstract contract ContractMetadata is IContractMetadata { emit ContractURIUpdated(prevURI, _uri); } - /// @dev Checks whether contract metadata can be set in the given execution context. - function _canSetContractURI() internal virtual; + /// @dev Returns whether contract metadata can be set in the given execution context. + function _canSetContractURI() internal virtual returns (bool); } diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index 471cb83a3..995ca1fe4 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -102,8 +102,9 @@ abstract contract DropSinglePhase is IDropSinglePhase { /// @dev Lets a contract admin set claim conditions. function setClaimConditions(ClaimCondition calldata _condition, bool _resetClaimEligibility) external override { - // require(_canSetClaimConditions(), "Not authorized"); - _canSetClaimConditions(); + if (!_canSetClaimConditions()) { + revert DropSinglePhase__NotAuthorized(); + } bytes32 targetConditionId = conditionId; uint256 supplyClaimedAlready = claimCondition.supplyClaimed; @@ -114,7 +115,7 @@ abstract contract DropSinglePhase is IDropSinglePhase { } // require(supplyClaimedAlready <= _condition.maxClaimableSupply, "max supply claimed already"); - if(supplyClaimedAlready > _condition.maxClaimableSupply) { + if (supplyClaimedAlready > _condition.maxClaimableSupply) { revert DropSinglePhase__MaxSupplyClaimedAlready(supplyClaimedAlready); } @@ -148,7 +149,12 @@ abstract contract DropSinglePhase is IDropSinglePhase { // "invalid currency or price." // ); if (_currency != currentClaimPhase.currency || _pricePerToken != currentClaimPhase.pricePerToken) { - revert DropSinglePhase__InvalidCurrencyOrPrice(_currency, currentClaimPhase.currency, _pricePerToken, currentClaimPhase.pricePerToken); + revert DropSinglePhase__InvalidCurrencyOrPrice( + _currency, + currentClaimPhase.currency, + _pricePerToken, + currentClaimPhase.pricePerToken + ); } // If we're checking for an allowlist quantity restriction, ignore the general quantity restriction. @@ -169,7 +175,10 @@ abstract contract DropSinglePhase is IDropSinglePhase { // "exceed max claimable supply." // ); if (currentClaimPhase.supplyClaimed + _quantity > currentClaimPhase.maxClaimableSupply) { - revert DropSinglePhase__ExceedMaxClaimableSupply(currentClaimPhase.supplyClaimed, currentClaimPhase.maxClaimableSupply); + revert DropSinglePhase__ExceedMaxClaimableSupply( + currentClaimPhase.supplyClaimed, + currentClaimPhase.maxClaimableSupply + ); } (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); @@ -182,7 +191,12 @@ abstract contract DropSinglePhase is IDropSinglePhase { currentClaimPhase.startTimestamp >= block.timestamp || (lastClaimedAt != 0 && block.timestamp < nextValidClaimTimestamp) ) { - revert DropSinglePhase__CannotClaimYet(block.timestamp, currentClaimPhase.startTimestamp, lastClaimedAt, nextValidClaimTimestamp); + revert DropSinglePhase__CannotClaimYet( + block.timestamp, + currentClaimPhase.startTimestamp, + lastClaimedAt, + nextValidClaimTimestamp + ); } } @@ -279,5 +293,5 @@ abstract contract DropSinglePhase is IDropSinglePhase { virtual returns (uint256 startTokenId); - function _canSetClaimConditions() internal virtual; + function _canSetClaimConditions() internal virtual returns (bool); } diff --git a/contracts/feature/LazyMint.sol b/contracts/feature/LazyMint.sol index 03f12c883..0dc6e3d42 100644 --- a/contracts/feature/LazyMint.sol +++ b/contracts/feature/LazyMint.sol @@ -24,7 +24,7 @@ abstract contract LazyMint is ILazyMint { /// @dev Returns the id for the batch of tokens the given tokenId belongs to. function getBatchIdAtIndex(uint256 _index) public view returns (uint256) { // require(_index < getBaseURICount(), "invalid index."); - if(_index >= getBaseURICount()) { + if (_index >= getBaseURICount()) { revert LazyMint__InvalidIndex(_index); } return batchIds[_index]; diff --git a/contracts/feature/Ownable.sol b/contracts/feature/Ownable.sol index 42342a642..66b4acfd7 100644 --- a/contracts/feature/Ownable.sol +++ b/contracts/feature/Ownable.sol @@ -15,9 +15,9 @@ abstract contract Ownable is IOwnable { /// @dev Lets a contract admin set a new owner for the contract. The new owner must be a contract admin. function setOwner(address _newOwner) external override { - // require(_canSetOwner(), "Not authorized"); - // if (!_canSetOwner()) revert NotAuthorized__SetOwner(); - _canSetOwner(); + if (!_canSetOwner()) { + revert Ownable__NotAuthorized(); + } _setupOwner(_newOwner); } @@ -29,6 +29,6 @@ abstract contract Ownable is IOwnable { emit OwnerUpdated(_prevOwner, _newOwner); } - /// @dev Checks whether owner can be set in the given execution context. - function _canSetOwner() internal virtual; + /// @dev Returns whether owner can be set in the given execution context. + function _canSetOwner() internal virtual returns (bool); } diff --git a/contracts/feature/Permissions.sol b/contracts/feature/Permissions.sol index 95f4832d1..40854a558 100644 --- a/contracts/feature/Permissions.sol +++ b/contracts/feature/Permissions.sol @@ -34,7 +34,7 @@ contract Permissions is IPermissions { function grantRole(bytes32 role, address account) public virtual override { _checkRole(_getRoleAdmin[role], msg.sender); // require(!_hasRole[role][account], "Can only grant to non holders"); - if(_hasRole[role][account]) { + if (_hasRole[role][account]) { revert Permissions__CanOnlyGrantToNonHolders(account); } _setupRole(role, account); diff --git a/contracts/feature/PlatformFee.sol b/contracts/feature/PlatformFee.sol index 7374410f5..d4a2abfa5 100644 --- a/contracts/feature/PlatformFee.sol +++ b/contracts/feature/PlatformFee.sol @@ -23,9 +23,9 @@ abstract contract PlatformFee is IPlatformFee { /// @dev Lets a contract admin update the platform fee recipient and bps function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external override { - // require(_canSetPlatformFeeInfo(), "Not authorized"); - // if (!_canSetPlatformFeeInfo()) revert NotAuthorized__SetPlatformFeeInfo(); - _canSetPlatformFeeInfo(); + if (!_canSetPlatformFeeInfo()) { + revert PlatformFee__NotAuthorized(); + } _setupPlatformFeeInfo(_platformFeeRecipient, _platformFeeBps); } @@ -42,6 +42,6 @@ abstract contract PlatformFee is IPlatformFee { emit PlatformFeeInfoUpdated(_platformFeeRecipient, _platformFeeBps); } - /// @dev Checks whether platform fee info can be set in the given execution context. - function _canSetPlatformFeeInfo() internal virtual; + /// @dev Returns whether platform fee info can be set in the given execution context. + function _canSetPlatformFeeInfo() internal virtual returns (bool); } diff --git a/contracts/feature/PrimarySale.sol b/contracts/feature/PrimarySale.sol index d645b5189..bef0fd5f0 100644 --- a/contracts/feature/PrimarySale.sol +++ b/contracts/feature/PrimarySale.sol @@ -19,9 +19,9 @@ abstract contract PrimarySale is IPrimarySale { /// @dev Lets a contract admin set the recipient for all primary sales. function setPrimarySaleRecipient(address _saleRecipient) external override { - // require(_canSetPrimarySaleRecipient(), "Not authorized"); - // if (!_canSetPrimarySaleRecipient()) revert NotAuthorized__SetPrimarySaleRecipient(); - _canSetPrimarySaleRecipient(); + if (!_canSetPrimarySaleRecipient()) { + revert PrimarySale__NotAuthorized(); + } _setupPrimarySaleRecipient(_saleRecipient); } @@ -31,6 +31,6 @@ abstract contract PrimarySale is IPrimarySale { emit PrimarySaleRecipientUpdated(_saleRecipient); } - /// @dev Checks whether primary sale recipient can be set in the given execution context. - function _canSetPrimarySaleRecipient() internal virtual; + /// @dev Returns whether primary sale recipient can be set in the given execution context. + function _canSetPrimarySaleRecipient() internal virtual returns (bool); } diff --git a/contracts/feature/Royalty.sol b/contracts/feature/Royalty.sol index 21bf11d18..253e903a2 100644 --- a/contracts/feature/Royalty.sol +++ b/contracts/feature/Royalty.sol @@ -77,9 +77,9 @@ abstract contract Royalty is IRoyalty { address _recipient, uint256 _bps ) external override { - // require(_canSetRoyaltyInfo(), "Not authorized"); - // if (!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); - _canSetRoyaltyInfo(); + if (!_canSetRoyaltyInfo()) { + revert Royalty__NotAuthorized(); + } _setupRoyaltyInfoForToken(_tokenId, _recipient, _bps); } @@ -100,6 +100,6 @@ abstract contract Royalty is IRoyalty { emit RoyaltyForToken(_tokenId, _recipient, _bps); } - /// @dev Checks whether royalty info can be set in the given execution context. - function _canSetRoyaltyInfo() internal virtual; + /// @dev Returns whether royalty info can be set in the given execution context. + function _canSetRoyaltyInfo() internal virtual returns (bool); } diff --git a/contracts/feature/interface/IContractMetadata.sol b/contracts/feature/interface/IContractMetadata.sol index b4200ea9b..b476f698f 100644 --- a/contracts/feature/interface/IContractMetadata.sol +++ b/contracts/feature/interface/IContractMetadata.sol @@ -20,4 +20,7 @@ interface IContractMetadata { /// @dev Emitted when the contract URI is updated. event ContractURIUpdated(string prevURI, string newURI); + + /// @dev Emitted when an unauthorized caller tries to set the contract metadata URI. + error ContractMetadata__NotAuthorized(); } diff --git a/contracts/feature/interface/IDropSinglePhase.sol b/contracts/feature/interface/IDropSinglePhase.sol index c7629656d..1875ec064 100644 --- a/contracts/feature/interface/IDropSinglePhase.sol +++ b/contracts/feature/interface/IDropSinglePhase.sol @@ -9,8 +9,16 @@ interface IDropSinglePhase is IClaimCondition { uint256 maxQuantityInAllowlist; } + /// @dev Emitted when an unauthorized caller tries to set claim conditions. + error DropSinglePhase__NotAuthorized(); + /// @notice Emitted when given currency or price is invalid. - error DropSinglePhase__InvalidCurrencyOrPrice(address givenCurrency, address requiredCurrency, uint256 givenPricePerToken, uint256 requiredPricePerToken); + error DropSinglePhase__InvalidCurrencyOrPrice( + address givenCurrency, + address requiredCurrency, + uint256 givenPricePerToken, + uint256 requiredPricePerToken + ); /// @notice Emitted when claiming invalid quantity of tokens. error DropSinglePhase__InvalidQuantity(); @@ -19,7 +27,12 @@ interface IDropSinglePhase is IClaimCondition { error DropSinglePhase__ExceedMaxClaimableSupply(uint256 supplyClaimed, uint256 maxClaimableSupply); /// @notice Emitted when the current timestamp is invalid for claim. - error DropSinglePhase__CannotClaimYet(uint256 blockTimestamp, uint256 startTimestamp, uint256 lastClaimedAt, uint256 nextValidClaimTimestamp); + error DropSinglePhase__CannotClaimYet( + uint256 blockTimestamp, + uint256 startTimestamp, + uint256 lastClaimedAt, + uint256 nextValidClaimTimestamp + ); /// @notice Emitted when given allowlist proof is invalid. error DropSinglePhase__NotInWhitelist(); diff --git a/contracts/feature/interface/IOwnable.sol b/contracts/feature/interface/IOwnable.sol index f983e2649..c94c1b2ee 100644 --- a/contracts/feature/interface/IOwnable.sol +++ b/contracts/feature/interface/IOwnable.sol @@ -16,4 +16,7 @@ interface IOwnable { /// @dev Emitted when a new Owner is set. event OwnerUpdated(address indexed prevOwner, address indexed newOwner); + + /// @dev Emitted when an unauthorized caller tries to set the owner. + error Ownable__NotAuthorized(); } diff --git a/contracts/feature/interface/IPlatformFee.sol b/contracts/feature/interface/IPlatformFee.sol index fa833ed65..41edabc3e 100644 --- a/contracts/feature/interface/IPlatformFee.sol +++ b/contracts/feature/interface/IPlatformFee.sol @@ -19,4 +19,7 @@ interface IPlatformFee { /// @dev Emitted when fee on primary sales is updated. event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps); + + /// @dev Emitted when an unauthorized caller tries to set platform fee details. + error PlatformFee__NotAuthorized(); } diff --git a/contracts/feature/interface/IPrimarySale.sol b/contracts/feature/interface/IPrimarySale.sol index 6a28e9e93..3bca8cb97 100644 --- a/contracts/feature/interface/IPrimarySale.sol +++ b/contracts/feature/interface/IPrimarySale.sol @@ -16,4 +16,7 @@ interface IPrimarySale { /// @dev Emitted when a new sale recipient is set. event PrimarySaleRecipientUpdated(address indexed recipient); + + /// @dev Emitted when an unauthorized caller tries to set primary sales details. + error PrimarySale__NotAuthorized(); } diff --git a/contracts/feature/interface/IRoyalty.sol b/contracts/feature/interface/IRoyalty.sol index e518b17de..7d299957d 100644 --- a/contracts/feature/interface/IRoyalty.sol +++ b/contracts/feature/interface/IRoyalty.sol @@ -18,6 +18,9 @@ interface IRoyalty { /// @notice Emitted when the given bps exceeds max bps. error Royalty__ExceedsMaxBps(uint256 royaltyBps); + /// @dev Emitted when an unauthorized caller tries to set royalty details. + error Royalty__NotAuthorized(); + /// @dev Returns the royalty recipient and fee bps. function getDefaultRoyaltyInfo() external view returns (address, uint16); diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index e647efbb1..c442d3db2 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -74,9 +74,6 @@ contract SignatureDrop is Custom Errors //////////////////////////////////////////////////////////////*/ - /// @notice Emitted when caller is not admin. - error SignatureDrop__NotAuthorized(address caller); - /// @notice Emitted when minting the given quantity will exceed available quantity. error SignatureDrop__NotEnoughMintedTokens(uint256 currentIndex, uint256 quantity); @@ -313,45 +310,33 @@ contract SignatureDrop is } /// @dev Checks whether platform fee info can be set in the given execution context. - function _canSetPlatformFeeInfo() internal view override { - if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { - revert SignatureDrop__NotAuthorized(_msgSender()); - } + function _canSetPlatformFeeInfo() internal view override returns (bool) { + return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); } /// @dev Checks whether primary sale recipient can be set in the given execution context. - function _canSetPrimarySaleRecipient() internal view override { - if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { - revert SignatureDrop__NotAuthorized(_msgSender()); - } + function _canSetPrimarySaleRecipient() internal view override returns (bool) { + return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); } /// @dev Checks whether owner can be set in the given execution context. - function _canSetOwner() internal view override { - if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { - revert SignatureDrop__NotAuthorized(_msgSender()); - } + function _canSetOwner() internal view override returns (bool) { + return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); } /// @dev Checks whether royalty info can be set in the given execution context. - function _canSetRoyaltyInfo() internal view override { - if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { - revert SignatureDrop__NotAuthorized(_msgSender()); - } + function _canSetRoyaltyInfo() internal view override returns (bool) { + return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); } /// @dev Checks whether contract metadata can be set in the given execution context. - function _canSetContractURI() internal view override { - if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { - revert SignatureDrop__NotAuthorized(_msgSender()); - } + function _canSetContractURI() internal view override returns (bool) { + return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); } /// @dev Checks whether platform fee info can be set in the given execution context. - function _canSetClaimConditions() internal view override { - if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender())) { - revert SignatureDrop__NotAuthorized(_msgSender()); - } + function _canSetClaimConditions() internal view override returns (bool) { + return hasRole(DEFAULT_ADMIN_ROLE, _msgSender()); } /*/////////////////////////////////////////////////////////////// diff --git a/docs/ContractMetadata.md b/docs/ContractMetadata.md index 837017834..e9ab0e6e3 100644 --- a/docs/ContractMetadata.md +++ b/docs/ContractMetadata.md @@ -68,15 +68,15 @@ event ContractURIUpdated(string prevURI, string newURI) ## Errors -### NotAuthorized__SetContractURI +### ContractMetadata__NotAuthorized ```solidity -error NotAuthorized__SetContractURI() +error ContractMetadata__NotAuthorized() ``` - +*Emitted when an unauthorized caller tries to set the contract metadata URI.* diff --git a/docs/DelayedReveal.md b/docs/DelayedReveal.md index 6aec9730e..e5649e5ba 100644 --- a/docs/DelayedReveal.md +++ b/docs/DelayedReveal.md @@ -131,12 +131,17 @@ Reveals a batch of delayed reveal NFTs. ### DelayedReveal__NothingToReveal ```solidity -error DelayedReveal__NothingToReveal() +error DelayedReveal__NothingToReveal(uint256 batchId) ``` +Emitted when encrypted URI for a given batch is empty. +#### Parameters +| Name | Type | Description | +|---|---|---| +| batchId | uint256 | undefined | diff --git a/docs/DropERC1155.md b/docs/DropERC1155.md index 9ff96f4a1..db4478a90 100644 --- a/docs/DropERC1155.md +++ b/docs/DropERC1155.md @@ -1452,3 +1452,82 @@ event WalletClaimCountUpdated(uint256 tokenId, address indexed wallet, uint256 c +## Errors + +### Ownable__NotAuthorized + +```solidity +error Ownable__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set the owner.* + + +### PlatformFee__ExceedsMaxBps + +```solidity +error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps) +``` + +Emitted when given platform-fee bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| platformFeeBps | uint256 | undefined | + +### PlatformFee__NotAuthorized + +```solidity +error PlatformFee__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set platform fee details.* + + +### PrimarySale__NotAuthorized + +```solidity +error PrimarySale__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set primary sales details.* + + +### Royalty__ExceedsMaxBps + +```solidity +error Royalty__ExceedsMaxBps(uint256 royaltyBps) +``` + +Emitted when the given bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| royaltyBps | uint256 | undefined | + +### Royalty__NotAuthorized + +```solidity +error Royalty__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set royalty details.* + + + diff --git a/docs/DropERC20.md b/docs/DropERC20.md index 5962a5173..30e91ec39 100644 --- a/docs/DropERC20.md +++ b/docs/DropERC20.md @@ -1407,3 +1407,44 @@ event WalletClaimCountUpdated(address indexed wallet, uint256 count) +## Errors + +### PlatformFee__ExceedsMaxBps + +```solidity +error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps) +``` + +Emitted when given platform-fee bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| platformFeeBps | uint256 | undefined | + +### PlatformFee__NotAuthorized + +```solidity +error PlatformFee__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set platform fee details.* + + +### PrimarySale__NotAuthorized + +```solidity +error PrimarySale__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set primary sales details.* + + + diff --git a/docs/DropERC721.md b/docs/DropERC721.md index 6518abd99..951bc3e40 100644 --- a/docs/DropERC721.md +++ b/docs/DropERC721.md @@ -1572,3 +1572,82 @@ event WalletClaimCountUpdated(address indexed wallet, uint256 count) +## Errors + +### Ownable__NotAuthorized + +```solidity +error Ownable__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set the owner.* + + +### PlatformFee__ExceedsMaxBps + +```solidity +error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps) +``` + +Emitted when given platform-fee bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| platformFeeBps | uint256 | undefined | + +### PlatformFee__NotAuthorized + +```solidity +error PlatformFee__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set platform fee details.* + + +### PrimarySale__NotAuthorized + +```solidity +error PrimarySale__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set primary sales details.* + + +### Royalty__ExceedsMaxBps + +```solidity +error Royalty__ExceedsMaxBps(uint256 royaltyBps) +``` + +Emitted when the given bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| royaltyBps | uint256 | undefined | + +### Royalty__NotAuthorized + +```solidity +error Royalty__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set royalty details.* + + + diff --git a/docs/DropSinglePhase.md b/docs/DropSinglePhase.md index edb8ec6d4..8b87e7577 100644 --- a/docs/DropSinglePhase.md +++ b/docs/DropSinglePhase.md @@ -187,35 +187,57 @@ event TokensClaimed(address indexed claimer, address indexed receiver, uint256 i ### DropSinglePhase__CannotClaimYet ```solidity -error DropSinglePhase__CannotClaimYet() +error DropSinglePhase__CannotClaimYet(uint256 blockTimestamp, uint256 startTimestamp, uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) ``` +Emitted when the current timestamp is invalid for claim. +#### Parameters +| Name | Type | Description | +|---|---|---| +| blockTimestamp | uint256 | undefined | +| startTimestamp | uint256 | undefined | +| lastClaimedAt | uint256 | undefined | +| nextValidClaimTimestamp | uint256 | undefined | ### DropSinglePhase__ExceedMaxClaimableSupply ```solidity -error DropSinglePhase__ExceedMaxClaimableSupply() +error DropSinglePhase__ExceedMaxClaimableSupply(uint256 supplyClaimed, uint256 maxClaimableSupply) ``` +Emitted when claiming given quantity will exceed max claimable supply. +#### Parameters +| Name | Type | Description | +|---|---|---| +| supplyClaimed | uint256 | undefined | +| maxClaimableSupply | uint256 | undefined | ### DropSinglePhase__InvalidCurrencyOrPrice ```solidity -error DropSinglePhase__InvalidCurrencyOrPrice() +error DropSinglePhase__InvalidCurrencyOrPrice(address givenCurrency, address requiredCurrency, uint256 givenPricePerToken, uint256 requiredPricePerToken) ``` +Emitted when given currency or price is invalid. +#### Parameters +| Name | Type | Description | +|---|---|---| +| givenCurrency | address | undefined | +| requiredCurrency | address | undefined | +| givenPricePerToken | uint256 | undefined | +| requiredPricePerToken | uint256 | undefined | ### DropSinglePhase__InvalidQuantity @@ -223,7 +245,7 @@ error DropSinglePhase__InvalidCurrencyOrPrice() error DropSinglePhase__InvalidQuantity() ``` - +Emitted when claiming invalid quantity of tokens. @@ -231,12 +253,44 @@ error DropSinglePhase__InvalidQuantity() ### DropSinglePhase__InvalidQuantityProof ```solidity -error DropSinglePhase__InvalidQuantityProof() +error DropSinglePhase__InvalidQuantityProof(uint256 maxQuantityInAllowlist) ``` +Emitted when claiming more than allowed quantity in allowlist. + +#### Parameters +| Name | Type | Description | +|---|---|---| +| maxQuantityInAllowlist | uint256 | undefined | + +### DropSinglePhase__MaxSupplyClaimedAlready + +```solidity +error DropSinglePhase__MaxSupplyClaimedAlready(uint256 supplyClaimedAlready) +``` + +Emitted when max claimable supply in given condition is less than supply claimed already. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| supplyClaimedAlready | uint256 | undefined | + +### DropSinglePhase__NotAuthorized + +```solidity +error DropSinglePhase__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set claim conditions.* ### DropSinglePhase__NotInWhitelist @@ -245,7 +299,7 @@ error DropSinglePhase__InvalidQuantityProof() error DropSinglePhase__NotInWhitelist() ``` - +Emitted when given allowlist proof is invalid. @@ -256,7 +310,7 @@ error DropSinglePhase__NotInWhitelist() error DropSinglePhase__ProofClaimed() ``` - +Emitted when allowlist spot is already used. diff --git a/docs/IContractMetadata.md b/docs/IContractMetadata.md index 1165fc5a7..b5c1efdbf 100644 --- a/docs/IContractMetadata.md +++ b/docs/IContractMetadata.md @@ -66,3 +66,17 @@ event ContractURIUpdated(string prevURI, string newURI) +## Errors + +### ContractMetadata__NotAuthorized + +```solidity +error ContractMetadata__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set the contract metadata URI.* + + + diff --git a/docs/IDelayedReveal.md b/docs/IDelayedReveal.md index 8ae0b8097..43a108e6c 100644 --- a/docs/IDelayedReveal.md +++ b/docs/IDelayedReveal.md @@ -59,3 +59,22 @@ Reveals a batch of delayed reveal NFTs. +## Errors + +### DelayedReveal__NothingToReveal + +```solidity +error DelayedReveal__NothingToReveal(uint256 batchId) +``` + +Emitted when encrypted URI for a given batch is empty. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| batchId | uint256 | undefined | + + diff --git a/docs/IDropSinglePhase.md b/docs/IDropSinglePhase.md index fe4c82132..972e9ca7d 100644 --- a/docs/IDropSinglePhase.md +++ b/docs/IDropSinglePhase.md @@ -90,3 +90,137 @@ event TokensClaimed(address indexed claimer, address indexed receiver, uint256 i +## Errors + +### DropSinglePhase__CannotClaimYet + +```solidity +error DropSinglePhase__CannotClaimYet(uint256 blockTimestamp, uint256 startTimestamp, uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) +``` + +Emitted when the current timestamp is invalid for claim. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| blockTimestamp | uint256 | undefined | +| startTimestamp | uint256 | undefined | +| lastClaimedAt | uint256 | undefined | +| nextValidClaimTimestamp | uint256 | undefined | + +### DropSinglePhase__ExceedMaxClaimableSupply + +```solidity +error DropSinglePhase__ExceedMaxClaimableSupply(uint256 supplyClaimed, uint256 maxClaimableSupply) +``` + +Emitted when claiming given quantity will exceed max claimable supply. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| supplyClaimed | uint256 | undefined | +| maxClaimableSupply | uint256 | undefined | + +### DropSinglePhase__InvalidCurrencyOrPrice + +```solidity +error DropSinglePhase__InvalidCurrencyOrPrice(address givenCurrency, address requiredCurrency, uint256 givenPricePerToken, uint256 requiredPricePerToken) +``` + +Emitted when given currency or price is invalid. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| givenCurrency | address | undefined | +| requiredCurrency | address | undefined | +| givenPricePerToken | uint256 | undefined | +| requiredPricePerToken | uint256 | undefined | + +### DropSinglePhase__InvalidQuantity + +```solidity +error DropSinglePhase__InvalidQuantity() +``` + +Emitted when claiming invalid quantity of tokens. + + + + +### DropSinglePhase__InvalidQuantityProof + +```solidity +error DropSinglePhase__InvalidQuantityProof(uint256 maxQuantityInAllowlist) +``` + +Emitted when claiming more than allowed quantity in allowlist. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| maxQuantityInAllowlist | uint256 | undefined | + +### DropSinglePhase__MaxSupplyClaimedAlready + +```solidity +error DropSinglePhase__MaxSupplyClaimedAlready(uint256 supplyClaimedAlready) +``` + +Emitted when max claimable supply in given condition is less than supply claimed already. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| supplyClaimedAlready | uint256 | undefined | + +### DropSinglePhase__NotAuthorized + +```solidity +error DropSinglePhase__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set claim conditions.* + + +### DropSinglePhase__NotInWhitelist + +```solidity +error DropSinglePhase__NotInWhitelist() +``` + +Emitted when given allowlist proof is invalid. + + + + +### DropSinglePhase__ProofClaimed + +```solidity +error DropSinglePhase__ProofClaimed() +``` + +Emitted when allowlist spot is already used. + + + + + diff --git a/docs/ILazyMint.md b/docs/ILazyMint.md index 1ab6f65e1..9c598098c 100644 --- a/docs/ILazyMint.md +++ b/docs/ILazyMint.md @@ -37,3 +37,54 @@ Lazy mints a given amount of NFTs. +## Errors + +### LazyMint__InvalidIndex + +```solidity +error LazyMint__InvalidIndex(uint256 index) +``` + +Emitted when the given index is equal to or higher than total number of batches. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint256 | undefined | + +### LazyMint__NoBaseURIForToken + +```solidity +error LazyMint__NoBaseURIForToken(uint256 tokenId) +``` + +Emitted when there's no Base URI set for the given token ID. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenId | uint256 | undefined | + +### LazyMint__NoBatchIDForToken + +```solidity +error LazyMint__NoBatchIDForToken(uint256 tokenId) +``` + +Emitted when the given token ID doesn't belong to any batch. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenId | uint256 | undefined | + + diff --git a/docs/IMarketplace.md b/docs/IMarketplace.md index d5c535caf..1e3bb0f94 100644 --- a/docs/IMarketplace.md +++ b/docs/IMarketplace.md @@ -397,3 +397,33 @@ event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platf +## Errors + +### PlatformFee__ExceedsMaxBps + +```solidity +error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps) +``` + +Emitted when given platform-fee bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| platformFeeBps | uint256 | undefined | + +### PlatformFee__NotAuthorized + +```solidity +error PlatformFee__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set platform fee details.* + + + diff --git a/docs/IOwnable.md b/docs/IOwnable.md index aa21d97c2..9c50c9663 100644 --- a/docs/IOwnable.md +++ b/docs/IOwnable.md @@ -66,3 +66,17 @@ event OwnerUpdated(address indexed prevOwner, address indexed newOwner) +## Errors + +### Ownable__NotAuthorized + +```solidity +error Ownable__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set the owner.* + + + diff --git a/docs/IPack.md b/docs/IPack.md index 9c14b3c91..35f42fe95 100644 --- a/docs/IPack.md +++ b/docs/IPack.md @@ -304,3 +304,44 @@ event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, +## Errors + +### Ownable__NotAuthorized + +```solidity +error Ownable__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set the owner.* + + +### Royalty__ExceedsMaxBps + +```solidity +error Royalty__ExceedsMaxBps(uint256 royaltyBps) +``` + +Emitted when the given bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| royaltyBps | uint256 | undefined | + +### Royalty__NotAuthorized + +```solidity +error Royalty__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set royalty details.* + + + diff --git a/docs/IPermissions.md b/docs/IPermissions.md index 8490b4c54..50a5a426a 100644 --- a/docs/IPermissions.md +++ b/docs/IPermissions.md @@ -189,3 +189,39 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed +## Errors + +### Permissions__CanOnlyGrantToNonHolders + +```solidity +error Permissions__CanOnlyGrantToNonHolders(address account) +``` + +Emitted when specified account already has the role. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +### Permissions__CanOnlyRenounceForSelf + +```solidity +error Permissions__CanOnlyRenounceForSelf(address caller, address account) +``` + +Emitted when calling address is different from the specified account. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| caller | address | undefined | +| account | address | undefined | + + diff --git a/docs/IPermissionsEnumerable.md b/docs/IPermissionsEnumerable.md index 00bd39312..50bba4a37 100644 --- a/docs/IPermissionsEnumerable.md +++ b/docs/IPermissionsEnumerable.md @@ -234,3 +234,39 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed +## Errors + +### Permissions__CanOnlyGrantToNonHolders + +```solidity +error Permissions__CanOnlyGrantToNonHolders(address account) +``` + +Emitted when specified account already has the role. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +### Permissions__CanOnlyRenounceForSelf + +```solidity +error Permissions__CanOnlyRenounceForSelf(address caller, address account) +``` + +Emitted when calling address is different from the specified account. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| caller | address | undefined | +| account | address | undefined | + + diff --git a/docs/IPlatformFee.md b/docs/IPlatformFee.md index 2ccaa430f..e68b30a62 100644 --- a/docs/IPlatformFee.md +++ b/docs/IPlatformFee.md @@ -68,3 +68,33 @@ event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platf +## Errors + +### PlatformFee__ExceedsMaxBps + +```solidity +error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps) +``` + +Emitted when given platform-fee bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| platformFeeBps | uint256 | undefined | + +### PlatformFee__NotAuthorized + +```solidity +error PlatformFee__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set platform fee details.* + + + diff --git a/docs/IPrimarySale.md b/docs/IPrimarySale.md index e0ecea162..d8cabf4d0 100644 --- a/docs/IPrimarySale.md +++ b/docs/IPrimarySale.md @@ -65,3 +65,17 @@ event PrimarySaleRecipientUpdated(address indexed recipient) +## Errors + +### PrimarySale__NotAuthorized + +```solidity +error PrimarySale__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set primary sales details.* + + + diff --git a/docs/IRoyalty.md b/docs/IRoyalty.md index 81e48f97d..ac9203755 100644 --- a/docs/IRoyalty.md +++ b/docs/IRoyalty.md @@ -151,3 +151,33 @@ event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, +## Errors + +### Royalty__ExceedsMaxBps + +```solidity +error Royalty__ExceedsMaxBps(uint256 royaltyBps) +``` + +Emitted when the given bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| royaltyBps | uint256 | undefined | + +### Royalty__NotAuthorized + +```solidity +error Royalty__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set royalty details.* + + + diff --git a/docs/ISignatureMintERC721.md b/docs/ISignatureMintERC721.md index 74e612f7f..3e0e0d041 100644 --- a/docs/ISignatureMintERC721.md +++ b/docs/ISignatureMintERC721.md @@ -82,3 +82,33 @@ event TokensMintedWithSignature(address indexed signer, address indexed mintedTo +## Errors + +### SignatureMintERC721__InvalidRequest + +```solidity +error SignatureMintERC721__InvalidRequest() +``` + +Emitted when either the signature or the request uid is invalid. + + + + +### SignatureMintERC721__RequestExpired + +```solidity +error SignatureMintERC721__RequestExpired(uint256 blockTimestamp) +``` + +Emitted when block-timestamp is outside of validity start and end range. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| blockTimestamp | uint256 | undefined | + + diff --git a/docs/LazyMint.md b/docs/LazyMint.md index f68175f87..7d8f88b73 100644 --- a/docs/LazyMint.md +++ b/docs/LazyMint.md @@ -76,3 +76,54 @@ Lazy mints a given amount of NFTs. +## Errors + +### LazyMint__InvalidIndex + +```solidity +error LazyMint__InvalidIndex(uint256 index) +``` + +Emitted when the given index is equal to or higher than total number of batches. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint256 | undefined | + +### LazyMint__NoBaseURIForToken + +```solidity +error LazyMint__NoBaseURIForToken(uint256 tokenId) +``` + +Emitted when there's no Base URI set for the given token ID. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenId | uint256 | undefined | + +### LazyMint__NoBatchIDForToken + +```solidity +error LazyMint__NoBatchIDForToken(uint256 tokenId) +``` + +Emitted when the given token ID doesn't belong to any batch. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenId | uint256 | undefined | + + diff --git a/docs/LazyMintERC721.md b/docs/LazyMintERC721.md index 457946fbb..77139961b 100644 --- a/docs/LazyMintERC721.md +++ b/docs/LazyMintERC721.md @@ -137,3 +137,54 @@ event TokensLazyMinted(uint256 indexed startTokenId, uint256 endTokenId, string +## Errors + +### LazyMint__InvalidIndex + +```solidity +error LazyMint__InvalidIndex(uint256 index) +``` + +Emitted when the given index is equal to or higher than total number of batches. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint256 | undefined | + +### LazyMint__NoBaseURIForToken + +```solidity +error LazyMint__NoBaseURIForToken(uint256 tokenId) +``` + +Emitted when there's no Base URI set for the given token ID. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenId | uint256 | undefined | + +### LazyMint__NoBatchIDForToken + +```solidity +error LazyMint__NoBatchIDForToken(uint256 tokenId) +``` + +Emitted when the given token ID doesn't belong to any batch. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenId | uint256 | undefined | + + diff --git a/docs/Marketplace.md b/docs/Marketplace.md index 841b875e6..8f598675b 100644 --- a/docs/Marketplace.md +++ b/docs/Marketplace.md @@ -962,3 +962,33 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed +## Errors + +### PlatformFee__ExceedsMaxBps + +```solidity +error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps) +``` + +Emitted when given platform-fee bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| platformFeeBps | uint256 | undefined | + +### PlatformFee__NotAuthorized + +```solidity +error PlatformFee__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set platform fee details.* + + + diff --git a/docs/Multiwrap.md b/docs/Multiwrap.md index f3826b77a..47bc81bd6 100644 --- a/docs/Multiwrap.md +++ b/docs/Multiwrap.md @@ -1141,59 +1141,86 @@ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId ## Errors -### NotAuthorized__SetContractURI +### ContractMetadata__NotAuthorized ```solidity -error NotAuthorized__SetContractURI() +error ContractMetadata__NotAuthorized() ``` +*Emitted when an unauthorized caller tries to set the contract metadata URI.* - -### NotAuthorized__SetOwner +### Ownable__NotAuthorized ```solidity -error NotAuthorized__SetOwner() +error Ownable__NotAuthorized() ``` +*Emitted when an unauthorized caller tries to set the owner.* - -### NotAuthorized__SetRoyaltyInfo +### Permissions__CanOnlyGrantToNonHolders ```solidity -error NotAuthorized__SetRoyaltyInfo() +error Permissions__CanOnlyGrantToNonHolders(address account) ``` +Emitted when specified account already has the role. +#### Parameters +| Name | Type | Description | +|---|---|---| +| account | address | undefined | ### Permissions__CanOnlyRenounceForSelf ```solidity -error Permissions__CanOnlyRenounceForSelf() +error Permissions__CanOnlyRenounceForSelf(address caller, address account) ``` +Emitted when calling address is different from the specified account. +#### Parameters +| Name | Type | Description | +|---|---|---| +| caller | address | undefined | +| account | address | undefined | ### Royalty__ExceedsMaxBps ```solidity -error Royalty__ExceedsMaxBps() +error Royalty__ExceedsMaxBps(uint256 royaltyBps) ``` +Emitted when the given bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| royaltyBps | uint256 | undefined | + +### Royalty__NotAuthorized + +```solidity +error Royalty__NotAuthorized() +``` +*Emitted when an unauthorized caller tries to set royalty details.* diff --git a/docs/Ownable.md b/docs/Ownable.md index 6da36dc34..2a6559cf2 100644 --- a/docs/Ownable.md +++ b/docs/Ownable.md @@ -68,15 +68,15 @@ event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ## Errors -### NotAuthorized__SetOwner +### Ownable__NotAuthorized ```solidity -error NotAuthorized__SetOwner() +error Ownable__NotAuthorized() ``` - +*Emitted when an unauthorized caller tries to set the owner.* diff --git a/docs/Pack.md b/docs/Pack.md index bb9a51641..1f95f3627 100644 --- a/docs/Pack.md +++ b/docs/Pack.md @@ -1349,3 +1349,44 @@ event Unpaused(address account) +## Errors + +### Ownable__NotAuthorized + +```solidity +error Ownable__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set the owner.* + + +### Royalty__ExceedsMaxBps + +```solidity +error Royalty__ExceedsMaxBps(uint256 royaltyBps) +``` + +Emitted when the given bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| royaltyBps | uint256 | undefined | + +### Royalty__NotAuthorized + +```solidity +error Royalty__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set royalty details.* + + + diff --git a/docs/Permissions.md b/docs/Permissions.md index 7e323d533..09b3600cf 100644 --- a/docs/Permissions.md +++ b/docs/Permissions.md @@ -208,15 +208,37 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed ## Errors +### Permissions__CanOnlyGrantToNonHolders + +```solidity +error Permissions__CanOnlyGrantToNonHolders(address account) +``` + +Emitted when specified account already has the role. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + ### Permissions__CanOnlyRenounceForSelf ```solidity -error Permissions__CanOnlyRenounceForSelf() +error Permissions__CanOnlyRenounceForSelf(address caller, address account) ``` +Emitted when calling address is different from the specified account. +#### Parameters +| Name | Type | Description | +|---|---|---| +| caller | address | undefined | +| account | address | undefined | diff --git a/docs/PermissionsEnumerable.md b/docs/PermissionsEnumerable.md index 5c79f0c4c..c093ca26c 100644 --- a/docs/PermissionsEnumerable.md +++ b/docs/PermissionsEnumerable.md @@ -253,15 +253,37 @@ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed ## Errors +### Permissions__CanOnlyGrantToNonHolders + +```solidity +error Permissions__CanOnlyGrantToNonHolders(address account) +``` + +Emitted when specified account already has the role. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + ### Permissions__CanOnlyRenounceForSelf ```solidity -error Permissions__CanOnlyRenounceForSelf() +error Permissions__CanOnlyRenounceForSelf(address caller, address account) ``` +Emitted when calling address is different from the specified account. +#### Parameters +| Name | Type | Description | +|---|---|---| +| caller | address | undefined | +| account | address | undefined | diff --git a/docs/PlatformFee.md b/docs/PlatformFee.md index 8109c07d5..148b41b71 100644 --- a/docs/PlatformFee.md +++ b/docs/PlatformFee.md @@ -70,26 +70,31 @@ event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platf ## Errors -### NotAuthorized__SetPlatformFeeInfo +### PlatformFee__ExceedsMaxBps ```solidity -error NotAuthorized__SetPlatformFeeInfo() +error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps) ``` +Emitted when given platform-fee bps exceeds max bps. +#### Parameters +| Name | Type | Description | +|---|---|---| +| platformFeeBps | uint256 | undefined | -### PlatformFee__ExceedsMaxBps +### PlatformFee__NotAuthorized ```solidity -error PlatformFee__ExceedsMaxBps() +error PlatformFee__NotAuthorized() ``` - +*Emitted when an unauthorized caller tries to set platform fee details.* diff --git a/docs/PrimarySale.md b/docs/PrimarySale.md index 2e342a41f..60a8510a5 100644 --- a/docs/PrimarySale.md +++ b/docs/PrimarySale.md @@ -67,15 +67,15 @@ event PrimarySaleRecipientUpdated(address indexed recipient) ## Errors -### NotAuthorized__SetPrimarySaleRecipient +### PrimarySale__NotAuthorized ```solidity -error NotAuthorized__SetPrimarySaleRecipient() +error PrimarySale__NotAuthorized() ``` - +*Emitted when an unauthorized caller tries to set primary sales details.* diff --git a/docs/Royalty.md b/docs/Royalty.md index 7693af366..3504e24c5 100644 --- a/docs/Royalty.md +++ b/docs/Royalty.md @@ -153,26 +153,31 @@ event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, ## Errors -### NotAuthorized__SetRoyaltyInfo +### Royalty__ExceedsMaxBps ```solidity -error NotAuthorized__SetRoyaltyInfo() +error Royalty__ExceedsMaxBps(uint256 royaltyBps) ``` +Emitted when the given bps exceeds max bps. +#### Parameters +| Name | Type | Description | +|---|---|---| +| royaltyBps | uint256 | undefined | -### Royalty__ExceedsMaxBps +### Royalty__NotAuthorized ```solidity -error Royalty__ExceedsMaxBps() +error Royalty__NotAuthorized() ``` - +*Emitted when an unauthorized caller tries to set royalty details.* diff --git a/docs/SignatureDrop.md b/docs/SignatureDrop.md index 848762804..10c47c753 100644 --- a/docs/SignatureDrop.md +++ b/docs/SignatureDrop.md @@ -1533,49 +1533,87 @@ Cannot query the balance for the zero address. +### ContractMetadata__NotAuthorized + +```solidity +error ContractMetadata__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set the contract metadata URI.* + + ### DelayedReveal__NothingToReveal ```solidity -error DelayedReveal__NothingToReveal() +error DelayedReveal__NothingToReveal(uint256 batchId) ``` +Emitted when encrypted URI for a given batch is empty. +#### Parameters +| Name | Type | Description | +|---|---|---| +| batchId | uint256 | undefined | ### DropSinglePhase__CannotClaimYet ```solidity -error DropSinglePhase__CannotClaimYet() +error DropSinglePhase__CannotClaimYet(uint256 blockTimestamp, uint256 startTimestamp, uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) ``` +Emitted when the current timestamp is invalid for claim. +#### Parameters +| Name | Type | Description | +|---|---|---| +| blockTimestamp | uint256 | undefined | +| startTimestamp | uint256 | undefined | +| lastClaimedAt | uint256 | undefined | +| nextValidClaimTimestamp | uint256 | undefined | ### DropSinglePhase__ExceedMaxClaimableSupply ```solidity -error DropSinglePhase__ExceedMaxClaimableSupply() +error DropSinglePhase__ExceedMaxClaimableSupply(uint256 supplyClaimed, uint256 maxClaimableSupply) ``` +Emitted when claiming given quantity will exceed max claimable supply. +#### Parameters +| Name | Type | Description | +|---|---|---| +| supplyClaimed | uint256 | undefined | +| maxClaimableSupply | uint256 | undefined | ### DropSinglePhase__InvalidCurrencyOrPrice ```solidity -error DropSinglePhase__InvalidCurrencyOrPrice() +error DropSinglePhase__InvalidCurrencyOrPrice(address givenCurrency, address requiredCurrency, uint256 givenPricePerToken, uint256 requiredPricePerToken) ``` +Emitted when given currency or price is invalid. +#### Parameters +| Name | Type | Description | +|---|---|---| +| givenCurrency | address | undefined | +| requiredCurrency | address | undefined | +| givenPricePerToken | uint256 | undefined | +| requiredPricePerToken | uint256 | undefined | ### DropSinglePhase__InvalidQuantity @@ -1583,7 +1621,7 @@ error DropSinglePhase__InvalidCurrencyOrPrice() error DropSinglePhase__InvalidQuantity() ``` - +Emitted when claiming invalid quantity of tokens. @@ -1591,21 +1629,53 @@ error DropSinglePhase__InvalidQuantity() ### DropSinglePhase__InvalidQuantityProof ```solidity -error DropSinglePhase__InvalidQuantityProof() +error DropSinglePhase__InvalidQuantityProof(uint256 maxQuantityInAllowlist) ``` +Emitted when claiming more than allowed quantity in allowlist. + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| maxQuantityInAllowlist | uint256 | undefined | + +### DropSinglePhase__MaxSupplyClaimedAlready + +```solidity +error DropSinglePhase__MaxSupplyClaimedAlready(uint256 supplyClaimedAlready) +``` + +Emitted when max claimable supply in given condition is less than supply claimed already. +#### Parameters + +| Name | Type | Description | +|---|---|---| +| supplyClaimedAlready | uint256 | undefined | + +### DropSinglePhase__NotAuthorized + +```solidity +error DropSinglePhase__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set claim conditions.* + + ### DropSinglePhase__NotInWhitelist ```solidity error DropSinglePhase__NotInWhitelist() ``` - +Emitted when given allowlist proof is invalid. @@ -1616,10 +1686,58 @@ error DropSinglePhase__NotInWhitelist() error DropSinglePhase__ProofClaimed() ``` +Emitted when allowlist spot is already used. + + + + +### LazyMint__InvalidIndex + +```solidity +error LazyMint__InvalidIndex(uint256 index) +``` + +Emitted when the given index is equal to or higher than total number of batches. +#### Parameters + +| Name | Type | Description | +|---|---|---| +| index | uint256 | undefined | + +### LazyMint__NoBaseURIForToken + +```solidity +error LazyMint__NoBaseURIForToken(uint256 tokenId) +``` +Emitted when there's no Base URI set for the given token ID. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenId | uint256 | undefined | + +### LazyMint__NoBatchIDForToken + +```solidity +error LazyMint__NoBatchIDForToken(uint256 tokenId) +``` + +Emitted when the given token ID doesn't belong to any batch. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| tokenId | uint256 | undefined | ### MintToZeroAddress @@ -1643,103 +1761,124 @@ The quantity of tokens minted must be more than zero. -### NotAuthorized__SetContractURI +### Ownable__NotAuthorized ```solidity -error NotAuthorized__SetContractURI() +error Ownable__NotAuthorized() ``` +*Emitted when an unauthorized caller tries to set the owner.* - -### NotAuthorized__SetOwner +### OwnerQueryForNonexistentToken ```solidity -error NotAuthorized__SetOwner() +error OwnerQueryForNonexistentToken() ``` +The token does not exist. - -### NotAuthorized__SetPlatformFeeInfo +### Permissions__CanOnlyGrantToNonHolders ```solidity -error NotAuthorized__SetPlatformFeeInfo() +error Permissions__CanOnlyGrantToNonHolders(address account) ``` +Emitted when specified account already has the role. +#### Parameters +| Name | Type | Description | +|---|---|---| +| account | address | undefined | -### NotAuthorized__SetPrimarySaleRecipient +### Permissions__CanOnlyRenounceForSelf ```solidity -error NotAuthorized__SetPrimarySaleRecipient() +error Permissions__CanOnlyRenounceForSelf(address caller, address account) ``` +Emitted when calling address is different from the specified account. +#### Parameters +| Name | Type | Description | +|---|---|---| +| caller | address | undefined | +| account | address | undefined | -### NotAuthorized__SetRoyaltyInfo +### PlatformFee__ExceedsMaxBps ```solidity -error NotAuthorized__SetRoyaltyInfo() +error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps) ``` +Emitted when given platform-fee bps exceeds max bps. +#### Parameters +| Name | Type | Description | +|---|---|---| +| platformFeeBps | uint256 | undefined | -### OwnerQueryForNonexistentToken +### PlatformFee__NotAuthorized ```solidity -error OwnerQueryForNonexistentToken() +error PlatformFee__NotAuthorized() ``` -The token does not exist. +*Emitted when an unauthorized caller tries to set platform fee details.* -### Permissions__CanOnlyRenounceForSelf +### PrimarySale__NotAuthorized ```solidity -error Permissions__CanOnlyRenounceForSelf() +error PrimarySale__NotAuthorized() ``` +*Emitted when an unauthorized caller tries to set primary sales details.* - -### PlatformFee__ExceedsMaxBps +### Royalty__ExceedsMaxBps ```solidity -error PlatformFee__ExceedsMaxBps() +error Royalty__ExceedsMaxBps(uint256 royaltyBps) ``` +Emitted when the given bps exceeds max bps. +#### Parameters +| Name | Type | Description | +|---|---|---| +| royaltyBps | uint256 | undefined | -### Royalty__ExceedsMaxBps +### Royalty__NotAuthorized ```solidity -error Royalty__ExceedsMaxBps() +error Royalty__NotAuthorized() ``` - +*Emitted when an unauthorized caller tries to set royalty details.* ### SignatureDrop__MintingZeroTokens @@ -1748,7 +1887,7 @@ error Royalty__ExceedsMaxBps() error SignatureDrop__MintingZeroTokens() ``` - +Emitted when given quantity to mint is zero. @@ -1756,24 +1895,36 @@ error SignatureDrop__MintingZeroTokens() ### SignatureDrop__MustSendTotalPrice ```solidity -error SignatureDrop__MustSendTotalPrice() +error SignatureDrop__MustSendTotalPrice(uint256 sentValue, uint256 totalPrice) ``` +Emitted when sent value doesn't match the total price of tokens. +#### Parameters +| Name | Type | Description | +|---|---|---| +| sentValue | uint256 | undefined | +| totalPrice | uint256 | undefined | ### SignatureDrop__NotEnoughMintedTokens ```solidity -error SignatureDrop__NotEnoughMintedTokens() +error SignatureDrop__NotEnoughMintedTokens(uint256 currentIndex, uint256 quantity) ``` +Emitted when minting the given quantity will exceed available quantity. +#### Parameters +| Name | Type | Description | +|---|---|---| +| currentIndex | uint256 | undefined | +| quantity | uint256 | undefined | ### SignatureDrop__NotTransferRole @@ -1781,7 +1932,7 @@ error SignatureDrop__NotEnoughMintedTokens() error SignatureDrop__NotTransferRole() ``` - +Emitted when given address doesn't have transfer role. @@ -1792,32 +1943,37 @@ error SignatureDrop__NotTransferRole() error SignatureDrop__ZeroAmount() ``` +Emitted when given amount for lazy-minting is zero. - -### SignatureMintERC721Upgradeable__InvalidRequest +### SignatureMintERC721__InvalidRequest ```solidity -error SignatureMintERC721Upgradeable__InvalidRequest() +error SignatureMintERC721__InvalidRequest() ``` +Emitted when either the signature or the request uid is invalid. - -### SignatureMintERC721Upgradeable__RequestExpired +### SignatureMintERC721__RequestExpired ```solidity -error SignatureMintERC721Upgradeable__RequestExpired() +error SignatureMintERC721__RequestExpired(uint256 blockTimestamp) ``` +Emitted when block-timestamp is outside of validity start and end range. +#### Parameters +| Name | Type | Description | +|---|---|---| +| blockTimestamp | uint256 | undefined | ### TransferCallerNotOwnerNorApproved diff --git a/docs/SignatureMintERC721.md b/docs/SignatureMintERC721.md index cdaf51432..690d33e19 100644 --- a/docs/SignatureMintERC721.md +++ b/docs/SignatureMintERC721.md @@ -82,3 +82,33 @@ event TokensMintedWithSignature(address indexed signer, address indexed mintedTo +## Errors + +### SignatureMintERC721__InvalidRequest + +```solidity +error SignatureMintERC721__InvalidRequest() +``` + +Emitted when either the signature or the request uid is invalid. + + + + +### SignatureMintERC721__RequestExpired + +```solidity +error SignatureMintERC721__RequestExpired(uint256 blockTimestamp) +``` + +Emitted when block-timestamp is outside of validity start and end range. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| blockTimestamp | uint256 | undefined | + + diff --git a/docs/SignatureMintERC721Upgradeable.md b/docs/SignatureMintERC721Upgradeable.md index 8c7dc170d..0fcced875 100644 --- a/docs/SignatureMintERC721Upgradeable.md +++ b/docs/SignatureMintERC721Upgradeable.md @@ -82,3 +82,33 @@ event TokensMintedWithSignature(address indexed signer, address indexed mintedTo +## Errors + +### SignatureMintERC721__InvalidRequest + +```solidity +error SignatureMintERC721__InvalidRequest() +``` + +Emitted when either the signature or the request uid is invalid. + + + + +### SignatureMintERC721__RequestExpired + +```solidity +error SignatureMintERC721__RequestExpired(uint256 blockTimestamp) +``` + +Emitted when block-timestamp is outside of validity start and end range. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| blockTimestamp | uint256 | undefined | + + diff --git a/docs/ThirdwebContract.md b/docs/ThirdwebContract.md index 89977cb18..386f220f8 100644 --- a/docs/ThirdwebContract.md +++ b/docs/ThirdwebContract.md @@ -84,15 +84,15 @@ event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ## Errors -### NotAuthorized__SetOwner +### Ownable__NotAuthorized ```solidity -error NotAuthorized__SetOwner() +error Ownable__NotAuthorized() ``` - +*Emitted when an unauthorized caller tries to set the owner.* diff --git a/docs/TokenERC1155.md b/docs/TokenERC1155.md index 483edbd5f..e837d9fdb 100644 --- a/docs/TokenERC1155.md +++ b/docs/TokenERC1155.md @@ -1175,3 +1175,82 @@ event URI(string value, uint256 indexed id) +## Errors + +### Ownable__NotAuthorized + +```solidity +error Ownable__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set the owner.* + + +### PlatformFee__ExceedsMaxBps + +```solidity +error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps) +``` + +Emitted when given platform-fee bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| platformFeeBps | uint256 | undefined | + +### PlatformFee__NotAuthorized + +```solidity +error PlatformFee__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set platform fee details.* + + +### PrimarySale__NotAuthorized + +```solidity +error PrimarySale__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set primary sales details.* + + +### Royalty__ExceedsMaxBps + +```solidity +error Royalty__ExceedsMaxBps(uint256 royaltyBps) +``` + +Emitted when the given bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| royaltyBps | uint256 | undefined | + +### Royalty__NotAuthorized + +```solidity +error Royalty__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set royalty details.* + + + diff --git a/docs/TokenERC20.md b/docs/TokenERC20.md index 7de176d09..da2924247 100644 --- a/docs/TokenERC20.md +++ b/docs/TokenERC20.md @@ -1215,3 +1215,44 @@ event Unpaused(address account) +## Errors + +### PlatformFee__ExceedsMaxBps + +```solidity +error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps) +``` + +Emitted when given platform-fee bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| platformFeeBps | uint256 | undefined | + +### PlatformFee__NotAuthorized + +```solidity +error PlatformFee__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set platform fee details.* + + +### PrimarySale__NotAuthorized + +```solidity +error PrimarySale__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set primary sales details.* + + + diff --git a/docs/TokenERC721.md b/docs/TokenERC721.md index 87ff0f65a..ed06a8398 100644 --- a/docs/TokenERC721.md +++ b/docs/TokenERC721.md @@ -1195,3 +1195,82 @@ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId +## Errors + +### Ownable__NotAuthorized + +```solidity +error Ownable__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set the owner.* + + +### PlatformFee__ExceedsMaxBps + +```solidity +error PlatformFee__ExceedsMaxBps(uint256 platformFeeBps) +``` + +Emitted when given platform-fee bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| platformFeeBps | uint256 | undefined | + +### PlatformFee__NotAuthorized + +```solidity +error PlatformFee__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set platform fee details.* + + +### PrimarySale__NotAuthorized + +```solidity +error PrimarySale__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set primary sales details.* + + +### Royalty__ExceedsMaxBps + +```solidity +error Royalty__ExceedsMaxBps(uint256 royaltyBps) +``` + +Emitted when the given bps exceeds max bps. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| royaltyBps | uint256 | undefined | + +### Royalty__NotAuthorized + +```solidity +error Royalty__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set royalty details.* + + + diff --git a/lib/forge-std b/lib/forge-std index 9a538e315..0d0485bde 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 9a538e31562a6323a1fb36e838417e72047b5de7 +Subproject commit 0d0485bdea9f9455bd684acb0ba88548a104d99b diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 571886802..3eb8ac9ee 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; -import { SignatureDrop } from "contracts/signature-drop/SignatureDrop.sol"; +import { SignatureDrop, IDropSinglePhase, IDelayedReveal, ISignatureMintERC721, ERC721AUpgradeable, IPermissions, ILazyMint } from "contracts/signature-drop/SignatureDrop.sol"; // Test imports +import "erc721a-upgradeable/contracts/IERC721AUpgradeable.sol"; import "contracts/lib/TWStrings.sol"; import "./utils/BaseTest.sol"; import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; @@ -79,31 +80,31 @@ contract SignatureDropBenchmarkTest is BaseTest { erc20.approve(address(sigdrop), 1); } - function signMintRequest(SignatureDrop.MintRequest memory mintrequest, uint256 privateKey) + function signMintRequest(SignatureDrop.MintRequest memory _mintrequest, uint256 privateKey) internal returns (bytes memory) { bytes memory encodedRequest = abi.encode( typehashMintRequest, - mintrequest.to, - mintrequest.royaltyRecipient, - mintrequest.royaltyBps, - mintrequest.primarySaleRecipient, - keccak256(bytes(mintrequest.uri)), - mintrequest.quantity, - mintrequest.pricePerToken, - mintrequest.currency, - mintrequest.validityStartTimestamp, - mintrequest.validityEndTimestamp, - mintrequest.uid + _mintrequest.to, + _mintrequest.royaltyRecipient, + _mintrequest.royaltyBps, + _mintrequest.primarySaleRecipient, + keccak256(bytes(_mintrequest.uri)), + _mintrequest.quantity, + _mintrequest.pricePerToken, + _mintrequest.currency, + _mintrequest.validityStartTimestamp, + _mintrequest.validityEndTimestamp, + _mintrequest.uid ); bytes32 structHash = keccak256(encodedRequest); bytes32 typedDataHash = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); (uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, typedDataHash); - bytes memory signature = abi.encodePacked(r, s, v); + bytes memory sig = abi.encodePacked(r, s, v); - return signature; + return sig; } function test_benchmark_mintWithSignature() public { @@ -211,7 +212,7 @@ contract SignatureDropTest is BaseTest { sigdrop.grantRole(role, receiver); - vm.expectRevert("Can only grant to non holders"); + vm.expectRevert(abi.encodeWithSelector(IPermissions.Permissions__CanOnlyGrantToNonHolders.selector, receiver)); sigdrop.grantRole(role, receiver); vm.stopPrank(); @@ -258,7 +259,15 @@ contract SignatureDropTest is BaseTest { sigdrop.setClaimConditions(conditions[0], false); vm.prank(getActor(5), getActor(5)); - vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__CannotClaimYet()"))); + vm.expectRevert( + abi.encodeWithSelector( + IDropSinglePhase.DropSinglePhase__CannotClaimYet.selector, + block.timestamp, + conditions[0].startTimestamp, + 0, + type(uint256).max + ) + ); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } @@ -338,7 +347,7 @@ contract SignatureDropTest is BaseTest { sigdrop.lazyMint(100, "ipfs://", ""); - vm.expectRevert("No batch id for token."); + vm.expectRevert(abi.encodeWithSelector(ILazyMint.LazyMint__NoBatchIDForToken.selector, 100)); sigdrop.tokenURI(100); vm.stopPrank(); @@ -516,7 +525,7 @@ contract SignatureDropTest is BaseTest { console.log(sigdrop.getBaseURICount()); sigdrop.lazyMint(100, "", encryptedURI); - vm.expectRevert("invalid index."); + vm.expectRevert(abi.encodeWithSelector(ILazyMint.LazyMint__InvalidIndex.selector, 2)); sigdrop.reveal(2, "key"); vm.stopPrank(); @@ -532,7 +541,7 @@ contract SignatureDropTest is BaseTest { sigdrop.lazyMint(100, "", encryptedURI); sigdrop.reveal(0, "key"); - vm.expectRevert(bytes4(abi.encodeWithSignature("DelayedReveal__NothingToReveal()"))); + vm.expectRevert(abi.encodeWithSelector(IDelayedReveal.DelayedReveal__NothingToReveal.selector, 100)); sigdrop.reveal(0, "key"); vm.stopPrank(); @@ -682,7 +691,7 @@ contract SignatureDropTest is BaseTest { sigdrop.mintWithSignature(mintrequest, signature); signature = signMintRequest(mintrequest, 4321); - vm.expectRevert(bytes4(abi.encodeWithSignature("SignatureMintERC721Upgradeable__InvalidRequest()"))); + vm.expectRevert(abi.encodeWithSelector(ISignatureMintERC721.SignatureMintERC721__InvalidRequest.selector)); sigdrop.mintWithSignature(mintrequest, signature); } @@ -709,7 +718,9 @@ contract SignatureDropTest is BaseTest { bytes memory signature = signMintRequest(mintrequest, privateKey); vm.warp(1000); - vm.expectRevert(bytes4(abi.encodeWithSignature("SignatureDrop__NotEnoughMintedTokens()"))); + vm.expectRevert( + abi.encodeWithSelector(SignatureDrop.SignatureDrop__NotEnoughMintedTokens.selector, 0, mintrequest.quantity) + ); sigdrop.mintWithSignature(mintrequest, signature); } @@ -738,7 +749,7 @@ contract SignatureDropTest is BaseTest { bytes memory signature = signMintRequest(mintrequest, privateKey); vm.startPrank(address(deployerSigner)); vm.warp(mintrequest.validityStartTimestamp); - vm.expectRevert(bytes4(abi.encodeWithSignature("SignatureDrop__MustSendTotalPrice()"))); + vm.expectRevert(abi.encodeWithSelector(SignatureDrop.SignatureDrop__MustSendTotalPrice.selector, 2, 1)); sigdrop.mintWithSignature{ value: 2 }(mintrequest, signature); vm.stopPrank(); } @@ -786,7 +797,7 @@ contract SignatureDropTest is BaseTest { erc20.balanceOf(deployerSigner) ); - vm.expectRevert(abi.encodeWithSignature("OwnerQueryForNonexistentToken()")); + vm.expectRevert(abi.encodeWithSelector(IERC721AUpgradeable.OwnerQueryForNonexistentToken.selector)); owner = sigdrop.ownerOf(1); } } @@ -870,7 +881,15 @@ contract SignatureDropTest is BaseTest { vm.prank(getActor(5), getActor(5)); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); - vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__CannotClaimYet()"))); + vm.expectRevert( + abi.encodeWithSelector( + IDropSinglePhase.DropSinglePhase__CannotClaimYet.selector, + block.timestamp, + 0, + 1, + type(uint256).max + ) + ); vm.prank(getActor(5), getActor(5)); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } @@ -897,7 +916,7 @@ contract SignatureDropTest is BaseTest { vm.prank(deployerSigner); sigdrop.setClaimConditions(conditions[0], false); - vm.expectRevert(bytes4(abi.encodeWithSignature("SignatureDrop__NotEnoughMintedTokens()"))); + vm.expectRevert(abi.encodeWithSelector(SignatureDrop.SignatureDrop__NotEnoughMintedTokens.selector, 0, 101)); vm.prank(getActor(6), getActor(6)); sigdrop.claim(receiver, 101, address(0), 0, alp, ""); } @@ -927,7 +946,9 @@ contract SignatureDropTest is BaseTest { vm.prank(getActor(5), getActor(5)); sigdrop.claim(receiver, 100, address(0), 0, alp, ""); - vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__ExceedMaxClaimableSupply()"))); + vm.expectRevert( + abi.encodeWithSelector(IDropSinglePhase.DropSinglePhase__ExceedMaxClaimableSupply.selector, 100, 100) + ); vm.prank(getActor(6), getActor(6)); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } @@ -958,14 +979,14 @@ contract SignatureDropTest is BaseTest { sigdrop.setClaimConditions(conditions[0], false); vm.prank(getActor(5)); - vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__InvalidQuantity()"))); + vm.expectRevert(abi.encodeWithSelector(IDropSinglePhase.DropSinglePhase__InvalidQuantity.selector)); sigdrop.claim(receiver, 101, address(0), 0, alp, ""); vm.prank(deployerSigner); sigdrop.setClaimConditions(conditions[0], true); vm.prank(getActor(5)); - vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__InvalidQuantity()"))); + vm.expectRevert(abi.encodeWithSelector(IDropSinglePhase.DropSinglePhase__InvalidQuantity.selector)); sigdrop.claim(receiver, 101, address(0), 0, alp, ""); } @@ -1010,7 +1031,7 @@ contract SignatureDropTest is BaseTest { sigdrop.claim(receiver, 1, address(0), 0, alp, ""); vm.prank(address(4)); - vm.expectRevert(bytes4(abi.encodeWithSignature("DropSinglePhase__NotInWhitelist()"))); + vm.expectRevert(abi.encodeWithSelector(IDropSinglePhase.DropSinglePhase__NotInWhitelist.selector)); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } @@ -1076,7 +1097,7 @@ contract SignatureDropTest is BaseTest { assertEq(uri, string(abi.encodePacked("ipfs://", "1"))); bytes memory newEncryptedURI = sigdrop.encryptDecrypt("ipfs://secret", "key"); - vm.expectRevert(bytes4(abi.encodeWithSignature("SignatureDrop__ZeroAmount()"))); + vm.expectRevert(abi.encodeWithSelector(SignatureDrop.SignatureDrop__ZeroAmount.selector)); sigdrop.lazyMint(0, "", newEncryptedURI); vm.stopPrank(); From 79c179046454dcf4162b34401d208c7d5f467682 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Sun, 26 Jun 2022 16:01:13 -0400 Subject: [PATCH 29/41] delete commented require statements --- contracts/feature/DelayedReveal.sol | 1 - contracts/feature/DropSinglePhase.sol | 25 ------------------- contracts/feature/LazyMint.sol | 1 - contracts/feature/Permissions.sol | 2 -- contracts/feature/PlatformFee.sol | 1 - contracts/feature/Royalty.sol | 8 +++--- contracts/feature/SignatureMintERC721.sol | 5 ---- .../SignatureMintERC721Upgradeable.sol | 5 ---- contracts/signature-drop/SignatureDrop.sol | 5 ---- 9 files changed, 3 insertions(+), 50 deletions(-) diff --git a/contracts/feature/DelayedReveal.sol b/contracts/feature/DelayedReveal.sol index 85a8915b1..2f1dc3817 100644 --- a/contracts/feature/DelayedReveal.sol +++ b/contracts/feature/DelayedReveal.sol @@ -20,7 +20,6 @@ abstract contract DelayedReveal is IDelayedReveal { /// @dev Returns the decrypted i.e. revealed URI for a batch of tokens. function getRevealURI(uint256 _batchId, bytes calldata _key) public view returns (string memory revealedURI) { bytes memory encryptedURI = encryptedBaseURI[_batchId]; - // require(encryptedURI.length != 0, "nothing to reveal."); if (encryptedURI.length == 0) { revert DelayedReveal__NothingToReveal(_batchId); } diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index 995ca1fe4..7a7796fc1 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -114,7 +114,6 @@ abstract contract DropSinglePhase is IDropSinglePhase { targetConditionId = keccak256(abi.encodePacked(_dropMsgSender(), block.number)); } - // require(supplyClaimedAlready <= _condition.maxClaimableSupply, "max supply claimed already"); if (supplyClaimedAlready > _condition.maxClaimableSupply) { revert DropSinglePhase__MaxSupplyClaimedAlready(supplyClaimedAlready); } @@ -144,10 +143,6 @@ abstract contract DropSinglePhase is IDropSinglePhase { ) public view { ClaimCondition memory currentClaimPhase = claimCondition; - // require( - // _currency == currentClaimPhase.currency && _pricePerToken == currentClaimPhase.pricePerToken, - // "invalid currency or price." - // ); if (_currency != currentClaimPhase.currency || _pricePerToken != currentClaimPhase.pricePerToken) { revert DropSinglePhase__InvalidCurrencyOrPrice( _currency, @@ -158,11 +153,6 @@ abstract contract DropSinglePhase is IDropSinglePhase { } // If we're checking for an allowlist quantity restriction, ignore the general quantity restriction. - // require( - // _quantity > 0 && - // (!verifyMaxQuantityPerTransaction || _quantity <= currentClaimPhase.quantityLimitPerTransaction), - // "invalid quantity." - // ); if ( _quantity == 0 || (verifyMaxQuantityPerTransaction && _quantity > currentClaimPhase.quantityLimitPerTransaction) @@ -170,10 +160,6 @@ abstract contract DropSinglePhase is IDropSinglePhase { revert DropSinglePhase__InvalidQuantity(); } - // require( - // currentClaimPhase.supplyClaimed + _quantity <= currentClaimPhase.maxClaimableSupply, - // "exceed max claimable supply." - // ); if (currentClaimPhase.supplyClaimed + _quantity > currentClaimPhase.maxClaimableSupply) { revert DropSinglePhase__ExceedMaxClaimableSupply( currentClaimPhase.supplyClaimed, @@ -182,11 +168,6 @@ abstract contract DropSinglePhase is IDropSinglePhase { } (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); - // require( - // claimCondition.startTimestamp < block.timestamp && - // (lastClaimedAt == 0 || block.timestamp >= nextValidClaimTimestamp), - // "cannot claim yet." - // ); if ( currentClaimPhase.startTimestamp >= block.timestamp || (lastClaimedAt != 0 && block.timestamp < nextValidClaimTimestamp) @@ -214,20 +195,14 @@ abstract contract DropSinglePhase is IDropSinglePhase { currentClaimPhase.merkleRoot, keccak256(abi.encodePacked(_claimer, _allowlistProof.maxQuantityInAllowlist)) ); - // require(validMerkleProof, "not in whitelist."); if (!validMerkleProof) { revert DropSinglePhase__NotInWhitelist(); } - // require(!usedAllowlistSpot[conditionId].get(merkleProofIndex), "proof claimed."); if (usedAllowlistSpot[conditionId].get(merkleProofIndex)) { revert DropSinglePhase__ProofClaimed(); } - // require( - // _allowlistProof.maxQuantityInAllowlist == 0 || _quantity <= _allowlistProof.maxQuantityInAllowlist, - // "invalid quantity proof." - // ); if (_allowlistProof.maxQuantityInAllowlist != 0 && _quantity > _allowlistProof.maxQuantityInAllowlist) { revert DropSinglePhase__InvalidQuantityProof(_allowlistProof.maxQuantityInAllowlist); } diff --git a/contracts/feature/LazyMint.sol b/contracts/feature/LazyMint.sol index 0dc6e3d42..7084bcde1 100644 --- a/contracts/feature/LazyMint.sol +++ b/contracts/feature/LazyMint.sol @@ -23,7 +23,6 @@ abstract contract LazyMint is ILazyMint { /// @dev Returns the id for the batch of tokens the given tokenId belongs to. function getBatchIdAtIndex(uint256 _index) public view returns (uint256) { - // require(_index < getBaseURICount(), "invalid index."); if (_index >= getBaseURICount()) { revert LazyMint__InvalidIndex(_index); } diff --git a/contracts/feature/Permissions.sol b/contracts/feature/Permissions.sol index 40854a558..5ac7ead4c 100644 --- a/contracts/feature/Permissions.sol +++ b/contracts/feature/Permissions.sol @@ -33,7 +33,6 @@ contract Permissions is IPermissions { function grantRole(bytes32 role, address account) public virtual override { _checkRole(_getRoleAdmin[role], msg.sender); - // require(!_hasRole[role][account], "Can only grant to non holders"); if (_hasRole[role][account]) { revert Permissions__CanOnlyGrantToNonHolders(account); } @@ -46,7 +45,6 @@ contract Permissions is IPermissions { } function renounceRole(bytes32 role, address account) public virtual override { - // require(msg.sender == account, "Can only renounce for self"); if (msg.sender != account) { revert Permissions__CanOnlyRenounceForSelf(msg.sender, account); } diff --git a/contracts/feature/PlatformFee.sol b/contracts/feature/PlatformFee.sol index d4a2abfa5..786f8812a 100644 --- a/contracts/feature/PlatformFee.sol +++ b/contracts/feature/PlatformFee.sol @@ -31,7 +31,6 @@ abstract contract PlatformFee is IPlatformFee { /// @dev Lets a contract admin update the platform fee recipient and bps function _setupPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) internal { - // require(_platformFeeBps <= 10_000, "Exceeds max bps"); if (_platformFeeBps > 10_000) { revert PlatformFee__ExceedsMaxBps(_platformFeeBps); } diff --git a/contracts/feature/Royalty.sol b/contracts/feature/Royalty.sol index 253e903a2..19c7ce9d5 100644 --- a/contracts/feature/Royalty.sol +++ b/contracts/feature/Royalty.sol @@ -51,16 +51,15 @@ abstract contract Royalty is IRoyalty { /// @dev Lets a contract admin update the default royalty recipient and bps. function setDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) external override { - // require(_canSetRoyaltyInfo(), "Not authorized"); - // if (!_canSetRoyaltyInfo()) revert NotAuthorized__SetRoyaltyInfo(); - _canSetRoyaltyInfo(); + if (!_canSetRoyaltyInfo()) { + revert Royalty__NotAuthorized(); + } _setupDefaultRoyaltyInfo(_royaltyRecipient, _royaltyBps); } /// @dev Lets a contract admin update the default royalty recipient and bps. function _setupDefaultRoyaltyInfo(address _royaltyRecipient, uint256 _royaltyBps) internal { - // require(_royaltyBps <= 10_000, "Exceeds max bps"); if (_royaltyBps > 10_000) { revert Royalty__ExceedsMaxBps(_royaltyBps); } @@ -90,7 +89,6 @@ abstract contract Royalty is IRoyalty { address _recipient, uint256 _bps ) internal { - // require(_bps <= 10_000, "Exceeds max bps"); if (_bps > 10_000) { revert Royalty__ExceedsMaxBps(_bps); } diff --git a/contracts/feature/SignatureMintERC721.sol b/contracts/feature/SignatureMintERC721.sol index d0bf37ec3..689e1a78f 100644 --- a/contracts/feature/SignatureMintERC721.sol +++ b/contracts/feature/SignatureMintERC721.sol @@ -38,15 +38,10 @@ abstract contract SignatureMintERC721 is EIP712, ISignatureMintERC721 { bool success; (success, signer) = verify(_req, _signature); - // require(success, "Invalid request"); if (!success) { revert SignatureMintERC721__InvalidRequest(); } - // require( - // _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, - // "Request expired" - // ); if (_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) { revert SignatureMintERC721__RequestExpired(block.timestamp); } diff --git a/contracts/feature/SignatureMintERC721Upgradeable.sol b/contracts/feature/SignatureMintERC721Upgradeable.sol index d779da5a0..6ed984e6e 100644 --- a/contracts/feature/SignatureMintERC721Upgradeable.sol +++ b/contracts/feature/SignatureMintERC721Upgradeable.sol @@ -42,15 +42,10 @@ abstract contract SignatureMintERC721Upgradeable is Initializable, EIP712Upgrade bool success; (success, signer) = verify(_req, _signature); - // require(success, "Invalid request"); if (!success) { revert SignatureMintERC721__InvalidRequest(); } - // require( - // _req.validityStartTimestamp <= block.timestamp && block.timestamp <= _req.validityEndTimestamp, - // "Request expired" - // ); if (_req.validityStartTimestamp > block.timestamp || block.timestamp > _req.validityEndTimestamp) { revert SignatureMintERC721__RequestExpired(block.timestamp); } diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index c442d3db2..6e46cac06 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -212,13 +212,11 @@ contract SignatureDrop is payable returns (address signer) { - // require(_req.quantity > 0, "minting zero tokens"); if (_req.quantity == 0) { revert SignatureDrop__MintingZeroTokens(); } uint256 tokenIdToMint = _currentIndex; - // require(tokenIdToMint + _req.quantity <= nextTokenIdToMint, "not enough minted tokens."); if (tokenIdToMint + _req.quantity > nextTokenIdToMint) { revert SignatureDrop__NotEnoughMintedTokens(tokenIdToMint, _req.quantity); } @@ -257,7 +255,6 @@ contract SignatureDrop is AllowlistProof calldata, bytes memory ) internal view override { - // require(_currentIndex + _quantity <= nextTokenIdToMint, "not enough minted tokens."); if (_currentIndex + _quantity > nextTokenIdToMint) { revert SignatureDrop__NotEnoughMintedTokens(_currentIndex, _quantity); } @@ -279,7 +276,6 @@ contract SignatureDrop is uint256 platformFees = (totalPrice * platformFeeBps) / MAX_BPS; if (_currency == CurrencyTransferLib.NATIVE_TOKEN) { - // require(msg.value == totalPrice, "must send total price."); if (msg.value != totalPrice) { revert SignatureDrop__MustSendTotalPrice(msg.value, totalPrice); } @@ -360,7 +356,6 @@ contract SignatureDrop is // if transfer is restricted on the contract, we still want to allow burning and minting if (!hasRole(TRANSFER_ROLE, address(0)) && from != address(0) && to != address(0)) { - // require(hasRole(TRANSFER_ROLE, from) || hasRole(TRANSFER_ROLE, to), "!TRANSFER_ROLE"); if (!hasRole(TRANSFER_ROLE, from) && !hasRole(TRANSFER_ROLE, to)) { revert SignatureDrop__NotTransferRole(); } From 04ceb024ac5bbf498acb344117d5cb473e27168e Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Sun, 26 Jun 2022 17:00:47 -0400 Subject: [PATCH 30/41] fix timestamp check --- contracts/feature/DropSinglePhase.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index 7a7796fc1..523e6abb0 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -169,7 +169,7 @@ abstract contract DropSinglePhase is IDropSinglePhase { (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); if ( - currentClaimPhase.startTimestamp >= block.timestamp || + currentClaimPhase.startTimestamp > block.timestamp || (lastClaimedAt != 0 && block.timestamp < nextValidClaimTimestamp) ) { revert DropSinglePhase__CannotClaimYet( From 97ba57147b16e6a5b5cd852bfbca0ec731aa5cbe Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Sun, 26 Jun 2022 20:36:59 -0400 Subject: [PATCH 31/41] run prettier --- contracts/drop/DropERC20.sol | 7 +-- contracts/drop/DropERC721.sol | 7 +-- contracts/feature/DropSinglePhase.sol | 2 +- contracts/feature/TokenBundle.sol | 3 +- contracts/feature/TokenStore.sol | 2 +- contracts/signature-drop/SignatureDrop.sol | 2 +- src/test/Multiwrap.t.sol | 63 +++++++++++----------- src/test/drop/DropERC721.t.sol | 1 + 8 files changed, 38 insertions(+), 49 deletions(-) diff --git a/contracts/drop/DropERC20.sol b/contracts/drop/DropERC20.sol index 722a3ae80..7e6359121 100644 --- a/contracts/drop/DropERC20.sol +++ b/contracts/drop/DropERC20.sol @@ -321,12 +321,7 @@ contract DropERC20 is } CurrencyTransferLib.transferCurrency(_currency, _msgSender(), platformFeeRecipient, platformFees); - CurrencyTransferLib.transferCurrency( - _currency, - _msgSender(), - primarySaleRecipient, - totalPrice - platformFees - ); + CurrencyTransferLib.transferCurrency(_currency, _msgSender(), primarySaleRecipient, totalPrice - platformFees); } /// @dev Transfers the tokens being claimed. diff --git a/contracts/drop/DropERC721.sol b/contracts/drop/DropERC721.sol index 288e6f287..a79f55473 100644 --- a/contracts/drop/DropERC721.sol +++ b/contracts/drop/DropERC721.sol @@ -461,12 +461,7 @@ contract DropERC721 is } CurrencyTransferLib.transferCurrency(_currency, _msgSender(), platformFeeRecipient, platformFees); - CurrencyTransferLib.transferCurrency( - _currency, - _msgSender(), - primarySaleRecipient, - totalPrice - platformFees - ); + CurrencyTransferLib.transferCurrency(_currency, _msgSender(), primarySaleRecipient, totalPrice - platformFees); } /// @dev Transfers the NFTs being claimed. diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index 21053adbd..7a7796fc1 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -269,4 +269,4 @@ abstract contract DropSinglePhase is IDropSinglePhase { returns (uint256 startTokenId); function _canSetClaimConditions() internal virtual returns (bool); -} \ No newline at end of file +} diff --git a/contracts/feature/TokenBundle.sol b/contracts/feature/TokenBundle.sol index efd5ed3e6..74ed98f9b 100644 --- a/contracts/feature/TokenBundle.sol +++ b/contracts/feature/TokenBundle.sol @@ -24,9 +24,8 @@ abstract contract TokenBundle is ITokenBundle { /// @dev Lets the calling contract create a bundle, by passing in a list of tokens and a unique id. function _createBundle(Token[] calldata _tokensToBind, uint256 _bundleId) internal { - uint256 targetCount = _tokensToBind.length; - + require(targetCount > 0, "TokenBundle: no tokens to bind."); require(bundle[_bundleId].count == 0, "TokenBundle: existent at bundleId"); diff --git a/contracts/feature/TokenStore.sol b/contracts/feature/TokenStore.sol index 931029cc6..33f8bae1b 100644 --- a/contracts/feature/TokenStore.sol +++ b/contracts/feature/TokenStore.sol @@ -93,4 +93,4 @@ contract TokenStore is TokenBundle, ERC721Holder, ERC1155Holder { _transferToken(_from, _to, _nativeToken); } } -} \ No newline at end of file +} diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index c1574c9f6..6e46cac06 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -385,4 +385,4 @@ contract SignatureDrop is { return ERC2771ContextUpgradeable._msgData(); } -} \ No newline at end of file +} diff --git a/src/test/Multiwrap.t.sol b/src/test/Multiwrap.t.sol index bf6699948..bf78cab57 100644 --- a/src/test/Multiwrap.t.sol +++ b/src/test/Multiwrap.t.sol @@ -112,7 +112,6 @@ contract MultiwrapTest is BaseTest { * note: Tests whether contract revert when a non-holder renounces a role. */ function test_revert_nonHolder_renounceRole() public { - address caller = address(0x123); bytes32 role = keccak256("MINTER_ROLE"); @@ -535,7 +534,7 @@ contract MultiwrapTest is BaseTest { vm.prank(address(tokenOwner)); vm.expectRevert("msg.value != amount"); multiwrap.wrap{ value: 10 ether }(nativeTokenContentToWrap, uriForWrappedToken, recipient); - + assertEq(address(multiwrap).balance, 10 ether); } @@ -570,36 +569,36 @@ contract MultiwrapTest is BaseTest { } /** - * note: Testing state changes; wrapped token owner calls `unwrap` to unwrap native tokens. - */ -function test_state_unwrap_nativeTokens() public { - // ===== setup: wrap tokens ===== - uint256 expectedIdForWrappedToken = multiwrap.nextTokenIdToMint(); - address recipient = address(0x123); - - ITokenBundle.Token[] memory nativeTokenContentToWrap = new ITokenBundle.Token[](1); - - vm.deal(address(tokenOwner), 100 ether); - nativeTokenContentToWrap[0] = ITokenBundle.Token({ - assetContract: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, - tokenType: ITokenBundle.TokenType.ERC20, - tokenId: 0, - totalAmount: 10 ether - }); - - vm.prank(address(tokenOwner)); - multiwrap.wrap{ value: 10 ether }(nativeTokenContentToWrap, uriForWrappedToken, recipient); - - // ===== target test content ===== - - assertEq(address(recipient).balance, 0); - - vm.prank(recipient); - // it fails here and it shouldn't - multiwrap.unwrap(expectedIdForWrappedToken, recipient); - - assertEq(address(recipient).balance, 10 ether); -} + * note: Testing state changes; wrapped token owner calls `unwrap` to unwrap native tokens. + */ + function test_state_unwrap_nativeTokens() public { + // ===== setup: wrap tokens ===== + uint256 expectedIdForWrappedToken = multiwrap.nextTokenIdToMint(); + address recipient = address(0x123); + + ITokenBundle.Token[] memory nativeTokenContentToWrap = new ITokenBundle.Token[](1); + + vm.deal(address(tokenOwner), 100 ether); + nativeTokenContentToWrap[0] = ITokenBundle.Token({ + assetContract: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, + tokenType: ITokenBundle.TokenType.ERC20, + tokenId: 0, + totalAmount: 10 ether + }); + + vm.prank(address(tokenOwner)); + multiwrap.wrap{ value: 10 ether }(nativeTokenContentToWrap, uriForWrappedToken, recipient); + + // ===== target test content ===== + + assertEq(address(recipient).balance, 0); + + vm.prank(recipient); + // it fails here and it shouldn't + multiwrap.unwrap(expectedIdForWrappedToken, recipient); + + assertEq(address(recipient).balance, 10 ether); + } /** * note: Testing state changes; wrapped token owner calls `unwrap` to unwrap underlying tokens. diff --git a/src/test/drop/DropERC721.t.sol b/src/test/drop/DropERC721.t.sol index 13529eaf5..6000fd596 100644 --- a/src/test/drop/DropERC721.t.sol +++ b/src/test/drop/DropERC721.t.sol @@ -10,6 +10,7 @@ import "../utils/BaseTest.sol"; contract SubExploitContract is ERC721Holder, ERC1155Holder { DropERC721 internal drop; address payable internal master; + // using Strings for uint256; // using Strings for uint256; From 1e747f73914a5ec0abf8f2be493f75447951066b Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Sun, 26 Jun 2022 20:57:47 -0400 Subject: [PATCH 32/41] REVERT G-3: breaks Marketplace --- contracts/lib/CurrencyTransferLib.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/contracts/lib/CurrencyTransferLib.sol b/contracts/lib/CurrencyTransferLib.sol index 549cff919..ca5de846e 100644 --- a/contracts/lib/CurrencyTransferLib.sol +++ b/contracts/lib/CurrencyTransferLib.sol @@ -19,6 +19,10 @@ library CurrencyTransferLib { address _to, uint256 _amount ) internal { + if (_amount == 0) { + return; + } + if (_currency == NATIVE_TOKEN) { safeTransferNativeToken(_to, _amount); } else { @@ -34,6 +38,10 @@ library CurrencyTransferLib { uint256 _amount, address _nativeTokenWrapper ) internal { + if (_amount == 0) { + return; + } + if (_currency == NATIVE_TOKEN) { if (_from == address(this)) { // withdraw from weth then transfer withdrawn native token to recipient @@ -58,6 +66,10 @@ library CurrencyTransferLib { address _to, uint256 _amount ) internal { + if (_from == _to) { + return; + } + if (_from == address(this)) { IERC20Upgradeable(_currency).safeTransfer(_to, _amount); } else { From 309ece85397f0c2a36a97a0a5a667df6664a5556 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Sun, 26 Jun 2022 21:03:41 -0400 Subject: [PATCH 33/41] Change revert test -> balances test post behaviour fix --- src/test/Multiwrap.t.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/Multiwrap.t.sol b/src/test/Multiwrap.t.sol index bf78cab57..f29c50d6b 100644 --- a/src/test/Multiwrap.t.sol +++ b/src/test/Multiwrap.t.sol @@ -399,7 +399,7 @@ contract MultiwrapTest is BaseTest { /** * note: Testing revert condition; token owner calls `wrap` to wrap native tokens, but with multiple instances in `tokensToWrap` array. */ - function test_revert_wrap_nativeTokens_insufficientValue_multipleInstances() public { + function test_balances_wrap_nativeTokens_multipleInstances() public { address recipient = address(0x123); ITokenBundle.Token[] memory nativeTokenContentToWrap = new ITokenBundle.Token[](2); @@ -419,8 +419,9 @@ contract MultiwrapTest is BaseTest { }); vm.prank(address(tokenOwner)); - vm.expectRevert("msg.value != amount"); multiwrap.wrap{ value: 10 ether }(nativeTokenContentToWrap, uriForWrappedToken, recipient); + + assertEq(weth.balanceOf(address(multiwrap)), 10 ether); } /** From 84b7d2fa0ee94930cb20d8cf917338b4b217fa4e Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Sun, 26 Jun 2022 21:13:08 -0400 Subject: [PATCH 34/41] Fix faulty >= to > --- contracts/feature/DropSinglePhase.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/feature/DropSinglePhase.sol b/contracts/feature/DropSinglePhase.sol index 7a7796fc1..523e6abb0 100644 --- a/contracts/feature/DropSinglePhase.sol +++ b/contracts/feature/DropSinglePhase.sol @@ -169,7 +169,7 @@ abstract contract DropSinglePhase is IDropSinglePhase { (uint256 lastClaimedAt, uint256 nextValidClaimTimestamp) = getClaimTimestamp(_claimer); if ( - currentClaimPhase.startTimestamp >= block.timestamp || + currentClaimPhase.startTimestamp > block.timestamp || (lastClaimedAt != 0 && block.timestamp < nextValidClaimTimestamp) ) { revert DropSinglePhase__CannotClaimYet( From 9369eab4444eac07d124b27528672f83e789ad12 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Mon, 27 Jun 2022 14:36:16 -0400 Subject: [PATCH 35/41] package bump --- contracts/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/package.json b/contracts/package.json index ca152e9a5..88e77f5f2 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,7 +1,7 @@ { "name": "@thirdweb-dev/contracts", "description": "Collection of smart contracts deployable via the thirdweb SDK, dashboard and CLI", - "version": "2.3.14", + "version": "2.3.15-0", "license": "Apache-2.0", "repository": { "type": "git", From 15fc367ff0c1aeacd4c9e4a111237ecc2ecca24d Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Mon, 27 Jun 2022 14:38:27 -0400 Subject: [PATCH 36/41] package release --- contracts/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/package.json b/contracts/package.json index 88e77f5f2..7fed91168 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,7 +1,7 @@ { "name": "@thirdweb-dev/contracts", "description": "Collection of smart contracts deployable via the thirdweb SDK, dashboard and CLI", - "version": "2.3.15-0", + "version": "2.3.15-1", "license": "Apache-2.0", "repository": { "type": "git", From 2c352ecd1d7129007766caaeeb6684b621ed94a1 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Tue, 28 Jun 2022 20:04:44 -0400 Subject: [PATCH 37/41] add bot check to SigDrop --- contracts/signature-drop/SignatureDrop.sol | 1 + src/test/SignatureDrop.t.sol | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/contracts/signature-drop/SignatureDrop.sol b/contracts/signature-drop/SignatureDrop.sol index 6e46cac06..90daa7aef 100644 --- a/contracts/signature-drop/SignatureDrop.sol +++ b/contracts/signature-drop/SignatureDrop.sol @@ -255,6 +255,7 @@ contract SignatureDrop is AllowlistProof calldata, bytes memory ) internal view override { + require(isTrustedForwarder(msg.sender) || _msgSender() == tx.origin, "BOT"); if (_currentIndex + _quantity > nextTokenIdToMint) { revert SignatureDrop__NotEnoughMintedTokens(_currentIndex, _quantity); } diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index 59013c525..f5b9bb1cd 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -74,7 +74,7 @@ contract SignatureDropBenchmarkTest is BaseTest { _mintrequest.uid = bytes32(id); _signature = signMintRequest(_mintrequest, privateKey); - vm.startPrank(deployerSigner); + vm.startPrank(deployerSigner, deployerSigner); vm.warp(1000); erc20.approve(address(sigdrop), 1); @@ -983,14 +983,14 @@ contract SignatureDropTest is BaseTest { vm.prank(deployerSigner); sigdrop.setClaimConditions(conditions[0], false); - vm.prank(getActor(5)); + vm.prank(getActor(5), getActor(5)); vm.expectRevert(abi.encodeWithSelector(IDropSinglePhase.DropSinglePhase__InvalidQuantity.selector)); sigdrop.claim(receiver, 101, address(0), 0, alp, ""); vm.prank(deployerSigner); sigdrop.setClaimConditions(conditions[0], true); - vm.prank(getActor(5)); + vm.prank(getActor(5), getActor(5)); vm.expectRevert(abi.encodeWithSelector(IDropSinglePhase.DropSinglePhase__InvalidQuantity.selector)); sigdrop.claim(receiver, 101, address(0), 0, alp, ""); } @@ -1032,10 +1032,10 @@ contract SignatureDropTest is BaseTest { sigdrop.setClaimConditions(conditions[0], false); // vm.prank(getActor(5), getActor(5)); - vm.prank(receiver); + vm.prank(receiver, receiver); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); - vm.prank(address(4)); + vm.prank(address(4), address(4)); vm.expectRevert(abi.encodeWithSelector(IDropSinglePhase.DropSinglePhase__NotInWhitelist.selector)); sigdrop.claim(receiver, 1, address(0), 0, alp, ""); } From 3f2a33b51a170564558655e5390e46969e11b941 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Tue, 28 Jun 2022 20:32:30 -0400 Subject: [PATCH 38/41] fix forge build errors --- src/test/ContractPublisher.t.sol | 192 ++++++++++++++++--------------- src/test/Pack.t.sol | 1 + src/test/SignatureDrop.t.sol | 24 ++-- 3 files changed, 111 insertions(+), 106 deletions(-) diff --git a/src/test/ContractPublisher.t.sol b/src/test/ContractPublisher.t.sol index 73f43e6cc..fe033c14f 100644 --- a/src/test/ContractPublisher.t.sol +++ b/src/test/ContractPublisher.t.sol @@ -84,32 +84,33 @@ contract ContractPublisherTest is BaseTest, IContractPublisherData { assertEq(customContract.bytecodeHash, keccak256(type(MockCustomContract).creationCode)); assertEq(customContract.implementation, address(0)); } - - function test_publish_viaOperator() public { - string memory contractId = "MyContract"; - - vm.prank(publisher); - byoc.approveOperator(operator, true); - - vm.prank(operator); - byoc.publishContract( - publisher, - publishMetadataUri, - keccak256(type(MockCustomContract).creationCode), - address(0), - contractId - ); - - IContractPublisher.CustomContractInstance memory customContract = byoc.getPublishedContract( - publisher, - contractId - ); - - assertEq(customContract.contractId, contractId); - assertEq(customContract.publishMetadataUri, publishMetadataUri); - assertEq(customContract.bytecodeHash, keccak256(type(MockCustomContract).creationCode)); - assertEq(customContract.implementation, address(0)); - } + + // Deprecated + // function test_publish_viaOperator() public { + // string memory contractId = "MyContract"; + + // vm.prank(publisher); + // byoc.approveOperator(operator, true); + + // vm.prank(operator); + // byoc.publishContract( + // publisher, + // publishMetadataUri, + // keccak256(type(MockCustomContract).creationCode), + // address(0), + // contractId + // ); + + // IContractPublisher.CustomContractInstance memory customContract = byoc.getPublishedContract( + // publisher, + // contractId + // ); + + // assertEq(customContract.contractId, contractId); + // assertEq(customContract.publishMetadataUri, publishMetadataUri); + // assertEq(customContract.bytecodeHash, keccak256(type(MockCustomContract).creationCode)); + // assertEq(customContract.implementation, address(0)); + // } function test_publish_revert_unapprovedCaller() public { string memory contractId = "MyContract"; @@ -144,34 +145,35 @@ contract ContractPublisherTest is BaseTest, IContractPublisherData { ); } - function test_publish_emit_ContractPublished() public { - string memory contractId = "MyContract"; - - vm.prank(publisher); - byoc.approveOperator(operator, true); - - IContractPublisher.CustomContractInstance memory expectedCustomContract = IContractPublisher - .CustomContractInstance({ - contractId: contractId, - publishTimestamp: 100, - publishMetadataUri: publishMetadataUri, - bytecodeHash: keccak256(type(MockCustomContract).creationCode), - implementation: address(0) - }); - - vm.expectEmit(true, true, true, true); - emit ContractPublished(operator, publisher, expectedCustomContract); - - vm.warp(100); - vm.prank(operator); - byoc.publishContract( - publisher, - publishMetadataUri, - keccak256(type(MockCustomContract).creationCode), - address(0), - contractId - ); - } + // Deprecated + // function test_publish_emit_ContractPublished() public { + // string memory contractId = "MyContract"; + + // vm.prank(publisher); + // byoc.approveOperator(operator, true); + + // IContractPublisher.CustomContractInstance memory expectedCustomContract = IContractPublisher + // .CustomContractInstance({ + // contractId: contractId, + // publishTimestamp: 100, + // publishMetadataUri: publishMetadataUri, + // bytecodeHash: keccak256(type(MockCustomContract).creationCode), + // implementation: address(0) + // }); + + // vm.expectEmit(true, true, true, true); + // emit ContractPublished(operator, publisher, expectedCustomContract); + + // vm.warp(100); + // vm.prank(operator); + // byoc.publishContract( + // publisher, + // publishMetadataUri, + // keccak256(type(MockCustomContract).creationCode), + // address(0), + // contractId + // ); + // } function test_unpublish() public { string memory contractId = "MyContract"; @@ -199,34 +201,35 @@ contract ContractPublisherTest is BaseTest, IContractPublisherData { assertEq(customContract.implementation, address(0)); } - function test_unpublish_viaOperator() public { - string memory contractId = "MyContract"; + // Deprecated + // function test_unpublish_viaOperator() public { + // string memory contractId = "MyContract"; - vm.prank(publisher); - byoc.publishContract( - publisher, - publishMetadataUri, - keccak256(type(MockCustomContract).creationCode), - address(0), - contractId - ); + // vm.prank(publisher); + // byoc.publishContract( + // publisher, + // publishMetadataUri, + // keccak256(type(MockCustomContract).creationCode), + // address(0), + // contractId + // ); - vm.prank(publisher); - byoc.approveOperator(operator, true); + // vm.prank(publisher); + // byoc.approveOperator(operator, true); - vm.prank(operator); - byoc.unpublishContract(publisher, contractId); + // vm.prank(operator); + // byoc.unpublishContract(publisher, contractId); - IContractPublisher.CustomContractInstance memory customContract = byoc.getPublishedContract( - publisher, - contractId - ); + // IContractPublisher.CustomContractInstance memory customContract = byoc.getPublishedContract( + // publisher, + // contractId + // ); - assertEq(customContract.contractId, ""); - assertEq(customContract.publishMetadataUri, ""); - assertEq(customContract.bytecodeHash, bytes32(0)); - assertEq(customContract.implementation, address(0)); - } + // assertEq(customContract.contractId, ""); + // assertEq(customContract.publishMetadataUri, ""); + // assertEq(customContract.bytecodeHash, bytes32(0)); + // assertEq(customContract.implementation, address(0)); + // } function test_unpublish_revert_unapprovedCaller() public { string memory contractId = "MyContract"; @@ -267,25 +270,26 @@ contract ContractPublisherTest is BaseTest, IContractPublisherData { byoc.unpublishContract(publisher, contractId); } - function test_unpublish_emit_ContractUnpublished() public { - string memory contractId = "MyContract"; + // Deprecated + // function test_unpublish_emit_ContractUnpublished() public { + // string memory contractId = "MyContract"; - vm.prank(publisher); - byoc.publishContract( - publisher, - publishMetadataUri, - keccak256(type(MockCustomContract).creationCode), - address(0), - contractId - ); + // vm.prank(publisher); + // byoc.publishContract( + // publisher, + // publishMetadataUri, + // keccak256(type(MockCustomContract).creationCode), + // address(0), + // contractId + // ); - vm.prank(publisher); - byoc.approveOperator(operator, true); + // vm.prank(publisher); + // byoc.approveOperator(operator, true); - vm.expectEmit(true, true, true, true); - emit ContractUnpublished(operator, publisher, contractId); + // vm.expectEmit(true, true, true, true); + // emit ContractUnpublished(operator, publisher, contractId); - vm.prank(operator); - byoc.unpublishContract(publisher, contractId); - } + // vm.prank(operator); + // byoc.unpublishContract(publisher, contractId); + // } } diff --git a/src/test/Pack.t.sol b/src/test/Pack.t.sol index cc3385a4f..07f102575 100644 --- a/src/test/Pack.t.sol +++ b/src/test/Pack.t.sol @@ -738,6 +738,7 @@ contract PackTest is BaseTest { function checkBalances(ITokenBundle.Token[] memory rewardUnits, address recipient) internal + view returns ( uint256 nativeTokenAmount, uint256 erc20Amount, diff --git a/src/test/SignatureDrop.t.sol b/src/test/SignatureDrop.t.sol index f5b9bb1cd..d5d61e7f8 100644 --- a/src/test/SignatureDrop.t.sol +++ b/src/test/SignatureDrop.t.sol @@ -80,23 +80,23 @@ contract SignatureDropBenchmarkTest is BaseTest { erc20.approve(address(sigdrop), 1); } - function signMintRequest(SignatureDrop.MintRequest memory _mintrequest, uint256 privateKey) + function signMintRequest(SignatureDrop.MintRequest memory _request, uint256 privateKey) internal returns (bytes memory) { bytes memory encodedRequest = abi.encode( typehashMintRequest, - _mintrequest.to, - _mintrequest.royaltyRecipient, - _mintrequest.royaltyBps, - _mintrequest.primarySaleRecipient, - keccak256(bytes(_mintrequest.uri)), - _mintrequest.quantity, - _mintrequest.pricePerToken, - _mintrequest.currency, - _mintrequest.validityStartTimestamp, - _mintrequest.validityEndTimestamp, - _mintrequest.uid + _request.to, + _request.royaltyRecipient, + _request.royaltyBps, + _request.primarySaleRecipient, + keccak256(bytes(_request.uri)), + _request.quantity, + _request.pricePerToken, + _request.currency, + _request.validityStartTimestamp, + _request.validityEndTimestamp, + _request.uid ); bytes32 structHash = keccak256(encodedRequest); bytes32 typedDataHash = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); From ab73980e92d9835b878c4e360e2826c2cddc5150 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Tue, 28 Jun 2022 20:36:28 -0400 Subject: [PATCH 39/41] Update permissions usage in pack tests --- src/test/Pack.t.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/Pack.t.sol b/src/test/Pack.t.sol index 07f102575..e8daa9ad0 100644 --- a/src/test/Pack.t.sol +++ b/src/test/Pack.t.sol @@ -226,7 +226,9 @@ contract PackTest is BaseTest { vm.startPrank(deployer); pack.revokeRole(keccak256("ASSET_ROLE"), address(0)); for (uint256 i = 0; i < packContents.length; i += 1) { - pack.grantRole(keccak256("ASSET_ROLE"), packContents[i].assetContract); + if(!pack.hasRole(keccak256("ASSET_ROLE"), packContents[i].assetContract)) { + pack.grantRole(keccak256("ASSET_ROLE"), packContents[i].assetContract); + } } vm.stopPrank(); From f5102b502195e5ccaf9d10b2df9b651e52a25999 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Tue, 28 Jun 2022 20:37:56 -0400 Subject: [PATCH 40/41] run prettier --- contracts/package.json | 4 ---- src/test/ContractPublisher.t.sol | 2 +- src/test/Pack.t.sol | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/contracts/package.json b/contracts/package.json index 24a99e8f3..08c84a09f 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,11 +1,7 @@ { "name": "@thirdweb-dev/contracts", "description": "Collection of smart contracts deployable via the thirdweb SDK, dashboard and CLI", -<<<<<<< HEAD - "version": "2.3.15-1", -======= "version": "2.4.1", ->>>>>>> main "license": "Apache-2.0", "repository": { "type": "git", diff --git a/src/test/ContractPublisher.t.sol b/src/test/ContractPublisher.t.sol index fe033c14f..2bb7b4048 100644 --- a/src/test/ContractPublisher.t.sol +++ b/src/test/ContractPublisher.t.sol @@ -84,7 +84,7 @@ contract ContractPublisherTest is BaseTest, IContractPublisherData { assertEq(customContract.bytecodeHash, keccak256(type(MockCustomContract).creationCode)); assertEq(customContract.implementation, address(0)); } - + // Deprecated // function test_publish_viaOperator() public { // string memory contractId = "MyContract"; diff --git a/src/test/Pack.t.sol b/src/test/Pack.t.sol index e8daa9ad0..c86de8024 100644 --- a/src/test/Pack.t.sol +++ b/src/test/Pack.t.sol @@ -226,7 +226,7 @@ contract PackTest is BaseTest { vm.startPrank(deployer); pack.revokeRole(keccak256("ASSET_ROLE"), address(0)); for (uint256 i = 0; i < packContents.length; i += 1) { - if(!pack.hasRole(keccak256("ASSET_ROLE"), packContents[i].assetContract)) { + if (!pack.hasRole(keccak256("ASSET_ROLE"), packContents[i].assetContract)) { pack.grantRole(keccak256("ASSET_ROLE"), packContents[i].assetContract); } } From d5ec953c6b05a93608e8b5fb722f11080cafbc11 Mon Sep 17 00:00:00 2001 From: Krishang Nadgauda Date: Tue, 28 Jun 2022 20:40:38 -0400 Subject: [PATCH 41/41] pack docs update --- docs/IPack.md | 41 ---------------------------------- docs/Pack.md | 62 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/docs/IPack.md b/docs/IPack.md index e888a0f35..32df02d77 100644 --- a/docs/IPack.md +++ b/docs/IPack.md @@ -105,44 +105,3 @@ Emitted when a pack is opened. -## Errors - -### Ownable__NotAuthorized - -```solidity -error Ownable__NotAuthorized() -``` - - - -*Emitted when an unauthorized caller tries to set the owner.* - - -### Royalty__ExceedsMaxBps - -```solidity -error Royalty__ExceedsMaxBps(uint256 royaltyBps) -``` - -Emitted when the given bps exceeds max bps. - - - -#### Parameters - -| Name | Type | Description | -|---|---|---| -| royaltyBps | uint256 | undefined | - -### Royalty__NotAuthorized - -```solidity -error Royalty__NotAuthorized() -``` - - - -*Emitted when an unauthorized caller tries to set royalty details.* - - - diff --git a/docs/Pack.md b/docs/Pack.md index 24dc2bd01..38846b1c7 100644 --- a/docs/Pack.md +++ b/docs/Pack.md @@ -375,7 +375,7 @@ function grantRole(bytes32 role, address account) external nonpayable - +*Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role.* #### Parameters @@ -415,7 +415,7 @@ function hasRoleWithSwitch(bytes32 role, address account) external view returns - +*Returns `true` if either (1) `account` has been granted `role`, or (2) the relevant role restrictions do not apply at the time of calling this function.* #### Parameters @@ -695,7 +695,7 @@ function renounceRole(bytes32 role, address account) external nonpayable - +*Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `account`.* #### Parameters @@ -712,7 +712,7 @@ function revokeRole(bytes32 role, address account) external nonpayable - +*Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role.* #### Parameters @@ -994,7 +994,7 @@ event ContractURIUpdated(string prevURI, string newURI) ### DefaultRoyalty ```solidity -event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) +event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps) ``` @@ -1005,13 +1005,13 @@ event DefaultRoyalty(address newRoyaltyRecipient, uint256 newRoyaltyBps) | Name | Type | Description | |---|---|---| -| newRoyaltyRecipient | address | undefined | +| newRoyaltyRecipient `indexed` | address | undefined | | newRoyaltyBps | uint256 | undefined | ### OwnerUpdated ```solidity -event OwnerUpdated(address prevOwner, address newOwner) +event OwnerUpdated(address indexed prevOwner, address indexed newOwner) ``` @@ -1022,8 +1022,8 @@ event OwnerUpdated(address prevOwner, address newOwner) | Name | Type | Description | |---|---|---| -| prevOwner | address | undefined | -| newOwner | address | undefined | +| prevOwner `indexed` | address | undefined | +| newOwner `indexed` | address | undefined | ### PackCreated @@ -1228,6 +1228,17 @@ event Unpaused(address account) ## Errors +### ContractMetadata__NotAuthorized + +```solidity +error ContractMetadata__NotAuthorized() +``` + + + +*Emitted when an unauthorized caller tries to set the contract metadata URI.* + + ### Ownable__NotAuthorized ```solidity @@ -1239,6 +1250,39 @@ error Ownable__NotAuthorized() *Emitted when an unauthorized caller tries to set the owner.* +### Permissions__CanOnlyGrantToNonHolders + +```solidity +error Permissions__CanOnlyGrantToNonHolders(address account) +``` + +Emitted when specified account already has the role. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| account | address | undefined | + +### Permissions__CanOnlyRenounceForSelf + +```solidity +error Permissions__CanOnlyRenounceForSelf(address caller, address account) +``` + +Emitted when calling address is different from the specified account. + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| caller | address | undefined | +| account | address | undefined | + ### Royalty__ExceedsMaxBps ```solidity