Skip to content

Commit 168b4b1

Browse files
Burn to claim macro audit fixes (#523)
* re-write marketplacev3 in new dynamic pattern * update tests: direct listings * update tests: english auctions * update tests: offers * update function for access control * update storage position acc erc7201 * Use latest dynamic contracts * Update dynamic-contracts deps * Fix [Q-1] Misleading function name for setMaxTotalSupply * Fix [Q-2] Missing sanity check when setting BurnToClaimInfo * Fix [Q-3] OPERATOR_ROLE is not used * Fix [Q-5] Named returns are not assigned * Complete fix for [Q-1] * Fix [Q-6] Avoid code duplication by using maxTotalSupply() * Fix [Q-12] Comply with ERC7201 standard * Fix [L-2] Missing sanity checks for PrimarySale and PlatformFee recipients * Fix [Q-9] Document behavior of tokenURI * Fix [Q-7] Adhere to naming convention for internal function * Fix [Q-4] Missing natspec documentation * Addendum [Q-2]: Consider removing redundant check in verifyBurnToClaim * Addendum [Q-1]: use totalMinted instead of currentIndex in _checkTotalSupply * Addendum [L-2]: appendix B * Addendum [Q-12]: fully comply with ERC7201 * Fix test --------- Co-authored-by: Yash <kumaryashcse@gmail.com>
1 parent af5c805 commit 168b4b1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1053
-857
lines changed

contracts/extension/interface/IBurnToClaim.sol

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ interface IBurnToClaim {
1010
ERC1155
1111
}
1212

13+
/**
14+
* @notice Configuration for burning tokens to claim new tokens.
15+
*
16+
* @param originContractAddress The address of the contract that the tokens are burned from.
17+
* @param tokenType The type of token to burn.
18+
* @param tokenId The token ID of the token to burn. Only used if tokenType is ERC1155.
19+
* @param mintPriceForNewToken The price to mint a new token.
20+
* @param currency The currency to pay the mint price in.
21+
*/
1322
struct BurnToClaimInfo {
1423
address originContractAddress;
1524
TokenType tokenType;
@@ -18,13 +27,17 @@ interface IBurnToClaim {
1827
address currency;
1928
}
2029

21-
/// @dev Emitted when tokens are burned to claim new tokens
30+
/// @notice Emitted when tokens are burned to claim new tokens
2231
event TokensBurnedAndClaimed(
2332
address indexed originContract,
2433
address indexed tokenOwner,
2534
uint256 indexed burnTokenId,
2635
uint256 quantity
2736
);
2837

38+
/**
39+
* @notice Sets the configuration for burning tokens to claim new tokens.
40+
* @param burnToClaimInfo The configuration for burning tokens to claim new tokens.
41+
*/
2942
function setBurnToClaimInfo(BurnToClaimInfo calldata burnToClaimInfo) external;
3043
}

contracts/extension/upgradeable/AccountPermissions.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import "../../external-deps/openzeppelin/utils/structs/EnumerableSet.sol";
1010
library AccountPermissionsStorage {
1111
/// @custom:storage-location erc7201:extension.manager.storage
1212
bytes32 public constant ACCOUNT_PERMISSIONS_STORAGE_POSITION =
13-
keccak256(abi.encode(uint256(keccak256("account.permissions.storage")) - 1));
13+
keccak256(abi.encode(uint256(keccak256("account.permissions.storage")) - 1)) & ~bytes32(uint256(0xff));
1414

1515
struct Data {
1616
/// @dev The set of all admins of the wallet.

contracts/extension/upgradeable/BatchMintMetadata.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pragma solidity ^0.8.0;
44
library BatchMintMetadataStorage {
55
/// @custom:storage-location erc7201:extension.manager.storage
66
bytes32 public constant BATCH_MINT_METADATA_STORAGE_POSITION =
7-
keccak256(abi.encode(uint256(keccak256("batch.mint.metadata.storage")) - 1));
7+
keccak256(abi.encode(uint256(keccak256("batch.mint.metadata.storage")) - 1)) & ~bytes32(uint256(0xff));
88

99
struct Data {
1010
/// @dev Largest tokenId of each batch of tokens with the same baseURI.

contracts/extension/upgradeable/BurnToClaim.sol

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import "../interface/IBurnToClaim.sol";
1414
library BurnToClaimStorage {
1515
/// @custom:storage-location erc7201:extension.manager.storage
1616
bytes32 public constant BURN_TO_CLAIM_STORAGE_POSITION =
17-
keccak256(abi.encode(uint256(keccak256("burn.to.claim.storage")) - 1));
17+
keccak256(abi.encode(uint256(keccak256("burn.to.claim.storage")) - 1)) & ~bytes32(uint256(0xff));
1818

1919
struct Data {
2020
IBurnToClaim.BurnToClaimInfo burnToClaimInfo;
@@ -29,23 +29,27 @@ library BurnToClaimStorage {
2929
}
3030

3131
abstract contract BurnToClaim is IBurnToClaim {
32+
/// @notice Returns the confugration for burning tokens to claim new tokens.
3233
function getBurnToClaimInfo() public view returns (BurnToClaimInfo memory) {
3334
return _burnToClaimStorage().burnToClaimInfo;
3435
}
3536

37+
/// @notice Sets the configuration for burning tokens to claim new tokens.
3638
function setBurnToClaimInfo(BurnToClaimInfo calldata _burnToClaimInfo) external virtual {
3739
require(_canSetBurnToClaim(), "Not authorized.");
40+
require(_burnToClaimInfo.originContractAddress != address(0), "Origin contract not set.");
41+
require(_burnToClaimInfo.currency != address(0), "Currency not set.");
3842

3943
_burnToClaimStorage().burnToClaimInfo = _burnToClaimInfo;
4044
}
4145

46+
/// @notice Verifies an attempt to burn tokens to claim new tokens.
4247
function verifyBurnToClaim(
4348
address _tokenOwner,
4449
uint256 _tokenId,
4550
uint256 _quantity
4651
) public view virtual {
4752
BurnToClaimInfo memory _burnToClaimInfo = getBurnToClaimInfo();
48-
require(_burnToClaimInfo.originContractAddress != address(0), "Origin contract not set.");
4953

5054
if (_burnToClaimInfo.tokenType == IBurnToClaim.TokenType.ERC721) {
5155
require(_quantity == 1, "Invalid amount");
@@ -61,6 +65,7 @@ abstract contract BurnToClaim is IBurnToClaim {
6165
}
6266
}
6367

68+
/// @dev Burns tokens to claim new tokens.
6469
function _burnTokensOnOrigin(
6570
address _tokenOwner,
6671
uint256 _tokenId,
@@ -80,5 +85,6 @@ abstract contract BurnToClaim is IBurnToClaim {
8085
data = BurnToClaimStorage.data();
8186
}
8287

88+
/// @dev Returns whether the caller can set the burn to claim configuration.
8389
function _canSetBurnToClaim() internal view virtual returns (bool);
8490
}

contracts/extension/upgradeable/ContractMetadata.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import "../interface/IContractMetadata.sol";
1717
library ContractMetadataStorage {
1818
/// @custom:storage-location erc7201:extension.manager.storage
1919
bytes32 public constant CONTRACT_METADATA_STORAGE_POSITION =
20-
keccak256(abi.encode(uint256(keccak256("contract.metadata.storage")) - 1));
20+
keccak256(abi.encode(uint256(keccak256("contract.metadata.storage")) - 1)) & ~bytes32(uint256(0xff));
2121

2222
struct Data {
2323
/// @notice Returns the contract metadata URI.

contracts/extension/upgradeable/DelayedReveal.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import "../interface/IDelayedReveal.sol";
88
library DelayedRevealStorage {
99
/// @custom:storage-location erc7201:extension.manager.storage
1010
bytes32 public constant DELAYED_REVEAL_STORAGE_POSITION =
11-
keccak256(abi.encode(uint256(keccak256("delayed.reveal.storage")) - 1));
11+
keccak256(abi.encode(uint256(keccak256("delayed.reveal.storage")) - 1)) & ~bytes32(uint256(0xff));
1212

1313
struct Data {
1414
/// @dev Mapping from tokenId of a batch of tokens => to delayed reveal data.

contracts/extension/upgradeable/Drop.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import "../../lib/MerkleProof.sol";
88

99
library DropStorage {
1010
/// @custom:storage-location erc7201:extension.manager.storage
11-
bytes32 public constant DROP_STORAGE_POSITION = keccak256(abi.encode(uint256(keccak256("drop.storage")) - 1));
11+
bytes32 public constant DROP_STORAGE_POSITION =
12+
keccak256(abi.encode(uint256(keccak256("drop.storage")) - 1)) & ~bytes32(uint256(0xff));
1213

1314
struct Data {
1415
/// @dev The active conditions for claiming tokens.

contracts/extension/upgradeable/ERC2771Context.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import "../interface/IERC2771Context.sol";
1010
library ERC2771ContextStorage {
1111
/// @custom:storage-location erc7201:extension.manager.storage
1212
bytes32 public constant ERC2771_CONTEXT_STORAGE_POSITION =
13-
keccak256(abi.encode(uint256(keccak256("erc2771.context.storage")) - 1));
13+
keccak256(abi.encode(uint256(keccak256("erc2771.context.storage")) - 1)) & ~bytes32(uint256(0xff));
1414

1515
struct Data {
1616
mapping(address => bool) trustedForwarder;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.0;
3+
4+
/// @author thirdweb
5+
6+
interface IERC2771Context {
7+
function isTrustedForwarder(address forwarder) external view returns (bool);
8+
}
9+
10+
/**
11+
* @dev Context variant with ERC2771 support.
12+
*/
13+
abstract contract ERC2771ContextConsumer {
14+
function _msgSender() public view virtual returns (address sender) {
15+
if (IERC2771Context(address(this)).isTrustedForwarder(msg.sender)) {
16+
// The assembly code is more direct than the Solidity version using `abi.decode`.
17+
assembly {
18+
sender := shr(96, calldataload(sub(calldatasize(), 20)))
19+
}
20+
} else {
21+
return msg.sender;
22+
}
23+
}
24+
25+
function _msgData() public view virtual returns (bytes calldata) {
26+
if (IERC2771Context(address(this)).isTrustedForwarder(msg.sender)) {
27+
return msg.data[:msg.data.length - 20];
28+
} else {
29+
return msg.data;
30+
}
31+
}
32+
}

contracts/extension/upgradeable/ERC2771ContextUpgradeable.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import "./Initializable.sol";
1111
library ERC2771ContextStorage {
1212
/// @custom:storage-location erc7201:extension.manager.storage
1313
bytes32 public constant ERC2771_CONTEXT_STORAGE_POSITION =
14-
keccak256(abi.encode(uint256(keccak256("erc2771.context.storage")) - 1));
14+
keccak256(abi.encode(uint256(keccak256("erc2771.context.storage")) - 1)) & ~bytes32(uint256(0xff));
1515

1616
struct Data {
1717
mapping(address => bool) trustedForwarder;

0 commit comments

Comments
 (0)