0

I'm developing zero fee NFT trading contract. After I canceled a listing of NFT, my smart contract's varuable is not updated.

  1. write approve() function of the NFT contract
  2. write list() function of my contract
  3. write cancelListing() function of my contract
  4. read _nftToItem() function and it's owner, specifiedBuyer, listed property of Item struct is not updated
  5. read getListedItem() function and get Error: Returned error: execution reverted

I deployed contract on Polygon Mumbai testnet.

Is there any mistake in my solidity code? Fully code is here.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";

contract ZeroTrade is ReentrancyGuard, ERC721Holder {
  using Counters for Counters.Counter;
  Counters.Counter public _itemCount; // TODO: change to private if neeeded
  Counters.Counter public _listedItemCount; // TODO: change to private if needed

  mapping(address => mapping(uint256 => Item)) public _nftToItem; // TODO: change to private if needed  

  mapping(uint256 => address) public _itemToContract;
  mapping(address => uint256[]) public _contractToTokenIds;
  mapping(address => uint256) public _contractTokenCount;

  struct Item {
    address nftContract;
    uint256 tokenId;
    address payable seller;
    address owner;
    address specifiedBuyer;
    uint256 price;
    bool listed;
  }

  constructor() {
    
  }

  function list(address _nftContract, uint256 _tokenId, address _buyer, uint256 _price) public payable nonReentrant {
    require(_price > 0, "Price must be at least 1 wei");
    require(_nftToItem[_nftContract][_tokenId].nftContract == address(0x0), "This NFT has been listed in the past. Use reList function.");
    
    IERC721(_nftContract).safeTransferFrom(msg.sender, address(this), _tokenId);

    _nftToItem[_nftContract][_tokenId] = Item(
      _nftContract,
      _tokenId, 
      payable(msg.sender),
      address(this),
      _buyer,
      _price,
      true
    );
    uint256 itemCount = _itemCount.current();
    _itemCount.increment();
    _listedItemCount.increment();

    _itemToContract[itemCount] = _nftContract;
    _contractToTokenIds[_nftContract].push(_tokenId);
    _contractTokenCount[_nftContract] += 1;
    emit NFTListed(_nftContract, _tokenId, msg.sender, address(this), _buyer, _price);
  }

  function cancelListing(address _nftContract, uint256 _tokenId) public payable nonReentrant {
    Item memory item = _nftToItem[_nftContract][_tokenId];
    require(msg.sender == item.seller, "You are not the seller");

    IERC721(_nftContract).safeTransferFrom(address(this), msg.sender, _tokenId);

    item.owner = msg.sender;
    item.specifiedBuyer = address(0);
    item.listed = false;

    _listedItemCount.decrement();
    emit NFTCancelListing(_nftContract, item.tokenId, msg.sender, item.owner);
  }

  function getListedItems() public view returns (Item[] memory) {
    uint256 itemCount = _itemCount.current();
    uint256 listedItemCount = _listedItemCount.current();

    Item[] memory items = new Item[](listedItemCount);
    uint itemsIndex = 0;
    for (uint i = 0; i < itemCount; i++) {
      address nftContract = _itemToContract[i];
      uint256[] memory tokenIds = new uint256[](_contractTokenCount[nftContract]);
      tokenIds = _contractToTokenIds[nftContract];
   
      for (uint j = 0; j < _contractTokenCount[nftContract]; j++) {
        uint256 tokenId = tokenIds[j];
        if (_nftToItem[nftContract][tokenId].listed) {
          items[itemsIndex] = _nftToItem[nftContract][tokenId];
          itemsIndex++;
        }
      }
    }
    return items;
  }

}

1 Answer 1

0

There is a small mistake in your cancelListing() function. You want to cancel the listing and reset the struct values stored in the mapping. Mappings, by default, store the data in the storage, i.e., on-chain. But here, when you created your instance item, you created it in memory. Thus, any change to the values will be on temporary memory and never on-chain. That's why your actual values were never updated.

Solution:

Item storage item = _nftToItem[_nftContract][_tokenId];

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.