All Projects → 1001-digital → erc721-extensions

1001-digital / erc721-extensions

Licence: MIT license
A set of composable extension contracts for the OpenZeppelin ERC721 base contracts.

Programming Languages

solidity
1140 projects
javascript
184084 projects - #8 most used programming language
shell
77523 projects

Projects that are alternatives of or similar to erc721-extensions

fnd-docs
Foundation developer docs
Stars: ✭ 33 (-78.98%)
Mutual labels:  smart-contracts, nfts
Awesome NFTs
A curated collection about NFTs - by bt3gl
Stars: ✭ 42 (-73.25%)
Mutual labels:  erc721, nfts
opensea-scraper
Scrapes nft floor prices and additional information from opensea. Used for https://nftfloorprice.info
Stars: ✭ 129 (-17.83%)
Mutual labels:  erc721, nfts
Simple-Game-ERC-721-Token-Template
🔮 Very Simple ERC-721 Smart Contract Template to create your own ERC-721 Tokens on the Ethereum Blockchain, with many customizable Options 🔮
Stars: ✭ 83 (-47.13%)
Mutual labels:  smart-contracts, erc721
erc721
The reference implementation of the ERC-721 non-fungible token standard.
Stars: ✭ 989 (+529.94%)
Mutual labels:  smart-contracts, erc721
ethereum-dex
Decentralized exchange implementation for the 0xcert protocol on the Ethereum blockchain.
Stars: ✭ 18 (-88.54%)
Mutual labels:  smart-contracts, erc721
nftfy-v1-core
A decentralized protocol for NFT fractionalization
Stars: ✭ 62 (-60.51%)
Mutual labels:  smart-contracts, erc721
nft-contracts
Open-source NFT contracts used by buildship.dev
Stars: ✭ 60 (-61.78%)
Mutual labels:  smart-contracts, erc721
enigma-docker-network-deprecated
A containarized Enigma Protocol environment to start writing secret contracts
Stars: ✭ 50 (-68.15%)
Mutual labels:  smart-contracts
awesome-ico-truths
Awesome Initial Coin Offerings (ICO) Truths - The Art of the Steal - The Scammers' Big Lies ++ ICO tokens are like bitcoins, ICOs are like IPOs, ICO White Papers are like "Due Diligence" Inverstor Prospectus, ...
Stars: ✭ 32 (-79.62%)
Mutual labels:  erc721
rICO-smart-contracts
Smart contracts for the Reversible ICO (rICO)
Stars: ✭ 38 (-75.8%)
Mutual labels:  smart-contracts
docs
Unleash Bitcoin's full potential with decentralized apps and smart contracts. The documentation covers key aspects of the Stacks network and technology and provides tutorials and other helpful content for developers.
Stars: ✭ 134 (-14.65%)
Mutual labels:  smart-contracts
algo-builder
Framework to automate development of Algorand Assets and Smart Contracts.
Stars: ✭ 132 (-15.92%)
Mutual labels:  smart-contracts
react-truffle-metamask
Build an DApp using react, redux, saga, truffle, metamask
Stars: ✭ 25 (-84.08%)
Mutual labels:  smart-contracts
ethereum-erc20
Fungible token implementation for the Ethereum blockchain.
Stars: ✭ 27 (-82.8%)
Mutual labels:  smart-contracts
gas-reporting
Reference documentation on every gas price API and all the different formats
Stars: ✭ 85 (-45.86%)
Mutual labels:  smart-contracts
MCW-Azure-Blockchain
MCW Azure Blockchain
Stars: ✭ 35 (-77.71%)
Mutual labels:  smart-contracts
defi-dapps-solidity-smart-contracts
This is a Web 3 Smart Contract learning and teaching repo which will be used to teach students all across Pakistan.
Stars: ✭ 241 (+53.5%)
Mutual labels:  erc721
awesome-solidity-gas-optimization
Best resources for Solidity gas optimizations ⛽
Stars: ✭ 893 (+468.79%)
Mutual labels:  smart-contracts
contracts
Off-the-shelf Solidity smart contracts
Stars: ✭ 100 (-36.31%)
Mutual labels:  smart-contracts

ERC721 Contract Extensions

A set of composable extensions for the OpenZeppelin ERC721 base contracts.

Available Extensions

WithContractMetaData.sol

Link to your collection's contract meta data right from within your smart contract.

Builds on Ownable and allows the contract owner to change contract metadata even after deployment.

Make sure the URL links to an appropriate JSON file.

contract Token is ERC721, WithContractMetadata {
  constructor()
    ERC721("Token", "LT")
    WithContractMetadata("ipfs://0123456789123456789123456789123456789123456789/metadata.json")
  {}
}

To change the contract metadat URI, call setContractURI(string uri) as the contract owner.

WithIPFSMetaData.sol

Handles linking to metadata files hosted on IPFS and follows best practices doing so:

  • Projects have to embed the Content ID hash in the contract right from the start
  • Project owners can never change the CID
  • Tokens link to an ipfs://-URL to be independent of particular IPFS Gateways.
  • Tokens wrap a folder with a metadata.json file (and pot. all the assets of the token).

Note: You should never publish metadata before public sale is complete.
This is to prevent people from trying to snipe rare tokens (rarity can be derived from going through all metadata files and looking at the trait and attribute distributions). Although very expensive (in gas fees) to do so, it is potentially possible and thus bad practice.

contract CleanToken is ERC721, WithIPFSMetaData {
  constructor()
    ERC721("CleanToken", "CT")
    WithIPFSMetaData("0123456789123456789123456789123456789123456789")
  {}
}

WithIPFSMetadataAndPreviewMetadata.sol

TODO

WithTransferTimeLock.sol

To prevent an attack vector right after public sale of tokens, this extension adds a timelock to transfers for 12 hours after initial sale. This gives all buyers enough time to familiarise themselves with their tokens and the entire collection, as well as the rarities of items.

Alternatively: Publish the entire collection without tokenIDs from the get go / or at least all rarity statistics.

TODO

WithLimitedSupply.sol

A simple token tracker that limits the token supply.

To keep track of the token supply and to get the next available tokenID, call nextToken() when creating new tokens.

contract RareToken is ERC721, WithLimitedSupply {
  constructor()
    ERC721("RareToken", "RT")
    WithLimitedSupply(1000) // Max. 1k NFTs available
  {}

  function mint () external ensureAvailability() {
    uint256 newTokenId = nextToken(); // Create a new token ID

    // ...
  }
}

The internal nextToken() method does not automatically check whether tokens are available but WithLimitedSupply provides the ensureAvailability modifier that you can attach to your minting function. If you implement minting multiple tokens within the same transaction, you should check availability with the ensureAvailabilityFor(amount) modifier.

There are two Contracts that build on this: LinearlyAssigned, which adds the option of starting the token tracker from a specific number and RandomlyAssigned, wich enables semi random token ID assignments.

LinearlyAssigned.sol

Instanciate it with the max supply as well as the starting index:

contract RareToken is ERC721, LinarlyAssigned {
  constructor()
    ERC721("RareToken", "RT")
    LinarlyAssigned(1000, 1) // Max. 1k NFTs available; Start counting from 1 (instead of 0)
  {}

  function mint () external ensureAvailability() {
    uint256 newTokenId = nextToken(); // Create a new token ID

    // ...
  }
}

RandomlyAssigned.sol

(Semi-)randomly* assign token IDs from a fixed collection size on mint.

contract RandomToken is ERC721, RandomlyAssigned {
  constructor()
    ERC721("RandomToken", "RT")
    RandomlyAssigned(1000, 1) // Max. 1k NFTs available; Start counting from 1 (instead of 0)
  {}

  function mint () external ensureAvailability() {
    uint256 newTokenId = nextToken(); // Create a new random token ID

    // ...
  }
}

*) We can't create proper random numbers on chain. But this does the job well enough, if you hide your metadata during public sale and are not too valuable of an NFT project (pot. exploit costs a lot of gas, thus making it economically unfeasible to do for profit for 'normal' NFT collections). If you want true random assignment, check out Chainlink.

WithSaleStart.sol

An extension that enables the contract owner to set and update the date of a public sale.

This builds upon the Ownable extension, so only contract deployers can change the sale start via setSaleStart(uint256 time). Also, to stay true to the trustless spirit of NFTs, it is not possible to change the sale start after the initial sale started.

To use this in your project, call the afterSaleStart / beforeSaleStart modifiers.

contract MyToken is ERC721, WithSaleStart {
  constructor()
    ERC721("MyToken", "MT")
    WithSaleStart(1735686000)
  {}

  function claim () external afterSaleStart {
    // ...
  }
}

LimitedTokensPerWallet.sol

Limits the amount of tokens an external wallet can hold.

contract LimitedToken is ERC721, LimitedTokensPerWallet {
  constructor()
    ERC721("LimitedToken", "LT")
    LimitedTokensPerWallet(3) // Only allow three tokens per wallet
  {}

  // Mint & Transfer limits are taken care of by the library.
}

OnePerWallet.sol

A more extreme version of LimitedTokensPerWallet, which only allows holding one token in an external wallet address.

To use this in your project just extend the Contract. If you need more control, call the onePerWallet modifier.

contract OneForAllToken is ERC721, OnePerWallet {
  constructor()
    ERC721("OneForAllToken", "OFA")
  {}

  // Mints and Transfer limites are taken care of by the library.
}

The above code does not prevent people from minting multiple tokens via a separate smart contract - it only checks against externally owned accounts (wallets with private keys). If you want to account for that, additionally activate the onePerAccount modifier on your mint function.

WithMarketOffers.sol

Implements a simple offer based marketplace. Owners of tokens can choose to sell them via the in-built market.

Just extend the WithMarketOffers.sol contract to make this work.

WithFees.sol

Aims to abstracts out the complexity of current fee standards.

contract SharedUpsideToken is ERC721, WithFees {
  constructor()
    ERC721("SharedUpsideToken", "SUP")
    // 500 Basis Points (5%) of secondary sales 
    // should go to the given beneficiary address
    WithFees(0xe11Da9560b51f8918295edC5ab9c0a90E9ADa20B, 500)
  {}

  function supportsInterface(bytes4 interfaceId) public view override(WithFees, ERC721) returns (bool) {
    return WithFees.supportsInterface(interfaceId);
  }
}

WithWithdrawals.sol

A simple helper that implements a withdrawal function.

Just call withdraw as the contract owner.

Installation

  1. In your project run npm install @1001-digital/erc721-extensions
  2. Within your project, import the extensions you want to use like import "@1001-digital/erc721-extensions/contracts/WithIPFSMetaData.sol";

Local Development

This project uses the Hardhat development environment. To set it up locally, clone this repository and run npm install.

Note: You can exchange npm run for hh if you have hh installed globally on your system.

  • Run the test suite: npm run test
  • Spin up a local development blockchain: npm run node

Thank You

If you have any improvement suggestions, feedback or bug reports please feel free add an issue, or reach out via Twitter @jwahdatehagh or Email [email protected].

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].