I am trying to setup an escrow contract which takes a deposit as a NFT into the contract. I am struggling to deposit the NFT into the contract.
I start by having a simple NFT that gets minted to the address with an id.
contract MyEpicNFT is ERC721URIStorage {
// Magic given to us by OpenZeppelin to help us keep track of tokenIds.
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
// We need to pass the name of our NFTs token and its symbol.
constructor() ERC721 ("SquareNFT", "SQUARE") {
console.log("This is my NFT contract. Woah!");
console.log(address(this));
}
// A function our user will hit to get their NFT.
function makeNft() public {
uint256 newItemId = _tokenIds.current();
_safeMint(msg.sender, newItemId);
_setTokenURI(newItemId, "https://jsonkeeper.com/b/1LHH");
console.log("An NFT w/ ID %s has been minted to %s", newItemId, msg.sender);
_tokenIds.increment();
}
}
An NFT w/ ID 0 has been minted to the msg.sender of the contract in this case: 0xdD870fA1b7C4700F2BD7f44238821C26f7392148
I know now I need to approve the Escrow contract to be allowed to "spend" this token. To do this on MyEpicNft contract I call the approve function with the contract address of the MyEpicNft and the Id of the NFT that was minted.
console.log:
This is my NFT contract. Woah!
0x5fc7Dc95b4Bb48dbC9894fCaE417482cb8A6A45a
In my case I call the approve with (0x5fc7Dc95b4Bb48dbC9894fCaE417482cb8A6A45a, 0) - this seems to work. Now what I need to do in the NftEscrow contract is to deposit the NFT.
The approve function i am using is from the ERC721 lib
approve(address to, uint256 tokenId)
There is a depositNFT function which takes the NFT address - in our case 0x5fc7Dc95b4Bb48dbC9894fCaE417482cb8A6A45a and 0. But when i do this i get the error message:
The transaction has been reverted to the initial state.
Reason provided by the contract: "ERC721: transfer caller is not owner nor approved".
Debug the transaction to get more information.
contract NftEscrow is IERC721Receiver {
enum ProjectState {newEscrow, nftDeposited, cancelNFT, ethDeposited, canceledBeforeDelivery, deliveryInitiated, delivered}
address payable public sellerAddress;
address payable public buyerAddress;
address public nftAddress;
uint256 tokenID;
bool buyerCancel = false;
bool sellerCancel = false;
ProjectState public projectState;
receive() external payable {
}
constructor(){
sellerAddress = payable(msg.sender);
projectState = ProjectState.newEscrow;
}
function onERC721Received( address , address , uint256 , bytes calldata ) public pure override returns (bytes4) {
return this.onERC721Received.selector;
}
function depositNFT(address _NFTAddress, uint256 _TokenID) public onlySeller {
nftAddress = _NFTAddress;
tokenID = _TokenID;
ERC721(nftAddress).safeTransferFrom(msg.sender, address(this), tokenID);
projectState = ProjectState.nftDeposited;
}
function depositEth() public payable {
buyerAddress = payable(msg.sender);
projectState = ProjectState.ethDeposited;
}
function confirmDelivery()public payable {
ERC721(nftAddress).safeTransferFrom(address(this), buyerAddress, tokenID);
sellerAddress.transfer(address(this).balance);
}
modifier onlySeller() {
require(msg.sender == sellerAddress);
_;
}
}
Not sure what I am doing wrong and been stuck on this for a day. Why can't i deposit the NFT to the smart contract?