// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /** * @title Genesis Mint Certificate NFT (G-CERT) * @notice On-Chain ERC-721 Institutional Certificate of Deposit & Asset Title * @dev Cryptographically anchors real-world assets (Cash, Gold, SKR, Gems, Treasuries) * to on-chain stablecoin issuance via Merkle Trees and IPFS metadata manifests. */ interface IERC721Receiver { function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4); } contract GenesisMintCertificateNFT { string public name = "Genesis Institutional Mint Certificate"; string public symbol = "G-CERT"; address public owner; address public authorizedAttestor; // Trust Officer / Auditor / Custodian uint256 private _nextTokenId; struct AssetCertificate { string assetType; // e.g. "USD_FIAT_SEED", "GOLD_BULLION_LBMA", "SKR_SECURITY_VAULT", "GEMS_GIA_CERTIFIED" uint256 valuationUSD; // 6 decimals ($5.00 = 5000000) bytes32 merkleRoot; // Cryptographic root of asset dossier (Assays, Title, Escrow Receipts) string ipfsCid; // ipfs:// CID containing decentralized immutable metadata string custodianLegalEntity; // Bonded Custodian / Vault Entity uint256 mintTimestamp; address stablecoinContract; // The stablecoin minted against this backing bool active; } mapping(uint256 => AssetCertificate) public certificates; mapping(uint256 => address) private _owners; mapping(address => uint256) private _balances; // Events event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); event CertificateMinted( uint256 indexed tokenId, address indexed recipient, string assetType, uint256 valuationUSD, bytes32 merkleRoot, string ipfsCid ); event AttestorUpdated(address indexed newAttestor); modifier onlyOwner() { require(msg.sender == owner, "Ownable: not owner"); _; } modifier onlyAttestor() { require(msg.sender == authorizedAttestor || msg.sender == owner, "Attestor: unauthorized"); _; } constructor(address _attestor) { owner = msg.sender; authorizedAttestor = _attestor; _nextTokenId = 1; } function ownerOf(uint256 tokenId) external view returns (address) { address tokenOwner = _owners[tokenId]; require(tokenOwner != address(0), "ERC721: non-existent token"); return tokenOwner; } function balanceOf(address account) external view returns (uint256) { require(account != address(0), "ERC721: zero address"); return _balances[account]; } /** * @notice Mints an immutable on-chain certificate linking physical/fiat reserves to stablecoin supply */ function issueCertificate( address recipient, string calldata assetType, uint256 valuationUSD, bytes32 merkleRoot, string calldata ipfsCid, string calldata custodianLegalEntity, address stablecoinContract ) external onlyAttestor returns (uint256) { require(recipient != address(0), "Invalid recipient"); require(merkleRoot != bytes32(0), "Invalid merkle root"); uint256 tokenId = _nextTokenId++; _owners[tokenId] = recipient; _balances[recipient] += 1; certificates[tokenId] = AssetCertificate({ assetType: assetType, valuationUSD: valuationUSD, merkleRoot: merkleRoot, ipfsCid: ipfsCid, custodianLegalEntity: custodianLegalEntity, mintTimestamp: block.timestamp, stablecoinContract: stablecoinContract, active: true }); emit CertificateMinted(tokenId, recipient, assetType, valuationUSD, merkleRoot, ipfsCid); emit Transfer(address(0), recipient, tokenId); return tokenId; } function tokenURI(uint256 tokenId) external view returns (string memory) { require(_owners[tokenId] != address(0), "Non-existent token"); return certificates[tokenId].ipfsCid; } function getCertificate(uint256 tokenId) external view returns (AssetCertificate memory) { require(_owners[tokenId] != address(0), "Non-existent token"); return certificates[tokenId]; } function setAuthorizedAttestor(address _newAttestor) external onlyOwner { authorizedAttestor = _newAttestor; emit AttestorUpdated(_newAttestor); } }