GithubHelp home page GithubHelp logo

classicvalues / nftoken Goto Github PK

View Code? Open in Web Editor NEW

This project forked from iamdefinitelyahuman/nftoken

0.0 1.0 0.0 56 KB

A non-fungible implementation of the ERC20 standard, allowing scalable NFT transfers with fixed gas costs.

License: MIT License

Solidity 96.74% Dockerfile 3.26%

nftoken's Introduction

NFToken

NFToken is a non-fungible implementation of the ERC20 standard, allowing scalable NFT transfers with fixed gas costs.

Motivations

NFToken is inspired by discussions with Gabriel Shapiro about the legal benefits and technical challenges of representing certificated shares on the Ethereum blockchain. See his excellent article "Tokenizing Corporate Capital Stock" for more information on this subject.

The goal in building NFToken was to create a token that is transferable like an ERC20, allows anyone to verify the complete chain of custody for any given token, and does not have prohibitively high gas costs for large transfers.

The implementation in this repository is a minimal proof of concept that can serve as a starting point for those who wish to expand upon these ideas and integrate them within their own projects. We have also produced an expanded version as an integral component of the ZeroLaw Augmentation Protocol (ZAP), that allows unique attributes to be applied on a per-token basis.

How it Works

NFToken applies a unique, sequential index value to every token. The first token minted will have an index value of 1. The maximum index value is 18446744073709551616 (2^64-2). References to token ranges are in the format start:stop where the final included value is stop-1. For example, a range of 2:6 would contains tokens 2, 3, 4 and 5.

Rather than storing every individual ID number, the contract only records the end of each token range. It takes advantage of the lack of cost in declaring empty storage, and saves range data in long fixed-length arrays.

Each transfer of tokens will include one or more TransferRange events. Monitoring this event allows you to track the chain of custody for each token.

Gas Costs

The upper bound cost to mint is ~500,000 gas. This mints 2^64-2 tokens - the maximum totalSupply for the contract.

The upper bound gas cost to transfer a single range is ~86,000 gas for the first range, and ~38,000 for each additional range. With a maximally fragmented token range, transferring one hundred tokens with a single token per range will cost ~39,000 gas per token.

However, transfer costs remain consistent regardless of the size of the range. This means the absolute lower bound cost, transferring 2^64-2 tokens as a single range, is ~0.00000000145 gas per token. A more reasonable lower bound, transferring one hundred tokens within a single range, costs ~860 gas per token.

The contract will merge ranges whenever possible, however fragmentation is inevitable and over time transfer costs are expected to increase. There are likely further optimizations that can be performed on this code to decrease costs and reduce the rate of fragmentation. If you have any ideas, I would love to hear from you.

Interface

NFToken fully implements the ERC20 interface and adheres to all expected behaviours. It also includes additional methods for working with token ranges, minting, and burning.

Working with Token Ranges

Tokens may be transferred via the standard ERC20 transfer and transferFrom methods, however if calling these methods there is no guarantee which specific tokens will be sent. The transferRange method allows a user to select exactly which tokens to transfer.

The following methods are available for accessing range data and initiating transfers:

rangesOf

function rangesOf(address _owner) external view returns (uint64[2][] memory)

Getter method that returns the start:stop indexes of each token range belonging to _owner.

>>> nft.rangesOf(accounts[1])
((1, 1000), (2000, 10001))

getRange

function getRange(uint256 _idx) external view returns (address _owner, uint64 _start, uint64 _stop)

Getter method that returns information about the range contains token _idx.

>>> token.getRange(31337).dict()
{
    '_owner': "0xf414d65808f5f59aE156E51B97f98094888e7d92",
    '_start': 30000,
    '_stop': 35001,
}

transferRange

function transferRange(address _to, uint64 _start, uint64 _stop) external returns (bool)

Transfers the token range _start:_stop from msg.sender to _to. Transferring a partial range is allowed. Transferring tokens from multiple ranges in the same call is not.

All transfers will emit one Transfer and one or more TransferRange events.

>>> nft.rangesOf(accounts[1])
((1, 1000), (2000, 10001))
>>> nft.transferRange(accounts[2], 3333, 4242, {'from': accounts[1]})
Transaction sent: 0x9ae3c41984aad767b2a535a5ade8f70b104b125da622124e9c3be52b7e373a11
NFToken.transferRange confirmed - block: 4   gas used: 134829 (100.00%)

>>> nft.rangesOf(accounts[1])
((1, 1000), (2000, 3333), (4242, 10001))

Minting and Burning

NFTokenMintable inherits NFToken, and includes functionality for minting and burning tokens.

mint

function mint(address _target, uint64 _value) external returns (bool)

Mints _value new tokens that are owned by _target.

>>> nft.rangesOf(accounts[0])
((1, 1001),)
>>> nft.mint(accounts[0], 5000, {'from': accounts[0]})
Transaction sent: 0x77ec76224d90763641971cd61e99711c911828053612cc16eb2e5d7faa20815e
NFToken.mint confirmed - block: 3   gas used: 182038 (100.00%)

>>> nft.rangesOf(accounts[0])
((1, 6001),)

burn

function burn(uint64 _start, uint64 _stop) external returns (bool)

Burns the tokens within the range _start:_stop. Only the contract owner can call to burn, and only tokens belonging to the owner can be burned.

>>> nft.burn(accounts[0], 42, 1337, {'from': accounts[0]})
Transaction sent: 0x5414b31e3e44e657ed5ee04c0c6e4c673ab2c6300f392dfd7c282b348db0bbc7
NFToken.burn confirmed - block: 6   gas used: 48312 (100.00%)

>>> nft.rangesOf(accounts[0])
((1, 42), (1337, 6001))

Testing

Unit testing and deployment of this project is performed with Brownie.

To run the tests:

brownie test

A dockerfile is available if you are experiencing issues.

License

This project is licensed under the MIT license.

nftoken's People

Contributors

iamdefinitelyahuman avatar nymd avatar lex-node avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.