--- title: Sample 721 with GSN support tags: GSN --- # Sample 721 with GSN support ``` // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@opengsn/contracts/src/BaseRelayRecipient.sol"; contract GSN is ERC721, BaseRelayRecipient { using Counters for Counters.Counter; string public override versionRecipient = "2.2.0+opengsn.batched.irelayrecipient"; Counters.Counter private currentTokenId; /// @dev Base token URI used as a prefix by tokenURI(). string public baseTokenURI; mapping(uint256 => string) private _tokenURIs; constructor(address forwarder_) ERC721("GSN", "GSN") { baseTokenURI = ""; _setTrustedForwarder(forwarder_); } function _msgSender() internal view override(Context, BaseRelayRecipient) returns (address sender) { sender = BaseRelayRecipient._msgSender(); } function _msgData() internal view override(Context, BaseRelayRecipient) returns (bytes calldata) { return BaseRelayRecipient._msgData(); } function mintTo(address recipient, string memory tokenURI_) public returns (uint256) { currentTokenId.increment(); uint256 newItemId = currentTokenId.current(); _safeMint(recipient, newItemId); _setTokenURI(newItemId, tokenURI_); return newItemId; } /// @dev Returns an URI for a given token ID function _baseURI() internal view virtual override returns (string memory) { return baseTokenURI; } function showBaseURI() public view returns (string memory) { return baseTokenURI; } /// @dev Sets the base token URI prefix. function setBaseTokenURI(string memory _baseTokenURI) public { baseTokenURI = _baseTokenURI; } function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual { require( _exists(tokenId), "ERC721Metadata: URI set of nonexistent token" ); _tokenURIs[tokenId] = _tokenURI; } function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { require( _exists(tokenId), "ERC721Metadata: URI query for nonexistent token" ); string memory _tokenURI = _tokenURIs[tokenId]; string memory base = _baseURI(); // If there is no base URI, return the token URI. if (bytes(base).length == 0) { return _tokenURI; } // If both are set, concatenate the baseURI and tokenURI (via abi.encodePacked). if (bytes(_tokenURI).length > 0) { return string(abi.encodePacked(base, _tokenURI)); } // If there is a baseURI but no tokenURI, concatenate the tokenID to the baseURI. return string(abi.encodePacked(base, tokenId)); } } ```