
Mongo DB
Express.js
React.js
Node.js
Paypal Checkout
Solidity
Next.js
Viem
AI
Wagmi
Reown
Tailwind
HTML5
CSS3
TypeScript
A revolutionary NFT marketplace that combines artificial intelligence with blockchain technology to create a unique digital asset ecosystem. Users can generate stunning artwork through AI-powered image generation, mint them as NFTs, and trade them in a secure marketplace. The platform features a native token for transactions and rewards, plus an engaging game that lets players earn while they create and collect.
The marketplace stands out by offering an intuitive interface for AI image generation, allowing artists and collectors to create unique digital assets from text prompts. Each generated image can be instantly minted as an NFT, with full ownership rights and the ability to trade or sell in the marketplace.
Platform Features:

The platform's core features include an advanced AGENTIC AI image generator that transforms text descriptions into unique artwork, a secure marketplace for trading NFTs, and a play-to-earn game that rewards users with the platform's native token. The marketplace implements smart contracts for secure transactions and ownership verification, while the gaming component adds an engaging layer of interaction and potential earnings. Users can stake their NFTs, participate in community events, and earn rewards through various platform activities. The native token serves as both a utility token for platform features and a governance token for community decisions, creating a comprehensive ecosystem for digital asset creation and trading.
Core Contract:
// SPDX-License-Identifier: MIT
/\*
- ███╗ ██╗ ██████╗ ██╗███████╗████████╗ █████╗ ██████╗ ████████╗
- ████╗ ██║██╔════╝ ██║██╔════╝╚══██╔══╝ ██╔══██╗██╔══██╗╚══██╔══╝
- ██╔██╗ ██║██║ ███╗██║█████╗ ██║ ███████║██████╔╝ ██║
- ██║╚██╗██║██║ ██║██║██╔══╝ ██║ ██╔══██║██╔══██╗ ██║
- ██║ ╚████║╚██████╔╝██║██║ ██║ ██║ ██║ ██║██║ ██║ ██║
- ╚═╝ ╚═══╝ ╚═════╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝
\*/
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/common/ERC2981.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
contract NgiFTArt is ERC721, ERC721URIStorage, Ownable, ERC2981, EIP712 {
// ================= STATE VARIABLES =================
using ECDSA for bytes32;
uint256 private \_tokenIdCounter;
address public platformAddress;
uint256 public constant ROYALTY_PERCENTAGE = 3; // 3% royalty fee
IERC20 public immutable usdtToken; // Immutable for gas optimization
// NFT data structure
struct NFTData {
uint256 intrinsicValueUSDT;
uint256 salePriceUSDT;
bool isListed;
bool isFirstTransfer;
}
// Mappings for NFT data and transfer tracking
mapping(uint256 => NFTData) public nftData;
// ========== CUSTOM ERRORS ==========
error PaymentFailed();
error InsufficientAllowance();
error RoyaltyTransferFailed();
error SellerPaymentFailed();
// ================= EVENTS =================
event NFTMinted(address indexed owner, uint256 tokenId, string tokenURI);
event USDTWithdrawn(uint256 tokenId, address indexed owner, uint256 amount);
event NFTListed(uint256 tokenId, uint256 salePrice);
event NFTUnlisted(uint256 tokenId);
event NFTSold(uint256 tokenId, address buyer, address seller, uint256 price);
event NFTTransferred(uint256 tokenId, address from, address to);
// ================= CONSTRUCTOR =================
constructor(address _usdtToken) ERC721("NgiFT Art", "NGIFT") Ownable(msg.sender) EIP712("NgiFTArt", "1") {
platformAddress = msg.sender;
usdtToken = IERC20(_usdtToken);
_setDefaultRoyalty(platformAddress, uint96(ROYALTY_PERCENTAGE * 100));
}
// ================= CORE FUNCTIONS =================
/// @notice Mints a new NFT and transfers it to specified address
function mintNFT(address to, string memory uri) external onlyOwner {
uint256 newTokenId = _tokenIdCounter++;
_safeMint(platformAddress, newTokenId);
_setTokenURI(newTokenId, uri);
_transfer(platformAddress, to, newTokenId);
emit NFTMinted(to, newTokenId, uri);
}
// ================= SALES MANAGEMENT =================
/// @notice Lists an NFT for sale with specified price
function listForSale(uint256 tokenId, uint256 salePriceUSDT) external {
require(ownerOf(tokenId) == msg.sender, "Not NFT owner");
require(!nftData[tokenId].isListed, "Already listed");
require(salePriceUSDT > 0, "Invalid price");
nftData[tokenId].salePriceUSDT = salePriceUSDT;
nftData[tokenId].isListed = true;
emit NFTListed(tokenId, salePriceUSDT);
}
/// @notice Unlists an NFT from sale
function unlistNFT(uint256 tokenId) external {
require(ownerOf(tokenId) == msg.sender, "Not owner");
require(nftData[tokenId].isListed, "Not listed");
nftData[tokenId].isListed = false;
nftData[tokenId].salePriceUSDT = 0;
emit NFTUnlisted(tokenId);
}
/// @notice Completes NFT purchase and distributes funds
function buyNFT(uint256 tokenId) external {
require(nftData[tokenId].isListed, "NFT not listed for sale");
address seller = ownerOf(tokenId);
require(seller != msg.sender, "Owner cannot buy their own NFT");
uint256 price = nftData[tokenId].salePriceUSDT;
// Verify allowance before de transfer
if (usdtToken.allowance(msg.sender, address(this)) < price) {
revert InsufficientAllowance();
}
// Transfer USDT from buyer to contract
if (!usdtToken.transferFrom(msg.sender, address(this), price)) {
revert PaymentFailed();
}
// Transfer royalty
uint256 royalty = (price * ROYALTY_PERCENTAGE) / 100;
if (!usdtToken.transfer(platformAddress, royalty)) {
revert RoyaltyTransferFailed();
}
// Transfer payment to seller
if (!usdtToken.transfer(seller, price - royalty)) {
revert SellerPaymentFailed();
}
// Update state and transfer NFT
nftData[tokenId].isListed = false;
delete nftData[tokenId].salePriceUSDT;
_transfer(seller, msg.sender, tokenId);
emit NFTSold(tokenId, msg.sender, seller, price);
}
// ================= USDT MANAGEMENT =================
/// @notice Adds USDT to NFT's intrinsic value
function addUSDT(uint256 tokenId, uint256 amount) external {
require(ownerOf(tokenId) == msg.sender, "Not owner");
require(!nftData[tokenId].isListed, "Listed NFTs locked");
require(usdtToken.transferFrom(msg.sender, address(this), amount), "Transfer failed");
nftData[tokenId].intrinsicValueUSDT += amount;
}
/// @notice Withdraws USDT from NFT's intrinsic value
function withdrawUSDT(uint256 tokenId) external {
require(ownerOf(tokenId) == msg.sender, "Not owner");
require(!nftData[tokenId].isListed, "Listed NFTs locked");
require(nftData[tokenId].intrinsicValueUSDT > 0, "No balance");
uint256 amount = nftData[tokenId].intrinsicValueUSDT;
delete nftData[tokenId].intrinsicValueUSDT;
require(usdtToken.transfer(msg.sender, amount), "Withdrawal failed");
emit USDTWithdrawn(tokenId, msg.sender, amount);
}
// ================= TRANSFERING NFT =================
/// @notice First transfer (Platform pays gas fee)
function transferFirstTimeWithSignature(
address to,
uint256 tokenId,
bytes memory signature
) internal {
// Build hash with EIP712
bytes32 structHash = keccak256(abi.encode(
keccak256("Transfer(address from,address to,uint256 tokenId)"),
ownerOf(tokenId),
to,
tokenId
));
bytes32 digest = _hashTypedDataV4(structHash); // Generarte sign hash
// Recover signer address
address signer = ECDSA.recover(digest, signature);
require(signer == ownerOf(tokenId), "Invalid signature");
// Platform makes transfer
_transfer(ownerOf(tokenId), to, tokenId);
// Mark first nft transfer as done
nftData[tokenId].isFirstTransfer = true;
emit NFTTransferred(tokenId, ownerOf(tokenId), to);
}
/// @notice Normal NFT transfer (User pays gas fee)
function transferNFT(
address to,
uint256 tokenId,
bytes memory signature
) external {
require(!nftData[tokenId].isListed, "NFT is listed, cannot transfer.");
if (!nftData[tokenId].isFirstTransfer) {
require(msg.sender == platformAddress, "Not authorized to make the first transfer.");
transferFirstTimeWithSignature(to, tokenId, signature);
} else {
require(ownerOf(tokenId) == msg.sender, "Not authorized, only owner can execute transfer.");
_transfer(msg.sender, to, tokenId);
}
}
// ================= PROPER OVERRIDES FOR OZ 5.2.0 =================
/// @notice Required balance tracking override
function _increaseBalance(address account, uint128 amount) internal override(ERC721) {
super._increaseBalance(account, amount);
}
/// @notice Returns token URI with proper overrides
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
/// @notice ERC165 interface support check
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721URIStorage, ERC2981)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}