function mintNft() external payable onlyWhenRevealed onlyWhitelisted {
if (msg.sender == address(0)) revert InvalidAddress();
require(tokenIdCounter < MAX_SUPPLY, "Max supply reached");
require(msg.sender != owner, "Owner can't mint NFTs");
require(usdc.transferFrom(msg.sender, address(this), lockAmount), "USDC transfer failed");
tokenIdCounter++;
collateralForMinting[tokenIdCounter] = lockAmount;
_safeMint(msg.sender, tokenIdCounter);
}
function cancelListing(uint256 _listingId) external {
Listing memory listing = s_listings[_listingId];
if (!listing.isActive) revert ListingNotActive(_listingId);
require(listing.seller == msg.sender, "Only seller can cancel listing");
s_listings[_listingId].isActive = false;
activeListingsCounter--;
usdc.safeTransfer(listing.seller, collateralForMinting[listing.tokenId]);
collateralForMinting[listing.tokenId] = 0;
emit NFT_Dealers_ListingCanceled(_listingId);
}
``
function testCollateralRefundedWhileNftRemainsOutstanding() public revealed whitelisted {
uint256 tokenId1 = 1;
uint256 tokenId2 = 2;
uint32 listPrice = 1000e6;
uint256 lockAmt = nftDealers.lockAmount();
console2.log("Initial userWithCash USDC balance:", usdc.balanceOf(userWithCash));
console2.log("Initial contract USDC balance:", usdc.balanceOf(address(nftDealers)));
console2.log("Lock amount:", lockAmt);
vm.startPrank(userWithCash);
usdc.approve(address(nftDealers), lockAmt);
nftDealers.mintNft();
console2.log("After mint #1 - user balance:", usdc.balanceOf(userWithCash));
console2.log("After mint #1 - contract balance:", usdc.balanceOf(address(nftDealers)));
console2.log("After mint #1 - collateral token #1:", nftDealers.collateralForMinting(tokenId1));
console2.log("After mint #1 - owner of token #1:", nftDealers.ownerOf(tokenId1));
console2.log("After mint #1 - NFT balance of user:", nftDealers.balanceOf(userWithCash));
assertEq(nftDealers.ownerOf(tokenId1), userWithCash);
assertEq(usdc.balanceOf(userWithCash), 0);
assertEq(usdc.balanceOf(address(nftDealers)), lockAmt);
assertEq(nftDealers.collateralForMinting(tokenId1), lockAmt);
nftDealers.list(tokenId1, listPrice);
nftDealers.cancelListing(tokenId1);
console2.log("After cancel #1 - user balance:", usdc.balanceOf(userWithCash));
console2.log("After cancel #1 - contract balance:", usdc.balanceOf(address(nftDealers)));
console2.log("After cancel #1 - collateral token #1:", nftDealers.collateralForMinting(tokenId1));
console2.log("After cancel #1 - owner of token #1:", nftDealers.ownerOf(tokenId1));
console2.log("After cancel #1 - NFT balance of user:", nftDealers.balanceOf(userWithCash));
assertEq(usdc.balanceOf(userWithCash), lockAmt, "user should have recovered full collateral");
assertEq(usdc.balanceOf(address(nftDealers)), 0, "contract no longer holds collateral for token #1");
assertEq(nftDealers.collateralForMinting(tokenId1), 0, "token #1 backing was erased");
assertEq(nftDealers.ownerOf(tokenId1), userWithCash, "token #1 is still outstanding");
assertEq(nftDealers.balanceOf(userWithCash), 1, "user still owns token #1");
usdc.approve(address(nftDealers), lockAmt);
nftDealers.mintNft();
vm.stopPrank();
console2.log("After mint #2 - user balance:", usdc.balanceOf(userWithCash));
console2.log("After mint #2 - contract balance:", usdc.balanceOf(address(nftDealers)));
console2.log("After mint #2 - collateral token #1:", nftDealers.collateralForMinting(tokenId1));
console2.log("After mint #2 - collateral token #2:", nftDealers.collateralForMinting(tokenId2));
console2.log("After mint #2 - owner of token #1:", nftDealers.ownerOf(tokenId1));
console2.log("After mint #2 - owner of token #2:", nftDealers.ownerOf(tokenId2));
console2.log("After mint #2 - NFT balance of user:", nftDealers.balanceOf(userWithCash));
assertEq(nftDealers.ownerOf(tokenId1), userWithCash, "user still owns token #1");
assertEq(nftDealers.ownerOf(tokenId2), userWithCash, "user minted token #2 with the same capital");
assertEq(nftDealers.balanceOf(userWithCash), 2, "user now owns two NFTs");
assertEq(nftDealers.collateralForMinting(tokenId1), 0, "token #1 remains uncollateralized");
assertEq(nftDealers.collateralForMinting(tokenId2), lockAmt, "only token #2 is backed");
assertEq(usdc.balanceOf(address(nftDealers)), lockAmt, "contract holds only one lock amount for two NFTs");
}
[⠊] Compiling...
No files changed, compilation skipped
Ran 1 test for test/NFTDealersTest.t.sol:NFTDealersTest
[PASS] testCollateralRefundedWhileNftRemainsOutstanding() (gas: 419823)
Logs:
Initial userWithCash USDC balance: 20000000
Initial contract USDC balance: 0
Lock amount: 20000000
After mint #1 - user balance: 0
After mint #1 - contract balance: 20000000
After mint #1 - collateral token #1: 20000000
After mint #1 - owner of token #1: 0x22CdC71E987473D657FCe79C9C0C0B1A62148056
After mint #1 - NFT balance of user: 1
After cancel #1 - user balance: 20000000
After cancel #1 - contract balance: 0
After cancel #1 - collateral token #1: 0
After cancel #1 - owner of token #1: 0x22CdC71E987473D657FCe79C9C0C0B1A62148056
After cancel #1 - NFT balance of user: 1
After mint #2 - user balance: 0
After mint #2 - contract balance: 20000000
After mint #2 - collateral token #1: 0
After mint #2 - collateral token #2: 20000000
After mint #2 - owner of token #1: 0x22CdC71E987473D657FCe79C9C0C0B1A62148056
After mint #2 - owner of token #2: 0x22CdC71E987473D657FCe79C9C0C0B1A62148056
After mint #2 - NFT balance of user: 2
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 3.13ms (927.30µs CPU time)
Ran 1 test suite in 14.93ms (3.13ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)