Currently I have a working smart contract that only implements ReentrancyGuard
.
Here below an snippet of this code for major reference about what works:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "hardhat/console.sol";
contract NFTMarket is ReentrancyGuard {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
Counters.Counter private _tokensSold;
address payable owner;
uint256 listingPrice = 0.025 ether;
constructor() {
owner = payable(msg.sender);
}
struct MarketToken {
uint256 itemId;
address nftContract;
uint256 tokenId;
address payable seller;
address payable owner;
uint256 price;
bool sold;
}
mapping(uint256 => MarketToken) private idToMarketToken;
event MarketTokenMinted(
uint256 indexed itemId,
address indexed nftContract,
uint256 indexed tokenId,
address seller,
address owner,
uint256 price,
bool sold
);
function makeMarketItem(
address nftContract,
uint256 tokenId,
uint256 price
) public payable nonReentrant {
// nonReentrant is a modifier to prevent reentry attack.
require(price > 0, "Price must be at least one wei");
require(
msg.value == listingPrice,
"Price must be equal to listing price"
);
_tokenIds.increment();
uint256 itemId = _tokenIds.current();
idToMarketToken[itemId] = MarketToken(
itemId,
nftContract,
tokenId,
payable(msg.sender),
payable(address(0)),
price,
false
);
// NFT transaction.
IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);
emit MarketTokenMinted(
itemId,
nftContract,
tokenId,
msg.sender,
address(0),
price,
false
);
}
// ...
Since it is discouraged to use transferFrom()
as how this contract code from above has currently implemented inside the function makeMarketItem()
, I wanted to update that line to use instead safeTransferFrom()
, but in order for this new function to work properly my contract has to implement as well IERC721Receiver
. However when I do add it along with ReentrancyGuard
, I'll get the error "Contract "NFTMarket" should be marked as abstract".
Down below the code that produces the error:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "hardhat/console.sol";
contract NFTMarket is IERC721Receiver, ReentrancyGuard {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
Counters.Counter private _tokensSold;
address payable owner;
uint256 listingPrice = 0.025 ether;
constructor() {
owner = payable(msg.sender);
}
struct MarketToken {
uint256 itemId;
address nftContract;
uint256 tokenId;
address payable seller;
address payable owner;
uint256 price;
bool sold;
}
mapping(uint256 => MarketToken) private idToMarketToken;
event MarketTokenMinted(
uint256 indexed itemId,
address indexed nftContract,
uint256 indexed tokenId,
address seller,
address owner,
uint256 price,
bool sold
);
function makeMarketItem(
address nftContract,
uint256 tokenId,
uint256 price
) public payable nonReentrant {
// nonReentrant is a modifier to prevent reentry attack.
require(price > 0, "Price must be at least one wei");
require(
msg.value == listingPrice,
"Price must be equal to listing price"
);
_tokenIds.increment();
uint256 itemId = _tokenIds.current();
idToMarketToken[itemId] = MarketToken(
itemId,
nftContract,
tokenId,
payable(msg.sender),
payable(address(0)),
price,
false
);
// NFT transaction.
IERC721(nftContract).safeTransferFrom(msg.sender, address(this), tokenId);
emit MarketTokenMinted(
itemId,
nftContract,
tokenId,
msg.sender,
address(0),
price,
false
);
}
// ...
What I'm missing or how is the right way to set this up correctly?