---
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));
}
}
```