An implementation of ERC1155D, a record setter for minting and transfer gas efficiency.

Overview

ERC1155D

An implementation of ERC1155D, a record setter for minting and transfer gas efficiency.

This contract is in alpha stage and has not been audited yet. This is only to demonstrate how the functionality works. Production use is not recommended!

Usage

The ERC1155D contract is a gas efficient NFT contract. An alternative to ERC721. It is intended to only be used for 1/1 NFT's (supply of 1) and does not support tokens with supply greater than 1.

To use the ERC1155D contract in your project, copy contracts/ERC1155D.sol to your project. Then, you can import it, and write an implementation that extends the contract as is ERC1155

NOTE: ERC1155D does not maintain tokenID enumeration. You will need to implement a counter for it in your contract, similar to supply in the example below.

example:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "../ERC1155D.sol";

/**
 * @title ERC1155D example implementation
 */
contract Example is ERC1155 {
    uint256 public supply; // tokenID's

    constructor(string memory uri) ERC1155(uri) {}

    function setURI(string memory newuri) public {
        _setURI(newuri);
    }

    function mint(address to, uint256 id) public {
      // amount is always 1    memory bytes, required param for IERC1155
      //                \       /
      //                 \     /
        _mint(to, supply, 1, '');
        supply++;
    }

Tests

This repo inherits the ERC1155 unit tests (hardhat-truffle) from the official OpenZeppelin contract tests. To run the tests:

  • install the dependencies with yarn or npm install
  • Run npx hardhat test tests/ERC1155.test.js

Maximally efficient Implementation

This is more for vanity metrics, but it is possible to acheive 50,434 gas with the following code. This eliminates the fallback function due to the function selector being all zeros, so if anyone sends ether directly to your contract, the transaction will revert.

pragma solidity 0.8.13;

contract ExampleMint {

    uint256 public constant MAX_SUPPLY = 10000;
    address[MAX_SUPPLY] _owners;
    uint256 public constant PRICE = 0.01 ether;
    uint256 private index = 1;
    
    event TransferSingle(address, address, address, uint256, uint256);

    function mint_efficient_1268F998() external payable {
        require(msg.value == PRICE, "wrong price");
        uint256 _index = index;
        require(_index < MAX_SUPPLY, "supply limit");

        emit TransferSingle(msg.sender, address(0), msg.sender, _index, 1);
        assembly {
            sstore(add(_owners.slot, _index), caller())
        }

        unchecked {
            _index++;
        }
        index = _index;
    }
}
Comments
  • _mintSingle function visibility.

    _mintSingle function visibility.

    _mintSingle is exposed as external and I believe this should be restricted to internal because :

    • This can lead to unexpected behaviors if used by others without being aware that the function can mint tokens
    • The contract should be flexible in a way to use the core implementation without the need to delete undesirable behaviours
    • The function is not part of ERC1155

    PS: Thanks for sharing this implementation.

    opened by uranium93 2
  • add function for prepaying gas

    add function for prepaying gas

    Summary

    This function allows the devs (or a friendly whale, if desired) to prepay some of the gas for minting. Setting the _owners storage from address(0) to the owner costs 22,100 gas (20,000 storage + 2,100 cold access).

    Addresses are 20 bytes long and don't use the left 12 bytes. This function sets the leftmost bit to 1. It leaves the other bits unaffected. This is to safeguard against someone overwriting addresses after mint.

    This can result in net savings for the community if the gas is prepaid during a cheap period, and minting happens during an expensive period.

    Unit Economics

    It costs 5,000 gas to go from non-zero to non-zero storage. By prepaying 22,100 gas, the minter saves 17,100 gas. It would seem that 5,000 gas is "wasted." However, this can result in a net gain for the community if done during a low congestion period. Example:

    low gas period: 20 gwei minting period: 100 gwei

    Cost in Ether to prepay the storage slot: 20 * 22,100 / 1 billion = 0.000442 Cost in Ether to store new address during mint with prepayment: 100 * 5,000 / 1 billion = 0.0005 Cost in Ether to store new address during mint sans prepayment: 100 * 22,100 / 1 billion = 0.00221

    Net savings: 0.00221 - 0.0005 - 0.000442 = 0.001268 Ether per address. This is substantial when thousands of addresses are involved.

    Implementation Details

    If thousands of addresses are involved, the prepayment must be done in several transactions to avoid running into the gas block limit. Thus, start and end are provided to enable breaking up the transaction.

    If the devs so desire, they can incentivize early minters by prepaying only the first hundred or so token ids.

    Credits

    This methodology was inspired by https://gastoken.io/

    opened by DonkeVerse 0
  • Implements (and passes) OpenZeppellin's ERC1155 token unit test suite

    Implements (and passes) OpenZeppellin's ERC1155 token unit test suite

    Notable changes:

    • Reorganizes to a hardhat project structure
    • Adds the basic tests and test dependencies in tests/
    • Adds contracts/Mocks for unit tests
    • Adds hardhat-config
    • Converts GitHub imports to @openzeppelin package imports

    tl;dr

    This PR has a lot in it, the main changes are:

    • moving the contract to the contracts folder
    • changing imports to @openzeppelin imports (for hardhat compilation the tests runner can read)
    • addition of test and mocks

    ERC1155.test.js is the main Unit test entry point. to run tests, install dependencies with yarn then npx hardhat test tests/ERC1155.test.js

    The other folders and files inside tests are additional utils and tests the main test file needs.

    Mocks

    the mock contracts are also used for unit tests and must be included-they also act as sample implementations

    all tests passing.

    84 tests are run and pass, these are the same tests used in the ERC1155 token tests from OZ, with the modification that calls to _mint only pass in an amount of 1 image

    I took the liberty of adding to the readme. open to changes there. 🙇

    opened by nftchef 0
  • Changes == operator to properly assign receipient address

    Changes == operator to properly assign receipient address

    Fixes a typo that prevents tokens from being transferred when calling _safeBatchTransferFrom Previously, was failing silently while passing all checks and emitting events while not actually transferring the tokens.

    image
    opened by nftchef 0
  • Adding `isOwnerOf` interface

    Adding `isOwnerOf` interface

    Hi @DonkeVerse @jeffreyscholz

    I am building two ERC1155 NFT implementations that also restricts themselves for 1/1 NFTs applications, and I am wondering whether we can have a common interface that can potentially be a standard in the future.

    • https://github.com/ctor-lab/ERC1155Delta
    • https://github.com/ctor-lab/ERC1155Soul

    Since the implementation of ERC1155Delta doesn't allow querying the ownership information from the id in order to achieve constant-gas batch minting. Therefore, ownerOfERC721Like will not work in this implementation.

    Instead, I am proposing to use the following interface for the ownership verification purpose.

     function isOwnerOf(address account, uint256 id) external view returns(bool);
    

    Also, adding this interface to supportsInterface so the third-party contract can recognise it and enables applications that is only available to 1/1 NFTs.

    opened by estarriolvetch 0
  • Not a issue - question on _beforeTokenTransfer

    Not a issue - question on _beforeTokenTransfer

    Read your article regarding this on Medium, and thank you for putting this together.

    When using the ERC1155, my use case was a collection of items, but there will always be just 1 item. I know I could use EIP721, but I'm really enjoying the gas savings.

    On my mint and reserve functions, I always set "amount" to 1, as you suggested. But for batch transfers, I implemented the following. Curious if this is overkill or not. Here, I always want to ensure the "amount" will able be 1. I wasn't sure if this would already be taken care of due to the minting function.

    function _beforeTokenTransfer(address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data)
            internal
            whenNotPaused
            override
        {
            uint256[] memory _amounts = new uint256[](ids.length);
    
            for (uint i = 0; i < ids.length; i++) {
                _amounts[i] = 1;
            }
    
            super._beforeTokenTransfer(operator, from, to, ids, _amounts, data);
        }
    

    If this isn't the correct place to ask this question, totally understand and can move it over to the Medium article.

    opened by james-lukensow 0
Owner
An NFT collection of donkes. Join our discord! https://discord.gg/3vrEG7ES
null
A JavaScript object getter and setter with string literals ⚡

objectio (object + io) A JavaScript object getter and setter with string literals ⚡ Usage import { get, set } from 'objectio'; const obj = { a: 1,

Shiono Yoshihide 2 Sep 14, 2022
Basic Implementation of a Contract Wallet in Solidity. The owner can transfer Ether/ERC20 and execute transactions via low-level calls.

Contract Wallet Basic Implementation of a Contract Wallet in Solidity. The owner can transfer Ether/ERC20 and execute transactions via low-level calls

Junho Yeo 3 Jun 18, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
A CLI tool to generate barrels with ease, efficiency, and intelligence

JS-Barrels A CLI tool to generate barrels with ease, efficiency, and intelligence Usage npx js-barrels -d ./folder/to/generate/barrels/for Options -d,

Snehil K 6 Aug 17, 2022
Claim $ARB airdrop of several wallets at the same time and transfer all the tokens to one address

arbitrum-airdrop-claimer Claim $ARB airdrop of several wallets at the same time and transfer all tokens to one address You need to have Node.js instal

Wizer 4 Mar 21, 2023
Hexo-backlink - This plugin is for transfer Obsidian-type backlink to standard hexo in-site post link.

Hexo-Backlink A plugin to convert backlink in .md file to in-site link. Install npm install hexo-backlink configuration Add backlink:true in _config.y

null 8 Sep 27, 2022
Crawler Crypto using NodeJS for performance with Elasticsearch DB for high efficiency.

Coin crawler - Coingecko version Crawler using NodeJS for performance with Elasticsearch DB for high efficiency. Requirements For development, you wil

Minh.N.Pham 1 Jan 20, 2022
Marry in Web3, Mint Paired Soulbound NFTs by MultiSign Flow, No transfer, No sell, a non-financial Dapp

ERC721-520 Token 是 NFT-like Soulbound Token Standard(灵魂绑定凭证) 的一种实现,是 ERC721 标准的扩展。 ERC721-520 Token 不可转让,不可售卖,一个人同时只能有一个有效 Token ERC721-520 Token 由二者通

Marry3 48 Dec 21, 2022
A cross-platform file transfer tool

LocalTransformer 不要被GitHub的评定给误导,该项目的实现和js没有任何关系,虽然web文件夹中有几万行js代码...,该项目是以go语言作为服务后台,flutter框架实现前台界面,本仓库为go的后端实现,当然也打包了web前端实现,由于相较于被功能的实现,后端的代码可能100

L_B__ 3 Oct 28, 2022
This project focuses on increasing the efficiency of a hospital's patient waitlist by creating an algorithm to generate an ordered list of 10 patients with the highest chance of accepting an appointment offer.

Patients-Facility Technical Interview Requirements This application was built on Node.JS v12.14. It has not been tested on other versions. You will al

Rwubakwanayo Olivier 4 Mar 20, 2023
Ethereum smart contract gas cost waste pattern detection and patching tool

Ethereum smart contract gas cost waste pattern detection and patching tool

ibelab 4 Mar 23, 2022
Hardhat plugin to track gas on the transaction level

hardhat-gas-trackooor Hardhat plugin to track gas on the transaction level. Example report Installation npm install hardhat-gas-trackooor --save-dev A

null 16 Jan 3, 2023
Gas-efficient on-chain batched shuffling for NFTs

Batch NFT reveal This repository contains a gas-efficient implementation of an on-chain shuffling algorithm used to reveal NFTs in batches. The main b

Tubby Cats 97 Dec 12, 2022
A prototype snap for injecting gas fee prices into a confirmation window that also serves as the basis for a 5-minute Snaps tutorial

@Montoya/gas-fee-snap A simple Snap example based on @MetaMask/template-snap. Read below for a tutorial! Prerequisites Before you begin, make sure you

Christian Montoya 18 Dec 8, 2022
Eigen ZK-ZKRollup, Low gas-fee, better privacy-enhancement, high composable

ZKZRU: Eigen ZK-ZKRollup Eigen ZK-ZKRollup provides confidential transaction for users with low gas cost. The ZK-Rollup is an extention of RollupNC an

Eigen Labs 25 Dec 22, 2022
🛠️ Easily track & compare gas costs estimated by Foundry on each of your Pull Requests!

?? ??️ Foundry Gas Diff Reporter Easily compare gas reports generated by Foundry automatically on each of your Pull Requests! How it works Everytime s

Romain Milon 133 Dec 28, 2022