# Create an NFT and deploy to a public testnet, using Truffle

**URL:** <https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961>\
**Category:** Guides and Tutorials\
**Tags:** erc721, nft\
**Created:** [May 29, 2020, 9:36am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961 "2020-05-29T09:36:47Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [May 29, 2020, 9:36am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/1 "2020-05-29T09:36:47Z")

</div>

In this tutorial we will create a non-fungible token (NFT) and deploy to a public testnet.

ERC721 is a standard for representing ownership of [_non-fungible_ tokens](https://docs.openzeppelin.com/contracts/3.x/tokens#different-kinds-of-tokens), that is, where each token is unique such as in real estate or collectibles.

We will use [Presets](https://docs.openzeppelin.com/contracts/3.x/api/presets) contracts in [OpenZeppelin Contracts 3](https://docs.openzeppelin.com/contracts/3.x/) to create an ERC721 and deploy using Truffle.

## Setting up the Environment

We begin by creating a new project.

```auto
$ mkdir mynft && cd mynft
$ npm init -y

```

Then we install [OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts) which has an implementation of ERC721.

```auto
npm install --save-dev @openzeppelin/contracts

```

Next we install a development tool for deployment, for this tutorial we will use [Truffle](https://www.trufflesuite.com/) but we could use any other tools such as Buidler, Remix or [OpenZeppelin CLI](https://docs.openzeppelin.com/cli).

```auto
npm install truffle

```

## Getting the contract artifacts

We will setup our Solidity project using `truffle init` to create a `contracts` directory and configuration to connect to a network.

```auto
$ npx truffle init
This directory is non-empty...
? Proceed anyway? (Y/n)
Starting unbox...
=================

? Proceed anyway? Yes
✔ Preparing to download box
✔ Downloading
✔ cleaning up temporary files
✔ Setting up box

Unbox successful, sweet!

Commands:

  Compile: truffle compile
  Migrate: truffle migrate
  Test contracts: truffle test

```

We are going to use Preset [`ERC721PresetMinterPauserAutoId`](https://docs.openzeppelin.com/contracts/3.x/api/presets#ERC721PresetMinterPauserAutoId) which is an ERC721 that is preset so it can be minted (with auto token ID and metadata URI), paused and burned.

The Preset contracts have already been compiled, so we only need to copy the artifacts to the `build/contracts` directory.

```auto
$ mkdir -p build/contracts/
$ cp node_modules/@openzeppelin/contracts/build/contracts/* build/contracts/

```

Using your favorite editor create `2_deploy.js` in the `migrations` directory with the following contents:

```auto
// migrations/2_deploy.js
// SPDX-License-Identifier: MIT
const ERC721PresetMinterPauserAutoId = artifacts.require("ERC721PresetMinterPauserAutoId");

module.exports = function(deployer) {
  deployer.deploy(ERC721PresetMinterPauserAutoId, "My NFT","NFT", "https://my-json-server.typicode.com/abcoathup/samplenft/tokens/");
};

```

## Deploy the contract to a local blockchain

We will use [`truffle develop`](https://www.trufflesuite.com/docs/truffle/reference/truffle-commands#develop) to open a Truffle console with a development blockchain

```auto
$ npx truffle develop
Truffle Develop started at http://127.0.0.1:9545/

Accounts:
(0) 0x0445c33bdce670d57189158b88c0034b579f37ce
(1) 0x46b68a577f95d02d2732cbe93c1809e9ca25b443
(2) 0xff8ddfd4ae8ed56c4b94738fef931b732f3aaeb5
...

Private Keys:
(0) 11e8321617611610d7561dfdf1fdbf87cee4cc99b97cc73c68f0eb5715fff7cc
(1) b28ee7deb262fbb6cccabb43179406e97bf7ff4c20b66feac3321019373531bd
(2) 44e5ce1f204a63e50faf2f202af1d5653aace83805dd9bc7062033f0625aaaa7
...

Mnemonic: ridge drop soon clutch empty north car drum maximum obey clinic coin

⚠️ Important ⚠️ : This mnemonic was created for you by Truffle. It is not secure.
Ensure you do not use it on production blockchains, or else you risk losing funds.

truffle(develop)>

```

We can deploy our new NFT to our development blockchain using migrate.

```auto
truffle(develop)> migrate

Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.

Starting migrations...
======================
> Network name: 'develop'
> Network id: 5777
> Block gas limit: 6721975 (0x6691b7)

1_initial_migration.js
======================

   Replacing 'Migrations'
   ----------------------
   > transaction hash: 0x5d71b0a45a0fe20e2ca645393bb44b83fbd47351c009c48be0b8b84b610fb3b7
   > Blocks: 0 Seconds: 0
   > contract address: 0x3797c825cAC4a1FA765F6D8cd7787fB195849555
   > block number: 1
   > block timestamp: 1590736865
   > account: 0x0445c33BdCe670D57189158b88c0034B579f37cE
   > balance: 99.99671674
   > gas used: 164163 (0x28143)
   > gas price: 20 gwei
   > value sent: 0 ETH
   > total cost: 0.00328326 ETH

   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost: 0.00328326 ETH

2_deploy.js
===========

   Replacing 'ERC721PresetMinterPauserAutoId'
   ------------------------------------------
   > transaction hash: 0x166d7b28f4afb949585b5a0e5b4151daa54acbcb70566b202fd62ab380a6650c
   > Blocks: 0 Seconds: 0
   > contract address: 0xDEE9411430c7Dd9b67fC6DA723DE729AdAB50AD7
   > block number: 3
   > block timestamp: 1590736866
   > account: 0x0445c33BdCe670D57189158b88c0034B579f37cE
   > balance: 99.92191642
   > gas used: 3697675 (0x386c0b)
   > gas price: 20 gwei
   > value sent: 0 ETH
   > total cost: 0.0739535 ETH

   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost: 0.0739535 ETH

Summary
=======
> Total deployments: 2
> Final cost: 0.07723676 ETH

```

We can then use our deployed contract.

```auto
truffle(develop)> nft = await ERC721PresetMinterPauserAutoId.deployed()
undefined

```

## Interact with our Token

The accounts that we can use were displayed when we started `truffle develop`

### Token metadata

We can call the contract to read token metadata such as `name`, `symbol` and `baseURI`

```auto
truffle(develop)> await nft.name()
'My NFT'
truffle(develop)> await nft.symbol()
'NFT'
truffle(develop)> await nft.baseURI()
'https://my-json-server.typicode.com/abcoathup/samplenft/tokens/'

```

### Mint

We can send a transaction to mint tokens to a given account, from an account with the minter role.  
In our case we are minting from the account which deployed the token, which is given the minter role.

We will mint 1 NFT with token ID 0.

```auto
truffle(develop)> await nft.mint("0x0445c33bdce670d57189158b88c0034b579f37ce")
{ tx:
   '0xd301a60dbb8ac187687f6639f200d4e6f2cfa065923092b3940330e35a26421d',
  receipt:
   { transactionHash:
      '0xd301a60dbb8ac187687f6639f200d4e6f2cfa065923092b3940330e35a26421d',
     transactionIndex: 0,
     blockHash:
      '0x3ad3cfcb26da0c969e9d5a5414a5e90a91a3a862c9e9082afc38a0ec0f1a5d00',
     blockNumber: 5,
     from: '0x0445c33bdce670d57189158b88c0034b579f37ce',
     to: '0xdee9411430c7dd9b67fc6da723de729adab50ad7',
     gasUsed: 156470,
...

```

We can check the owner of the token and the token URI for the metadata

```auto
truffle(develop)> await nft.ownerOf(0)
'0x0445c33BdCe670D57189158b88c0034B579f37cE'
truffle(develop)> await nft.tokenURI(0)
'https://my-json-server.typicode.com/abcoathup/samplenft/tokens/0'

```

## MetaData

[EIP-721](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md) includes an optional **metadata extension** with a `name`, `symbol` and for each tokenID a `tokenURI` with can point to a JSON file with `name`, `description` and `image` for the given token ID.

How you create and host this metadata is up to you.  
I would suggest using a domain that you control to point to where you host the data so that you can move it as required.

For this tutorial, we will use [My JSON Server](https://my-json-server.typicode.com/) where we can store a single JSON file in a GitHub repository that we can access via a fake JSON server.

⚠ For production we need to store our metadata in a permanent location that can exist for the life of the token.

For images we will use twemoji Graphics from [https://github.com/twitter/twemoji](https://github.com/twitter/twemoji) which are licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)

A sample JSON for tokenID 0 is:  
[http://my-json-server.typicode.com/abcoathup/samplenft/tokens/0](http://my-json-server.typicode.com/abcoathup/samplenft/tokens/0)

## Deploy to a public testnet

Next we will deploy to Rinkeby public testnet as OpenSea supports Rinkeby for testing.

To deploy, we will use the instructions for [Connecting to Public Test Networks with Truffle](https://forum.openzeppelin.com/t/connecting-to-public-test-networks-with-truffle/2960)

You will need the following:

- An Infura project ID (or a public node provider of your choice)
- `@truffle/hdwallet-provider` installed
- Configure `truffle-config.js` for Rinkeby network
- A funded testnet account and mnemonic
- A `secrets.json` or another secret-management solution. **Make sure you don’t commit this to GitHub!**

My `truffle-config.js` has the following `rinkeby` configuration:

```auto
    rinkeby: {
      provider: () => new HDWalletProvider(mnemonic, `https://rinkeby.infura.io/v3/${projectId}`),
      network_id: 4, // Rinkeby's id
      gas: 8500000,        
      gasPrice: 1000000000, // 1 gwei (in wei) (default: 100 gwei)
      confirmations: 2, // # of confs to wait between deployments. (default: 0)
      timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50)
      skipDryRun: true // Skip dry run before migrations? (default: false for public nets )
    },

```

### Deploy to Rinkeby

```auto
$ npx truffle console --network rinkeby
truffle(rinkeby)> migrate

Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.

Starting migrations...
======================
> Network name: 'rinkeby'
> Network id: 4
> Block gas limit: 10000000 (0x989680)

1_initial_migration.js
======================

   Deploying 'Migrations'
   ----------------------
   > transaction hash: 0xf817c3bb3b44349da50d90ef41317b64207eef76c5546a3348a8d8043a2d4d12
   > Blocks: 1 Seconds: 30
   > contract address: 0x1C883F26d124148c2E632539B4c37A6beD5eCD6f
   > block number: 6572315
   > block timestamp: 1590740195
   > account: 0x77737a65C296012C67F8c7f656d1Df81827c9541
   > balance: 3.986111900199984594
   > gas used: 164163 (0x28143)
   > gas price: 1 gwei
   > value sent: 0 ETH
   > total cost: 0.000164163 ETH

   Pausing for 2 confirmations...
   ------------------------------
   > confirmation number: 1 (block: 6572316)
   > confirmation number: 2 (block: 6572317)

   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost: 0.000164163 ETH

2_deploy.js
===========

   Deploying 'ERC721PresetMinterPauserAutoId'
   ------------------------------------------
   > transaction hash: 0x169e09cf7d50c226339493237b1d0981af0eed44698d35a132674105c311cb6e
   > Blocks: 0 Seconds: 9
   > contract address: 0x5c5c53D13aD8725cFE551D6E9dB93e9a9D38D78D
   > block number: 6572320
   > block timestamp: 1590740270
   > account: 0x77737a65C296012C67F8c7f656d1Df81827c9541
   > balance: 3.982371884199984594
   > gas used: 3697675 (0x386c0b)
   > gas price: 1 gwei
   > value sent: 0 ETH
   > total cost: 0.003697675 ETH

   Pausing for 2 confirmations...
   ------------------------------
   > confirmation number: 1 (block: 6572321)
   > confirmation number: 2 (block: 6572322)

   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost: 0.003697675 ETH

Summary
=======
> Total deployments: 2
> Final cost: 0.003861838 ETH

```

### Mint

We can send a transaction to mint tokens to a given account, from an account with the minter role.

```auto
truffle(rinkeby)> nft = await ERC721PresetMinterPauserAutoId.deployed()
undefined

```

In our case we are minting from the account which deployed the token, which is given the minter role.

To see configured accounts run the command `accounts`.

```auto
truffle(rinkeby)> accounts
[ '0x77737a65C296012C67F8c7f656d1Df81827c9541',

```

We will mint 1 NFT with token ID 0. Specify the address that you want to be the token holder (`0x77737a65C296012C67F8c7f656d1Df81827c9541` is one of my test accounts)

```auto
truffle(rinkeby)> await nft.mint("0x77737a65C296012C67F8c7f656d1Df81827c9541")
{ tx:
   '0xce8132ff0ffce128b8508d396fb0625a12c839fd1ee886eab5b4ddaf2755ca6f',
  receipt:
   { blockHash:
      '0x3f546e5caa9142d89dc3a87e7d369ba175629b480840d8bf88bd146f205e62de',
     blockNumber: 6572543,
     contractAddress: null,
     cumulativeGasUsed: 1410693,
     from: '0x77737a65c296012c67f8c7f656d1df81827c9541',
     gasUsed: 149870,
...

```

## OpenSea

We can validate our metadata

📓 To obtain the address of our contract on Rinkeby we can use the Truffle console

```auto
truffle(rinkeby)> nft.address
'0x5c5c53D13aD8725cFE551D6E9dB93e9a9D38D78D'

```

OpenSea metadata validation is at `https://rinkeby-api.opensea.io/asset/[nft contract address]/[token id]/validate`

My example can be found at:  
[https://rinkeby-api.opensea.io/asset/0x5c5c53D13aD8725cFE551D6E9dB93e9a9D38D78D/0/validate/](https://rinkeby-api.opensea.io/asset/0x5c5c53D13aD8725cFE551D6E9dB93e9a9D38D78D/0/validate/)

Assuming that there aren’t any issues with our metadata, we can view our NFT on OpenSea at `https://rinkeby.opensea.io/assets/[nft contract address]/[token id]`

My example can be found at:

> **[My NFT 0 - My NFT | OpenSea](https://testnets.opensea.io/assets/0x5c5c53D13aD8725cFE551D6E9dB93e9a9D38D78D/0)**
>
> My NFT

## Next steps

- Create your artwork and metadata.
- Host your images and metadata.
- Define what rights your token holders have.
- [Prepare for mainnet](https://docs.openzeppelin.com/learn/preparing-for-mainnet).

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [October 7, 2020, 12:37am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/2 "2020-10-07T00:37:19Z")

</div>

A post was split to a new topic: [Deployment failed on Rinkeby: “ERC721PresetMinterPauserAutoId” hit an invalid opcode](https://forum.openzeppelin.com/t/deployment-failed-on-rinkeby-erc721presetminterpauserautoid-hit-an-invalid-opcode/4055)

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [October 11, 2020, 11:56pm UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/3 "2020-10-11T23:56:29Z")

</div>

2 posts were split to a new topic: [Issue querying the balanceOf ERC721 contract from another ERC20 contract](https://forum.openzeppelin.com/t/issue-querying-the-balanceof-erc721-contract-from-another-erc20-contract/4104)

---

<div class="post-metadata">

**Author:** ![pacman809](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/pacman809/32/3333_2.png) [@pacman809](https://forum.openzeppelin.com/u/pacman809)\
**Post date:** [October 30, 2020, 5:08pm UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/4 "2020-10-30T17:08:15Z")

</div>

> [@abcoathup](#):
>
> [EIP-721](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md) includes an optional **metadata extension** with a `name` , `symbol` and for each tokenID a `tokenURI` with can point to a JSON file with `name` , `description` and `image` for the given token ID.
> 
> How you create and host this metadata is up to you.  
> I would suggest using a domain that you control to point to where you host the data so that you can move it as required.

Can you elaborate on how to use the extension for metadata? I am looking to change the metadata for every token. I have deployed the ```  
ERC721PresetMinterPauserAutoId

```contract
Thank You
```

---

<div class="post-metadata">

**Author:** ![jing](https://avatars.discourse-cdn.com/v4/letter/j/71e660/32.png) [@jing](https://forum.openzeppelin.com/u/jing)\
**Post date:** [November 6, 2020, 4:37pm UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/5 "2020-11-06T16:37:46Z")

</div>

**FOR THOSE USING WINDOWS LISTEN UP:**

instead of using the linux/mac commands for copying the artifacts instead manually go into the @openzeppelin folder within the project and copy paste from @openzeppelin/contracts/build/contracts/ then go back to the main folder of desktop/mynft and paste all the 4 artifacts into the build/contracts folder.

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [November 8, 2020, 10:36pm UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/6 "2020-11-08T22:36:30Z")

</div>

Hi @jing,

Thanks for sharing. Whilst I use Windows 10, I do all my smart contract development on Windows Subsystem for Linux (WSL2).

For Windows users I recommend using WSL2. Much of the ecosystem is written for and tested on Linux, so life is much easier using WSL. [Solidity Smart Contract development on Windows](https://forum.openzeppelin.com/t/solidity-smart-contract-development-on-windows/2110)

---

<div class="post-metadata">

**Author:** ![DavidGattis](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/davidgattis/32/3578_2.png) [@DavidGattis](https://forum.openzeppelin.com/u/DavidGattis)\
**Post date:** [November 17, 2020, 8:41pm UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/7 "2020-11-17T20:41:33Z")

</div>

Thanks for the tutorial, useful information! 👍

---

<div class="post-metadata">

**Author:** ![jsmellz](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/jsmellz/32/3947_2.png) [@jsmellz](https://forum.openzeppelin.com/u/jsmellz)\
**Post date:** [January 2, 2021, 1:03am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/8 "2021-01-02T01:03:27Z")

</div>

Good article! Thanks.

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [February 2, 2021, 12:16am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/9 "2021-02-02T00:16:20Z")

</div>

A post was split to a new topic: [ERC721 Transfer fails on MetaMask](https://forum.openzeppelin.com/t/erc721-transfer-fails-on-metamask/5638)

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [February 4, 2021, 10:12pm UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/10 "2021-02-04T22:12:00Z")

</div>

A post was split to a new topic: [Deploy failed](https://forum.openzeppelin.com/t/deploy-failed/5672)

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [March 15, 2021, 4:27am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/12 "2021-03-15T04:27:44Z")

</div>

A post was split to a new topic: [Hosting ERC721 metadata](https://forum.openzeppelin.com/t/hosting-erc721-metadata/6284)

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [March 16, 2021, 3:50am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/13 "2021-03-16T03:50:22Z")

</div>

A post was split to a new topic: [Where to store NFT metadata and where to set the price?](https://forum.openzeppelin.com/t/where-to-store-nft-metadata-and-where-to-set-the-price/6322)

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [March 22, 2021, 3:49am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/14 "2021-03-22T03:49:06Z")

</div>

A post was split to a new topic: [“Migrations” – transaction could not be decoded: could not recover secp256k1 key](https://forum.openzeppelin.com/t/migrations-transaction-could-not-be-decoded-could-not-recover-secp256k1-key/6429)

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [April 6, 2021, 9:01am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/15 "2021-04-06T09:01:55Z")

</div>

A post was split to a new topic: [Cost to deploy ERC721 token to mainnet](https://forum.openzeppelin.com/t/cost-to-deploy-erc721-token-to-mainnet/6789)

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [April 16, 2021, 6:55am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/16 "2021-04-16T06:55:02Z")

</div>

A post was split to a new topic: [Batch mint with ERC721PresetMinterPauserAutoId?](https://forum.openzeppelin.com/t/batch-mint-with-erc721presetminterpauserautoid/7045)

---

<div class="post-metadata">

**Author:** ![abcoathup](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/abcoathup/32/415_2.png) [@abcoathup](https://forum.openzeppelin.com/u/abcoathup)\
**Post date:** [April 19, 2021, 5:20am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/17 "2021-04-19T05:20:22Z")

</div>

3 posts were split to a new topic: [nft.baseURI is not a function](https://forum.openzeppelin.com/t/nft-baseuri-is-not-a-function/7126)

---

<div class="post-metadata">

**Author:** ![anhskrttt](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/anhskrttt/32/4490_2.png) [@anhskrttt](https://forum.openzeppelin.com/u/anhskrttt)\
**Post date:** [May 7, 2021, 6:47am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/18 "2021-05-07T06:47:29Z")

</div>

I completed this and it was a really good tutorial!

There is one question that I dont know how to figure it out. Can somebody drop any reference for me about how to make my own image on twemoji. I tried to search for some, but just didnt find anything thats helpful. I want to upload my own img to twemoji, to get my own twemoji link (ex: [https://twemoji.maxcdn.com/svg/1f40e.svg](https://twemoji.maxcdn.com/svg/1f40e.svg)). Can I upload my own img or I have to “draw my own” from twemoji?

Thanks for your support!

---

<div class="post-metadata">

**Author:** ![frangio](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/frangio/32/15251_2.png) [@frangio](https://forum.openzeppelin.com/u/frangio)\
**Post date:** [May 20, 2021, 8:50pm UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/19 "2021-05-20T20:50:34Z")

</div>

You can’t upload images to twemoji, you will need to host your own images somewhere else, such as GitHub Pages, or IPFS via [Pinata](https://pinata.cloud).

---

<div class="post-metadata">

**Author:** ![aster2709](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/aster2709/32/6378_2.png) [@aster2709](https://forum.openzeppelin.com/u/aster2709)\
**Post date:** [June 9, 2021, 7:04am UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/22 "2021-06-09T07:04:53Z")

</div>

my nft is deployed at 0x0843e3bdEc2c8F640FCead18BBD7929593B58cA6 and token 0 was minted, I’ve followed the tutorial and it also validated successfully, but my image doesn’t show up, why could that be? thanks in advance

---

<div class="post-metadata">

**Author:** ![frangio](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/frangio/32/15251_2.png) [@frangio](https://forum.openzeppelin.com/u/frangio)\
**Post date:** [June 9, 2021, 1:21pm UTC](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961/23 "2021-06-09T13:21:07Z")

</div>

When you say “my image doesn’t show up”, where are you trying to see it? I can see the contract on Rinkeby and it seems to have correct metadata.

[Next page](https://forum.openzeppelin.com/t/create-an-nft-and-deploy-to-a-public-testnet-using-truffle/2961.md?page=2)
