Open-source project
fulldecent/erc721 avatar
fulldecent/erc721

erc721: a reference Solidity implementation of the non-fungible token standard

The reference implementation of the ERC-721 non-fungible token standard.

1,046 stars393 forksSolidityMIT

At a glance

What is it?
erc721 is the reference implementation of ERC-721, split into a base contract with ERC-165 support plus optional metadata and enumeration extensions. It is MIT licensed, tested with Hardhat, and stricter than the standard because it excludes payable calls by default.
Who is it for?
erc721 fits a team that wants audited starting contracts for ERC-721 rather than writing its own, and that accepts a stricter base than the standard, notably no payable calls. It does not fit a project that needs the richer feature set of the 0xcert Framework, or a team that needs the current Solidity toolchain conventions without touching the code.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 10 days ago.
What is it written in?
Mainly Solidity, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Three contracts, not one, and which one you need

The implementation is split by what a project actually needs from the standard, and the README explains the choice in terms of optional features.

`nf-token.sol` is the base ERC-721 token implementation and includes support for ERC-165, the interface detection standard. `nf-token-metadata.sol` implements the optional metadata features: a token name, a symbol, and a distinct URI pointing to a publicly exposed ERC-721 JSON metadata file. `nf-token-enumerable.sol` implements the optional enumeration extension, which is what you need if you want to know the total supply of tokens or query a token by index.

Other Solidity files in the `tokens` and `utils` directories named `erc*.sol` are interfaces that define the respective standards, so they describe the shape of the standard without implementing behaviour.

There is also a `mocks` folder with mock contracts showing basic contract usage, and a separate set of test mocks under the tests directory that exist specifically to exercise different edge cases and behaviours. The README is explicit that those test mocks should not be used as a reference for implementation, which is a small but useful warning, since the wrong folder is an easy mistake to make in a repository with two directories of example code.

All contracts and tests live under the `src` folder, and the whole project ships with Hardhat testing.

Stricter than the standard on purpose

The README flags a deviation from ERC-721 that any integrator will hit. This implementation is more restrictive than the ERC-721 standard since it does not support `payable` function calls out of the box, and you are free to add that yourself.

This is a design choice with a clear rationale behind it. A transfer that accepts value is a transfer that can be made to fail, can be made to re-enter, and can be made to cost the sender nothing if the receiver rejects it. Leaving the payable path out of the reference code and requiring the author to add it deliberately makes that decision visible in the diff rather than buried in a template.

The project also positions itself as a starting point rather than a finished framework. The stated purpose is to provide a good starting point for anyone who wants to use and develop non-fungible tokens, so that instead of re-implementing ERC-721 yourself you can use code that has gone through multiple audits. The audit claim is part of the pitch, and there is a `BUG_BOUNTY.md` in the repository along with a `SECURITY.md` for responsible disclosure.

For teams that want more than the standard offers, the README points at the 0xcert Framework as the more feature-rich and advanced option, and the project has since been transferred from 0xcert to Nibbstack and renamed from `0xcert/ethereum-erc721` to `@nibbstack/erc721`.

Installing the package or working from a clone

There are two supported routes, and the README marks one of them as the recommendation for each case.

If you want to use the package in your JavaScript project, install it from npm:

bash
npm install @nibbstack/[email protected]

The version is pinned in the command because the published package and this repository's contract code move together, and an unpinned install can pull in a different set of contracts than the one you read about.

If you want to improve the project itself, clone the repository and install the npm dependencies:

bash
git clone [email protected]:nibbstack/erc721.git
cd ethereum-erc721
npm install

Note that the clone command still points at the old repository name in the directory step, a leftover from the transfer that the README does not update.

Then check the setup by running the test suite:

bash
npm run test

Requirements are modest: NodeJS 12 or later, on Windows, Linux or macOS. The package manifest defines the test script as `npx hardhat test`, with separate `compile`, `flatten`, `coverage` and `solhint` scripts, the last running `solhint src/**/*.sol` over the Solidity sources.

Consuming the ABI from JavaScript and deploying in Remix

Interacting with the contracts from JavaScript means requiring the compiled JSON artifacts rather than importing Solidity:

js
const contract = require("@nibbstack/erc721/abi/NFTokenEnumerable.json");
console.log(contract);

For a quick deployment without a local toolchain, the README points at the Remix IDE in the browser, restricted to Ethereum. The worked example is a contract for selling glass-blown artwork, where one token represents one piece with a serial number, minting a token for each new piece and burning it when the physical item changes hands.

The example contract inherits from both the metadata extension and an `Ownable` contract, sets the token name and symbol in its constructor, and exposes a `mint` function restricted to the owner that takes the recipient address, the token id and an RFC 3986 URI:

solidity
function mint(
  address _to,
  uint256 _tokenId,
  string calldata _uri
)
  external
  onlyOwner
{
  super._mint(_to, _tokenId);
  super._setTokenUri(_tokenId, _uri);
}

The example imports the contracts from GitHub URLs directly, which works inside Remix and means the contract text in your IDE is tied to whatever is on that branch at the time you paste it.

The README also carries a legal note that is easy to skip and worth reading: you should contact a lawyer before holding an auction or selling anything, since auction laws vary widely by jurisdiction, and the example is provided only as an example of the technology.

Validation, chain coverage and the testnet playground

Two practical tools sit alongside the code.

The first is an online validator at erc721validator.org, which the README says you can use to check the validity of a smart contract, the correctness of the implementation and the supported functions of the respective smart contract. That is worth using before deployment rather than after, since a contract that is wrong is not cheap to fix once it is on a public chain.

The second is a testnet playground. The project deployed some contracts to the Ropsten network, and the README lists the token addresses and transaction hashes for `nf-token.sol` and the other implementations, so you can interact with them without installing anything. The warning attached is blunt: in this test version of the contract, anybody can `mint` or `burn` tokens, so it should not be used for anything important.

On chain coverage, the implementation is described as complete for the Ethereum and Wanchain blockchains, and also compatible with other EVM compatible chains such as Binance Smart Chain and Avalanche. That word compatible is doing work: it means the contracts run on those chains, not that the deployment and tooling path is the same everywhere.

Versions, tooling age and what that means for you

The release history is old. The tags are 2.5.0 on 2021-11-08, 2.5.1 on 2021-11-29, and 2.6.1 on 2021-12-02, and the package manifest version matches the last of those at 2.6.1. The repository is not archived and the last push was on 2026-10-14, so the contracts are still being edited, but the published npm versions have not moved since the end of 2021.

The development dependency versions tell you the same story. Hardhat is pinned at 2.7.0, ethers at 5.5.2, and the testing stack goes through `@nomiclabs/hardhat-ethers`, `@nomiclabs/hardhat-waffle`, `ethereum-waffle` and `chai`. Those are the versions pinned in late 2021, so a fresh install of a project pinned this way is working with an older generation of the tooling.

That is a cost you should price before you start. You can use these contracts as they are, and many teams do, but if your own project already uses a newer Hardhat and a current ethers, you will be dealing with two stacks. The alternative, migrating the contract source to your current toolchain, is a manageable task since the Solidity is the part you want, not the test harness.

The licence is MIT, which means you can take the contracts, modify them and ship them in a commercial product as long as you keep the copyright and licence notice, a property that is why a reference implementation like this gets copied as widely as it has.

Editorial conclusion

erc721 fits a team that wants audited starting contracts for ERC-721 rather than writing its own, and that accepts a stricter base than the standard, notably no payable calls. It does not fit a project that needs the richer feature set of the 0xcert Framework, or a team that needs the current Solidity toolchain conventions without touching the code. Before deploying anything derived from it, run `npm run test` to confirm the Hardhat suite passes on your Node version, read the BUG_BOUNTY.md and SECURITY.md files for the reporting process, and remember the transfer functions are not payable unless you add that yourself.

Frequently asked questions

What is the erc721 repository?

It is the reference implementation of the ERC-721 non-fungible token standard for the Ethereum and Wanchain blockchains, also compatible with other EVM chains. It was transferred from 0xcert to Nibbstack and renamed to @nibbstack/erc721.

How do I install the erc721 contracts?

For use in a JavaScript project, install the npm package with `npm install @nibbstack/[email protected]`. To work on the project itself, clone the repository, run `npm install`, and confirm the setup with `npm run test`, which runs the Hardhat test suite.

What is the difference between nf-token.sol, nf-token-metadata.sol and nf-token-enumerable.sol?

nf-token.sol is the base implementation with ERC-165 support, nf-token-metadata.sol adds the optional metadata extension with name, symbol and a URI, and nf-token-enumerable.sol adds enumeration so you can query total supply or a token by index.

Why does this ERC-721 implementation reject payments on transfers?

The implementation is more restrictive than the ERC-721 standard since it does not support payable function calls out of the box, though the README says you are free to add that yourself.

Is the erc721 package still current?

The published npm versions stop at 2.6.1 from 2021-12-02, and the dev toolchain is pinned to that era, with hardhat 2.7.0 and ethers 5.5.2. The repository is not archived and the last push was on 2026-10-14.

Official sources

  1. fulldecent/erc721 on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/fulldecent-erc721.svg)](https://hysenlabs.com/projects/fulldecent-erc721)

Was this useful?