Skip to content

Commit 11f6726

Browse files
authored
Fix listing validation: add failsafe for nonexistent tokens (#364)
* fix listing validation: add failsafe for nonexistent tokens * add test * Add comment * prettier
1 parent 18598a0 commit 11f6726

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

contracts/marketplace/direct-listings/DirectListingsLogic.sol

+16-3
Original file line numberDiff line numberDiff line change
@@ -470,10 +470,23 @@ contract DirectListingsLogic is IDirectListings, ReentrancyGuardLogic, ERC2771Co
470470
IERC1155(_assetContract).balanceOf(_tokenOwner, _tokenId) >= _quantity &&
471471
IERC1155(_assetContract).isApprovedForAll(_tokenOwner, market);
472472
} else if (_tokenType == TokenType.ERC721) {
473+
address owner;
474+
address operator;
475+
476+
// failsafe for reverts in case of non-existent tokens
477+
try IERC721(_assetContract).ownerOf(_tokenId) returns (address _owner) {
478+
owner = _owner;
479+
480+
// Nesting the approval check inside this try block, to run only if owner check doesn't revert.
481+
// If the previous check for owner fails, then the return value will always evaluate to false.
482+
try IERC721(_assetContract).getApproved(_tokenId) returns (address _operator) {
483+
operator = _operator;
484+
} catch {}
485+
} catch {}
486+
473487
isValid =
474-
IERC721(_assetContract).ownerOf(_tokenId) == _tokenOwner &&
475-
(IERC721(_assetContract).getApproved(_tokenId) == market ||
476-
IERC721(_assetContract).isApprovedForAll(_tokenOwner, market));
488+
owner == _tokenOwner &&
489+
(operator == market || IERC721(_assetContract).isApprovedForAll(_tokenOwner, market));
477490
}
478491
}
479492

src/test/marketplace/DirectListings.t.sol

+46
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,52 @@ contract MarketplaceDirectListingsTest is BaseTest {
155155
Miscellaneous
156156
//////////////////////////////////////////////////////////////*/
157157

158+
function test_getValidListings_burnListedTokens() public {
159+
// Sample listing parameters.
160+
address assetContract = address(erc721);
161+
uint256 tokenId = 0;
162+
uint256 quantity = 1;
163+
address currency = address(erc20);
164+
uint256 pricePerToken = 1 ether;
165+
uint128 startTimestamp = 100;
166+
uint128 endTimestamp = 200;
167+
bool reserved = true;
168+
169+
// Mint the ERC721 tokens to seller. These tokens will be listed.
170+
_setupERC721BalanceForSeller(seller, 1);
171+
172+
// Approve Marketplace to transfer token.
173+
vm.prank(seller);
174+
erc721.setApprovalForAll(marketplace, true);
175+
176+
// List tokens.
177+
IDirectListings.ListingParameters memory listingParams = IDirectListings.ListingParameters(
178+
assetContract,
179+
tokenId,
180+
quantity,
181+
currency,
182+
pricePerToken,
183+
startTimestamp,
184+
endTimestamp,
185+
reserved
186+
);
187+
188+
vm.prank(seller);
189+
uint256 listingId = DirectListingsLogic(marketplace).createListing(listingParams);
190+
191+
// Total listings incremented
192+
assertEq(DirectListingsLogic(marketplace).totalListings(), 1);
193+
194+
// burn listed token
195+
vm.prank(seller);
196+
erc721.burn(0);
197+
198+
vm.warp(150);
199+
// Fetch listing and verify state.
200+
uint256 totalListings = DirectListingsLogic(marketplace).totalListings();
201+
assertEq(DirectListingsLogic(marketplace).getAllValidListings(0, totalListings - 1).length, 0);
202+
}
203+
158204
/**
159205
* @dev Tests contract state for Lister role.
160206
*/

0 commit comments

Comments
 (0)