{"id":15642155,"url":"https://github.com/iamdefinitelyahuman/nftoken","last_synced_at":"2025-04-28T15:55:44.378Z","repository":{"id":68574916,"uuid":"207229371","full_name":"iamdefinitelyahuman/nftoken","owner":"iamdefinitelyahuman","description":"A non-fungible implementation of the ERC20 standard, allowing scalable NFT transfers with fixed gas costs.","archived":false,"fork":false,"pushed_at":"2024-03-20T15:31:48.000Z","size":55,"stargazers_count":64,"open_issues_count":2,"forks_count":21,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-28T15:55:30.032Z","etag":null,"topics":["brownie","erc20","ethereum","solidity"],"latest_commit_sha":null,"homepage":"","language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iamdefinitelyahuman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-09T05:17:42.000Z","updated_at":"2025-03-18T03:17:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"c8a9130c-3f5f-481a-a974-250b66a74ce7","html_url":"https://github.com/iamdefinitelyahuman/nftoken","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamdefinitelyahuman%2Fnftoken","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamdefinitelyahuman%2Fnftoken/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamdefinitelyahuman%2Fnftoken/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iamdefinitelyahuman%2Fnftoken/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iamdefinitelyahuman","download_url":"https://codeload.github.com/iamdefinitelyahuman/nftoken/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251342720,"owners_count":21574244,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["brownie","erc20","ethereum","solidity"],"created_at":"2024-10-03T11:54:58.552Z","updated_at":"2025-04-28T15:55:44.331Z","avatar_url":"https://github.com/iamdefinitelyahuman.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NFToken\n\n`NFToken` is a non-fungible implementation of the ERC20 standard, allowing scalable NFT transfers with fixed gas costs.\n\n## Motivations\n\n`NFToken` is inspired by discussions with [Gabriel Shapiro](https://twitter.com/lex_node) about the legal benefits and technical challenges of representing certificated shares on the Ethereum blockchain. See his excellent article \"[Tokenizing Corporate Capital Stock](https://gabrielshapiro.wordpress.com/2018/10/28/2/)\" for more information on this subject.\n\nThe 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.\n\nThe 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)](https://github.com/zerolawtech/ZAP-Tech), that allows unique attributes to be applied on a per-token basis.\n\n## How it Works\n\n`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`.\n\nRather 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.\n\nEach transfer of tokens will include one or more `TransferRange` events. Monitoring this event allows you to track the chain of custody for each token.\n\n## Gas Costs\n\nThe upper bound cost to mint is `~500,000` gas. This mints `2^64-2` tokens - the maximum `totalSupply` for the contract.\n\nThe 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.\n\nHowever, **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.\n\nThe 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](mailto:b.hauser@zerolaw.tech).\n\n## Interface\n\n`NFToken` fully implements the [ERC20 interface](https://theethereum.wiki/w/index.php/ERC20_Token_Standard) and adheres to all [expected behaviours](https://eips.ethereum.org/EIPS/eip-20). It also includes additional methods for working with token ranges, minting, and burning.\n\n### Working with Token Ranges\n\nTokens 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.\n\nThe following methods are available for accessing range data and initiating transfers:\n\n#### `rangesOf`\n\n```javascript\nfunction rangesOf(address _owner) external view returns (uint64[2][] memory)\n```\n\nGetter method that returns the `start:stop` indexes of each token range belonging to `_owner`.\n\n```python\n\u003e\u003e\u003e nft.rangesOf(accounts[1])\n((1, 1000), (2000, 10001))\n```\n\n#### `getRange`\n\n```javascript\nfunction getRange(uint256 _idx) external view returns (address _owner, uint64 _start, uint64 _stop)\n```\n\nGetter method that returns information about the range contains token `_idx`.\n\n```python\n\u003e\u003e\u003e token.getRange(31337).dict()\n{\n    '_owner': \"0xf414d65808f5f59aE156E51B97f98094888e7d92\",\n    '_start': 30000,\n    '_stop': 35001,\n}\n```\n\n#### `transferRange`\n\n```javascript\nfunction transferRange(address _to, uint64 _start, uint64 _stop) external returns (bool)\n```\n\nTransfers 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.\n\nAll transfers will emit one ``Transfer`` and one or more ``TransferRange`` events.\n\n```python\n\u003e\u003e\u003e nft.rangesOf(accounts[1])\n((1, 1000), (2000, 10001))\n\u003e\u003e\u003e nft.transferRange(accounts[2], 3333, 4242, {'from': accounts[1]})\nTransaction sent: 0x9ae3c41984aad767b2a535a5ade8f70b104b125da622124e9c3be52b7e373a11\nNFToken.transferRange confirmed - block: 4   gas used: 134829 (100.00%)\n\n\u003e\u003e\u003e nft.rangesOf(accounts[1])\n((1, 1000), (2000, 3333), (4242, 10001))\n```\n\n### Minting and Burning\n\n`NFTokenMintable` inherits `NFToken`, and includes functionality for minting and burning tokens.\n\n#### `mint`\n\n```javascript\nfunction mint(address _target, uint64 _value) external returns (bool)\n```\n\nMints `_value` new tokens that are owned by `_target`.\n\n```python\n\u003e\u003e\u003e nft.rangesOf(accounts[0])\n((1, 1001),)\n\u003e\u003e\u003e nft.mint(accounts[0], 5000, {'from': accounts[0]})\nTransaction sent: 0x77ec76224d90763641971cd61e99711c911828053612cc16eb2e5d7faa20815e\nNFToken.mint confirmed - block: 3   gas used: 182038 (100.00%)\n\n\u003e\u003e\u003e nft.rangesOf(accounts[0])\n((1, 6001),)\n```\n\n#### `burn`\n\n```javascript\nfunction burn(uint64 _start, uint64 _stop) external returns (bool)\n```\n\nBurns 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.\n\n```python\n\u003e\u003e\u003e nft.burn(accounts[0], 42, 1337, {'from': accounts[0]})\nTransaction sent: 0x5414b31e3e44e657ed5ee04c0c6e4c673ab2c6300f392dfd7c282b348db0bbc7\nNFToken.burn confirmed - block: 6   gas used: 48312 (100.00%)\n\n\u003e\u003e\u003e nft.rangesOf(accounts[0])\n((1, 42), (1337, 6001))\n```\n\n## Testing\n\nUnit testing and deployment of this project is performed with [Brownie](https://github.com/iamdefinitelyahuman/brownie).\n\nTo run the tests:\n\n```bash\nbrownie test\n```\n\nA [dockerfile](Dockerfile) is available if you are experiencing issues.\n\n## License\n\nThis project is licensed under the [MIT](https://github.com/iamdefinitelyahuman/nftoken/blob/master/LICENSE) license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiamdefinitelyahuman%2Fnftoken","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiamdefinitelyahuman%2Fnftoken","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiamdefinitelyahuman%2Fnftoken/lists"}