The simple intention of my smart contract is to be able to give away an NFT (from your wallet) as a gift. I added a function to schedule when the recipient receives the NFT gift.
I achieved this by manipulating the time / block.timestamp when the code below in my contract is allowed to run
_transfer( from, to, tokenId );
Although I think the smart contract is ready for deployment/production, am not sure if I am using the BEST testing approach to verify that it is ready for production deployment.
I am hoping someone can point out a better/best testing practice for my contract.
Find below my smart contract code, followed by my step-by-step testing approach.
The idea is that you follow my my step-by-step testing approach and keep referring back to the code below:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;import "@openzeppelin/contracts@4.4.2/token/ERC721/ERC721.sol";
contract etherGifter is ERC721 {
address private to; address private from; string private messageToRecipient; uint256 public giftCount = 0; address private owner; uint256 private tokenId = 1; uint256 private firstReminderAt; uint256 private createdAt; enum Status { recipientAssigned, firstReminderSent, secondReminderSent, giftGifted } struct CryptoGift { address from; address to; uint256 tokenId; string tokenName; string messageToRecipient; Status GiftStatus; uint256 createdAt; uint256 firstReminderAt; } mapping(address => CryptoGift) public gifts; constructor() ERC721("Crypto Gifter", "CGFT") { owner = msg.sender; } function mintNFTtoken() public { _safeMint(msg.sender, tokenId); tokenId ++; } function setGiftRecipient( address _to, string calldata _tokenName, uint256 _tokenId, string calldata _messageToRecipient ) public payable { gifts[msg.sender] = CryptoGift(msg.sender, _to, _tokenId, _tokenName, _messageToRecipient, Status.recipientAssigned, block.timestamp, block.timestamp +30 ); giftCount++; } function getGiftStatus() public view returns ( Status) { CryptoGift storage giftStatus = gifts[msg.sender]; return giftStatus.GiftStatus; } function processGifting() public payable { CryptoGift storage giftRecipient = gifts[msg.sender]; uint256 isExecutionDate = giftRecipient.firstReminderAt; require( block.timestamp >= isExecutionDate, "WAIT... Its Not yet Valentines Day!" ); from = giftRecipient.from; to = giftRecipient.to; tokenId = giftRecipient.tokenId; _transfer( from, to, tokenId ); CryptoGift storage giftStatus = gifts[msg.sender]; giftStatus.GiftStatus = Status.giftGifted; giftCount--; }
}
The intention of my smart contract ISNT to mint any NFT tokens, however for testing purposes, I have had to add an NFT minting function. Needless to say, I will remove this function before deployment.
mintNFTtoken()
Because without any NFT's in my testing environment, I wouldn't have been able to test my smart contract.
In Remix, I deploy in the JavaScript VM Environment
using account: 0x5B3...eddC4 as the default wallet.
I mint 3 NFT tokens using the below function:
mintNFTtoken()
Running the Zeppelin ERC721 inherited function balanceOF() function confirms that 3 NFT tokens were successfully minted.
Also running Zeppelin ERC721 inherited function ownerOf() function confirms that NFT tokenId 1 is owned by the default wallet.
I then decide to choose the gift recipient by running my function
setGiftRecipient()
for recipient parameter: _to, I choose the wallet address: 0xAb...5cb2
token Name parameter: _tokenName, I write : None
for the tokenId parameter: _tokenId, I choose : 1
for the message parameter: _messageToRecipient, I write: Happy Valentines Day!
Ensuring that I am running the setGiftRecipient() as the contract owner:
I run my function below:
setGiftRecipient()
To verify that everything is in order, I run:
Excited that everything is working as designed, I now choose to process (the transfer of the gift) the gifting, by running:
processGifting()
Because I set the timer to 30 seconds, I first get the below message:
The transaction has been reverted to the initial state.
Reason provided by the contract: "WAIT... Its Not yet Valentines Day!".
I wait a few seconds later, then I run:
processGifting()
...and get an indication that the transaction was successful
I also check to varify new ownership of token number 1, by running Zeppelin ERC721 inherited function ownerOf() function.
My testing approach verifies that:
- The scheduling of the NFT transfers work,
- Also that the NFT transfers from an original owner to a new owner also works.
Is there a better method to run tests on my Dapp?