├── .github └── workflows │ └── markdown_link_checker.yml ├── .gitignore ├── LICENSE ├── README.md ├── assets └── images │ ├── branding.png │ ├── discord.svg │ ├── fig_entering.png │ ├── fig_exiting.png │ ├── fig_fuel_transactions.png │ ├── fig_node.png │ ├── fig_segwit.png │ ├── fig_send.png │ ├── fig_structs.png │ ├── fig_subscription.png │ ├── fig_swaps.png │ ├── fig_token_minting.png │ ├── fig_tx.png │ └── fig_witnesses.png ├── config ├── build.js └── files.js ├── package-lock.json ├── package.json ├── public ├── arrow-dark.svg ├── arrow.svg ├── discord.svg ├── dracula.css ├── edit.svg ├── favicon.png ├── github.svg ├── index.css ├── index.html ├── index.js ├── logo-old.svg ├── logo.svg ├── next.svg ├── open-menu.svg ├── search-gray.svg └── search.svg └── src └── v1.0.0 ├── 1. Introduction ├── 1. Welcome.md ├── 2. Benchmarks.md └── 3. Use Cases.md ├── 2. Getting Started ├── 0. Using the Wallet SDK.md ├── 1. One-Click Example.md └── 2. Running a Node.md ├── 2. SDK └── 1. Wallet.md ├── 3. Concepts ├── 0. Fundamentals │ ├── 1. Fuel Overview.md │ ├── 2. Security Analysis.md │ ├── 3. Block Architecture.md │ ├── 4. Transaction Architecture.md │ ├── 5. Serialization.md │ ├── 6. System Description Primer.md │ └── 7. Deployment Parameters.md ├── 1. Data Structures │ ├── Addresses.md │ ├── Blocks.md │ ├── Deposits.md │ ├── Inputs.md │ ├── Metadata.md │ ├── Outputs.md │ ├── Roots.md │ ├── Tokens.md │ ├── Transactions.md │ ├── Withdrawals.md │ └── Witness.md ├── 2. Verifiers │ ├── Block Header.md │ ├── Data.md │ ├── Inputs.md │ ├── Merkle Proof.md │ ├── Transaction Proof.md │ └── Witness.md ├── 3. Provers │ ├── Double Spend.md │ ├── Invalid Input.md │ ├── Invalid Sum.md │ ├── Invalid Transaction.md │ ├── Invalid Witness.md │ └── Malformed Block.md └── 4. Additional Modules │ └── Funnels.md ├── 4. Tools and Applications ├── 0. Fast Withdrawals.md ├── 1. Token Minting.md ├── 2. Subscriptions.md └── 3. Non-Custodial Exchanges.md └── 5. Future Roadmap └── 1. Planned Features.md /.github/workflows/markdown_link_checker.yml: -------------------------------------------------------------------------------- 1 | name: Check Markdown links 2 | 3 | on: push 4 | 5 | jobs: 6 | markdown-link-check: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v2 11 | - name: Create config file 12 | run: | 13 | echo "{ \"replacementPatterns\": [ { \"pattern\": \"^/\", \"replacement\": \"/github/workspace/\" } ] }" > config.json 14 | - name: Check links 15 | uses: gaurav-nelson/github-action-markdown-link-check@1.0.4 16 | with: 17 | config-file: config.json 18 | 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | build/ 4 | .cache/ 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2020 Fuel Labs 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Fuel Docs 2 | === 3 | 4 | [![Community](https://img.shields.io/badge/chat%20on-discord-orange?&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/xfpK4Pe) 5 | 6 | A complete set of documentation for the Fuel-powered tools and services. 7 | 8 | ## Building From Source 9 | 10 | ### Install Dependencies 11 | 12 | ```bash 13 | npm install 14 | ``` 15 | 16 | ### Build 17 | 18 | ```bash 19 | npm run build 20 | ``` 21 | 22 | ### Start 23 | 24 | ```bash 25 | npm run start 26 | ``` 27 | -------------------------------------------------------------------------------- /assets/images/branding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/branding.png -------------------------------------------------------------------------------- /assets/images/fig_entering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_entering.png -------------------------------------------------------------------------------- /assets/images/fig_exiting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_exiting.png -------------------------------------------------------------------------------- /assets/images/fig_fuel_transactions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_fuel_transactions.png -------------------------------------------------------------------------------- /assets/images/fig_node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_node.png -------------------------------------------------------------------------------- /assets/images/fig_segwit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_segwit.png -------------------------------------------------------------------------------- /assets/images/fig_send.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_send.png -------------------------------------------------------------------------------- /assets/images/fig_structs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_structs.png -------------------------------------------------------------------------------- /assets/images/fig_subscription.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_subscription.png -------------------------------------------------------------------------------- /assets/images/fig_swaps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_swaps.png -------------------------------------------------------------------------------- /assets/images/fig_token_minting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_token_minting.png -------------------------------------------------------------------------------- /assets/images/fig_tx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_tx.png -------------------------------------------------------------------------------- /assets/images/fig_witnesses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/assets/images/fig_witnesses.png -------------------------------------------------------------------------------- /config/build.js: -------------------------------------------------------------------------------- 1 | const {list, tree, normalize, title} = require('./files'); 2 | const path = require('path'); 3 | const fs = require('fs').promises; 4 | const fse = require('fs-extra'); 5 | const showdown = require('showdown'); 6 | const {markdownToTxt} = require('markdown-to-txt'); 7 | 8 | // Replace .md with .html 9 | const replaceLinksExt = { 10 | type: 'lang', 11 | regex: /\[(.+?)\]\((.+?)\.md\)/g, 12 | replace: '[$1]($2.html)', 13 | }; 14 | showdown.extension('replace-md-links', replaceLinksExt); 15 | 16 | // Remove "#. " prefix 17 | const removePrefixExt = { 18 | type: 'lang', 19 | regex: /(\/|\]\()[0-9]+\.((%20)| )/g, 20 | replace: '$1', 21 | }; 22 | showdown.extension('prefix-md-links', removePrefixExt); 23 | 24 | // Make external links open in new tab 25 | const targetLinksExt = { 26 | type: 'html', 27 | regex: /(]*?\s+)?href=["']http.*?["'])/g, 28 | replace: '$1 target="_blank" rel="noopener noreferrer"', 29 | }; 30 | showdown.extension('target-links', targetLinksExt); 31 | 32 | const converter = new showdown.Converter({ 33 | tables: true, 34 | extensions: [ 35 | 'replace-md-links', 36 | 'prefix-md-links', 37 | 'target-links', 38 | ], 39 | }); 40 | 41 | const src = './src/'; 42 | const dist = './dist/'; 43 | const build = './build/'; 44 | const index = './build/index.html'; 45 | const assets = './assets/'; 46 | 47 | const treeToPanel = _tree => 48 | _tree 49 | .map( 50 | v => v.children.length ? 51 | `

${ 52 | title(v.name)}

${ 53 | treeToPanel(v.children)}
` : 54 | `${ 55 | title(v.name)}`) 56 | .join(''); 57 | 58 | const filterVersion = (_tree, version = 'v1.0.0') => 59 | _tree.filter(v => v.name === version)[0].children; 60 | 61 | (async () => { 62 | let indexFile = false; 63 | const arr = list(src); 64 | const arrFiles = JSON.stringify(arr); 65 | const header = await fs.readFile(index, 'utf8'); 66 | const panel = treeToPanel(filterVersion(tree(src))); 67 | 68 | await fse.remove(dist); 69 | 70 | // copy assets over 71 | await fse.copy(assets, path.join(dist, 'assets')); 72 | 73 | // copy parcel build over 74 | for (const file of list(build)) { 75 | await fse.copy(path.join(build, file), path.join(dist, file)); 76 | } 77 | 78 | // build markdown 79 | var i = 0; 80 | for (const file of arr) { 81 | const content = await fs.readFile(path.join(src, file), 'utf8'); 82 | const html = 83 | header.replace('\'%%files%%\'', arrFiles) 84 | .replace('"%%files%%"', arrFiles) 85 | .replace('%%file%%', file) 86 | .replace('%%showBack%%', arr[i - 1] ? 'show-back' : 'hide-back') 87 | .replace('%%backTitle%%', title(arr[i - 1] || '')) 88 | .replace('%%back%%', normalize(arr[i - 1] || '')) 89 | .replace('%%nextTitle%%', title(arr[i + 1] || arr[0])) 90 | .replace('%%next%%', normalize(arr[i + 1] || arr[0])) 91 | .replace('%%title%%', title(file)) 92 | .replace('%%content%%', converter.makeHtml(content)) 93 | .replace('%%panel%%', panel); 94 | await fse.outputFile(path.join(dist, normalize(file)), html); 95 | await fse.outputFile( 96 | path.join(dist, normalize(file) + '.md'), markdownToTxt(content)); 97 | 98 | if (!indexFile) { 99 | await fse.outputFile(path.join(dist, 'index.html'), html); 100 | indexFile = true; 101 | } 102 | i++; 103 | } 104 | })(); 105 | -------------------------------------------------------------------------------- /config/files.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs") 2 | const path = require("path") 3 | 4 | const list = function(dirPath = "", arrayOfFiles = []) { 5 | files = fs.readdirSync(dirPath) 6 | 7 | arrayOfFiles = arrayOfFiles || []; 8 | 9 | files.forEach(function(file) { 10 | if (fs.statSync(dirPath + "/" + file).isDirectory()) { 11 | arrayOfFiles = list(dirPath + "/" + file, arrayOfFiles) 12 | } else { 13 | arrayOfFiles.push(path.join(dirPath.split('/').slice(2).join('/'), "/", file)) 14 | } 15 | }); 16 | 17 | return arrayOfFiles; 18 | } 19 | 20 | function tree(list = []) { 21 | let result = []; 22 | let level = {result}; 23 | 24 | list.forEach(path => { 25 | path.slice(1).split('/').reduce((r, name, i, a) => { 26 | if(!r[name]) { 27 | r[name] = { result: [] }; 28 | r.result.push({ name, path, children: r[name].result }); 29 | } 30 | return r[name]; 31 | }, level) 32 | }); 33 | 34 | return result; 35 | } 36 | 37 | function is_numeric(str){ 38 | return /^\d+$/.test(str); 39 | } 40 | 41 | const normalize = file => file 42 | .split('/') 43 | .map(v => (is_numeric(v[0]) ? v.slice(v.indexOf('.') + 2) : v)) 44 | .join('/') 45 | .replace('&', 'and') 46 | .replace('.md', '.html'); 47 | 48 | const title = file => normalize(file.split('/').pop()) 49 | .trim() 50 | .replace('.md', '') 51 | .replace('.html', ''); 52 | 53 | module.exports = { 54 | tree: src => tree(list(src)), 55 | list, 56 | normalize, 57 | title, 58 | }; 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fuel-docs", 3 | "version": "1.0.0", 4 | "description": "The Fuel documentation.", 5 | "main": "config/build.js", 6 | "scripts": { 7 | "start": "npm run build && http-server dist --cors", 8 | "build": "parcel build public/index.html --out-dir build && node config/build", 9 | "publish": "npm run build && now dist && now alias https://dist.fuellabs.now.sh docs.fuel.sh", 10 | "publish-staging": "npm run build && now dist && now alias https://dist.fuellabs.now.sh docs.staging.fuel.sh", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/FuelLabs/docs.git" 16 | }, 17 | "keywords": [ 18 | "fuel", 19 | "docs", 20 | "documentation" 21 | ], 22 | "author": "Nick Dodson ", 23 | "license": "Apache-2.0", 24 | "bugs": { 25 | "url": "https://github.com/FuelLabs/docs/issues" 26 | }, 27 | "homepage": "https://github.com/FuelLabs/docs#readme", 28 | "dependencies": { 29 | "copy-text-to-clipboard": "^2.2.0", 30 | "fs-extra": "^9.0.1", 31 | "markdown-to-txt": "^1.0.1", 32 | "hyperapp": "^2.0.4", 33 | "esm-import-regex": "1.0.0", 34 | "hyperapp-styled-components": "^0.1.2", 35 | "showdown": "^1.9.1", 36 | "regenerator-runtime": "^0.13.5" 37 | }, 38 | "devDependencies": { 39 | "cssnano": "^4.1.10", 40 | "http-server": "^0.12.3", 41 | "parcel": "^1.12.4" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /public/arrow-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /public/arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /public/discord.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /public/dracula.css: -------------------------------------------------------------------------------- 1 | /* Dracula Theme v1.2.5 2 | * 3 | * https://github.com/dracula/highlightjs 4 | * 5 | * Copyright 2016-present, All rights reserved 6 | * 7 | * Code licensed under the MIT license 8 | * 9 | * @author Denis Ciccale 10 | * @author Zeno Rocha 11 | */ 12 | 13 | .hljs { 14 | display: block; 15 | overflow-x: auto; 16 | padding: 0.5em; 17 | background: #282a36; 18 | } 19 | 20 | .hljs-built_in, 21 | .hljs-selector-tag, 22 | .hljs-section, 23 | .hljs-link { 24 | color: #8be9fd; 25 | } 26 | 27 | .hljs-keyword { 28 | color: #ff79c6; 29 | } 30 | 31 | .hljs, 32 | .hljs-subst { 33 | color: #f8f8f2; 34 | } 35 | 36 | .hljs-title { 37 | color: #50fa7b; 38 | } 39 | 40 | .hljs-string, 41 | .hljs-meta, 42 | .hljs-name, 43 | .hljs-type, 44 | .hljs-attr, 45 | .hljs-symbol, 46 | .hljs-bullet, 47 | .hljs-addition, 48 | .hljs-variable, 49 | .hljs-template-tag, 50 | .hljs-template-variable { 51 | color: #f1fa8c; 52 | } 53 | 54 | .hljs-comment, 55 | .hljs-quote, 56 | .hljs-deletion { 57 | color: #6272a4; 58 | } 59 | 60 | .hljs-keyword, 61 | .hljs-selector-tag, 62 | .hljs-literal, 63 | .hljs-title, 64 | .hljs-section, 65 | .hljs-doctag, 66 | .hljs-type, 67 | .hljs-name, 68 | .hljs-strong { 69 | font-weight: bold; 70 | } 71 | 72 | .hljs-literal, 73 | .hljs-number { 74 | color: #bd93f9; 75 | } 76 | 77 | .hljs-emphasis { 78 | font-style: italic; 79 | } 80 | -------------------------------------------------------------------------------- /public/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FuelLabs/docs/2e6a69b4e3e98b11540af642c044466b074f83a2/public/favicon.png -------------------------------------------------------------------------------- /public/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji; 3 | font-size: 13px; 4 | font-weight: 300; 5 | color: #26282A; 6 | padding-top: 85px; 7 | } 8 | 9 | .group { 10 | margin-bottom: 7px; 11 | } 12 | 13 | .next-flip { 14 | transform: scaleX(-1); 15 | } 16 | 17 | .group h2 a { 18 | font-weight: 300; 19 | color: #69737d; 20 | margin-bottom: 0px!important; 21 | cursor: pointer; 22 | text-decoration: none; 23 | margin-block-end: unset; 24 | z-index: 10000; 25 | } 26 | 27 | /* 28 | pre { 29 | display: inline-block; 30 | border-radius: 6px; 31 | margin: 0px!important; 32 | width: 100%!important; 33 | } 34 | 35 | pre code { 36 | border-radius: 6px; 37 | font-size: 13.6px!important; 38 | padding: 20px!important; 39 | background: #F1F1F1!important; 40 | } 41 | */ 42 | 43 | pre { 44 | background: rgb(40, 44, 52) !important; 45 | border-radius: 5px!important; 46 | font-family: Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace!important; 47 | font-size: 1em!important; 48 | font-weight: normal!important; 49 | font-size:13.6px!important; 50 | line-height: 1.4!important; 51 | } 52 | 53 | summary { 54 | outline: none; 55 | cursor: pointer; 56 | margin-bottom: 10px; 57 | } 58 | 59 | code { 60 | border-radius: 3px; 61 | padding: 3px!important; 62 | display: inline-block; 63 | margin: 3px; 64 | font-size: 13.6px; 65 | line-height: normal!important; 66 | } 67 | 68 | code span { 69 | line-height: normal!important; 70 | } 71 | 72 | 73 | p code { 74 | line-height: 20px; 75 | font-size: 15px; 76 | background: #F1F1F1!important; 77 | padding-top: 0px!important; 78 | padding-bottom: 0px!important; 79 | } 80 | 81 | li code { 82 | line-height: 20px; 83 | font-size: 15px; 84 | background: #F1F1F1!important; 85 | padding-top: 0px!important; 86 | padding-bottom: 0px!important; 87 | } 88 | 89 | .group-header { 90 | font-size: 19px; 91 | margin-bottom: 20px; 92 | } 93 | 94 | .group-header .arrow { 95 | display: none; 96 | } 97 | 98 | .group-children { 99 | display: none; 100 | flex-direction: column; 101 | margin-left: 17px; 102 | margin-bottom: 10px; 103 | } 104 | 105 | .group-children a { 106 | color: #69737d; 107 | text-decoration: none; 108 | font-size: 15px; 109 | margin-bottom: 15px; 110 | font-weight: 300; 111 | cursor: pointer; 112 | } 113 | 114 | .group-children .group-children { 115 | margin-bottom: 0px; 116 | } 117 | 118 | .group-children .group { 119 | margin-bottom: 0px; 120 | } 121 | 122 | .group-children .group-header { 123 | margin-top: 0px !important; 124 | font-size: 15px !important; 125 | margin-bottom: 15px; 126 | display: flex; 127 | flex-direction: row; 128 | align-items: center; 129 | } 130 | 131 | .group-children .group-header .arrow { 132 | display: inline-block; 133 | } 134 | 135 | .group-children .group-header h2 a { 136 | font-size: 13px !important; 137 | } 138 | 139 | .arrow { 140 | width: 7px; 141 | height: 7px; 142 | margin-bottom: 2px; 143 | margin-right: 10px; 144 | } 145 | 146 | .arrow-turned { 147 | -webkit-transform: rotate(90deg); 148 | -moz-transform: rotate(90deg); 149 | -o-transform: rotate(90deg); 150 | -ms-transform: rotate(90deg); 151 | transform: rotate(90deg); 152 | } 153 | 154 | .group-open { 155 | display: flex; 156 | } 157 | 158 | .group-now .group-children a { 159 | color: #69737D; 160 | } 161 | 162 | .group-now .group-children a { 163 | color: #69737D; 164 | } 165 | 166 | .link-open .dot { 167 | background: #69737D; 168 | } 169 | 170 | .group-now h2 a { 171 | color: #69737D !important; 172 | } 173 | 174 | .link-open { 175 | color: #26282a !important; 176 | font-weight: 600 !important; 177 | } 178 | 179 | #container { 180 | } 181 | 182 | #docs { 183 | display: flex; 184 | flex-direction: row; 185 | flex: 1; 186 | } 187 | 188 | #panel-wrapper { 189 | position: fixed; 190 | left: 0px; 191 | top: 0px; 192 | bottom: 0px; 193 | min-width: 270px; 194 | margin-left: 12.5%; 195 | overflow: hidden; 196 | overflow: scroll; 197 | z-index: 100000; 198 | } 199 | 200 | #panel-wrapper::-webkit-scrollbar { 201 | display: none; 202 | } 203 | 204 | .group-header a { 205 | cursor: pointer!important; 206 | } 207 | 208 | .group-header a:hover { 209 | } 210 | 211 | #panel-wrapper .group-header a { 212 | transition: color 0.2s ease-out; 213 | } 214 | 215 | #panel-wrapper .link-not-open { 216 | transition: color 0.2s ease-out; 217 | } 218 | 219 | #panel-wrapper #search { 220 | transition: border-color 0.2s ease-out; 221 | } 222 | 223 | #panel-wrapper:hover .group-header a { 224 | color: #69737d!important; 225 | } 226 | 227 | #panel-wrapper:hover .link-not-open { 228 | color: #69737d!important; 229 | } 230 | 231 | #panel-wrapper:hover #search { 232 | border-color: #e8e8e8!important; 233 | } 234 | 235 | .dot { 236 | display: inline-block; 237 | width: 4px; 238 | height: 4px; 239 | background: #69737d; 240 | border-radius: 50%; 241 | margin-bottom: 4px; 242 | margin-right: 10px; 243 | } 244 | 245 | #panel { 246 | margin-left: 20px; 247 | min-width: 270px; 248 | margin-top: 68px; 249 | z-index: 1000; 250 | font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji; 251 | } 252 | 253 | #panel-header { 254 | display: flex; 255 | flex-direction: row; 256 | justify-content: space-between; 257 | } 258 | 259 | #panel-header a { 260 | color: #45DBB7; 261 | font-weight: 300; 262 | margin-right: 20px; 263 | text-decoration: none; 264 | } 265 | 266 | #search { 267 | border: 1px solid #F1F1F1; 268 | border-radius: 5px; 269 | padding: 7px; 270 | padding-left: 18px; 271 | outline: none; 272 | } 273 | 274 | #search::-webkit-input-placeholder { 275 | /* Chrome/Opera/Safari */ 276 | transition: color 0.2s ease-out; 277 | color: #69737d !important; 278 | font-weight: 200; 279 | } 280 | #search:-moz-placeholder { 281 | /* Firefox 18- */ 282 | transition: color 0.2s ease-out; 283 | color: #69737d !important; 284 | font-weight: 200; 285 | } 286 | 287 | #search-wrapper { 288 | position: relative; 289 | } 290 | 291 | #search-wrapper img { 292 | position: absolute; 293 | height: 13px; 294 | width: 13px; 295 | right: 9px; 296 | top: 9px; 297 | } 298 | 299 | #version { 300 | border: 1px solid #F1F1F1; 301 | margin-top: 20px; 302 | border-radius: 5px; 303 | padding: 7px; 304 | outline: none; 305 | color: #69737d !important; 306 | text-decoration: none; 307 | max-width: 50px; 308 | } 309 | 310 | #content-wrapper { 311 | z-index: 1000; 312 | display: flex; 313 | flex-direction: row; 314 | justify-content: center; 315 | width: 100vw; 316 | margin-left: 250px; 317 | margin-top: 40px; 318 | } 319 | 320 | #content { 321 | width: 50vw; 322 | font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji; 323 | font-size: 16px; 324 | line-height: 2.1; 325 | } 326 | 327 | 328 | #content b { 329 | display: inline-block; 330 | font-weight: 700; 331 | } 332 | 333 | #content img { 334 | max-width: 100%; 335 | } 336 | 337 | #content h1 { 338 | display: inline-block; 339 | font-weight: 600; 340 | font-size: 3em; 341 | position: relative; 342 | z-index: 100000; 343 | padding-left: 30px; 344 | margin-left: -30px; 345 | overflow: visible; 346 | cursor: pointer; 347 | margin: 0px!important; 348 | padding-left: 0px!important; 349 | } 350 | 351 | #content h2 { 352 | font-weight: 600; 353 | font-size: 2em; 354 | margin-top: 40px; 355 | padding-bottom: 0px; 356 | margin-bottom: 20px; 357 | border-bottom: 1px solid #F1F1F1; 358 | cursor: pointer; 359 | } 360 | 361 | #content strong { 362 | font-weight: 500; 363 | } 364 | 365 | #content li p { 366 | margin-top: 0px; 367 | margin-bottom: 0px; 368 | } 369 | 370 | #content h4 { 371 | font-weight: 600; 372 | font-size: 1.5em; 373 | cursor: pointer; 374 | margin-bottom: 20px; 375 | } 376 | 377 | #content h5 { 378 | font-weight: 600; 379 | font-size: 1.5em; 380 | cursor: pointer; 381 | margin-bottom: 10px; 382 | } 383 | 384 | .search-item { 385 | margin-bottom: 40px; 386 | padding-bottom: 40px; 387 | border-bottom: 1px solid #F1F1F1; 388 | } 389 | 390 | #content p { 391 | line-height: 2.1; 392 | margin-bottom: 20px; 393 | } 394 | 395 | #content a { 396 | text-decoration: none; 397 | font-weight: 600; 398 | color: #029a78!important; 399 | } 400 | 401 | #content a:hover { 402 | text-decoration: underline; 403 | } 404 | 405 | #content table { 406 | border-collapse: collapse; 407 | font-size: 13px; 408 | } 409 | 410 | #content table, th, td { 411 | border: 1px solid #F1F1F1; 412 | padding: 10px; 413 | font-size: 13px; 414 | } 415 | 416 | #content a { 417 | color: #029a78; 418 | } 419 | 420 | #header { 421 | position: fixed; 422 | left: 0px; 423 | right: 0px; 424 | top: 0px; 425 | display: flex; 426 | flex-direction: row; 427 | justify-content: space-between; 428 | align-items: center; 429 | padding-left: 15%; 430 | padding-right: 15%; 431 | padding-top: 68px; 432 | height: 60px; 433 | z-index: 100000; 434 | transition: background-color 0.1s ease-in; 435 | transition: top 0.1s ease; 436 | background: #FFF; 437 | } 438 | 439 | .scroll-up { 440 | top: 0px!important; 441 | } 442 | 443 | .scroll-down { 444 | top: -200px!important; 445 | } 446 | 447 | #nav { 448 | display: flex; 449 | flex-direction: row; 450 | justify-content: flex-end; 451 | align-items: center; 452 | } 453 | 454 | .nav-break { 455 | width: 1px; 456 | height: 32px; 457 | background: #a6b3bc; 458 | margin-left: 15px; 459 | } 460 | 461 | #nav a img { 462 | height: 24px; 463 | width: 24px; 464 | } 465 | 466 | #nav a { 467 | margin-left: 30px; 468 | color: #69737d; 469 | font-size: 18px; 470 | font-weight: 500; 471 | text-decoration: none; 472 | transition: color 0.2s ease; 473 | } 474 | 475 | .social-first { 476 | margin-left: 15px!important; 477 | } 478 | 479 | .nav-hover:hover { 480 | color: #000!important; 481 | } 482 | 483 | .nav-docs { 484 | font-weight: 600; 485 | margin-right: 20px; 486 | position: relative; 487 | } 488 | 489 | .nav-docs-bottom { 490 | position: absolute; 491 | display: inline-block; 492 | z-index: 100000; 493 | height: 2px; 494 | min-width: 45px; 495 | top: 30px; 496 | background: #000; 497 | left: 0px; 498 | } 499 | 500 | #nav a.nav-open { 501 | color: #26282a!important; 502 | } 503 | 504 | #nav:hover a.nav-open { 505 | color: #26282a!important; 506 | } 507 | 508 | .logo { 509 | display: flex; 510 | flex-direction: row; 511 | align-items: center; 512 | font-size: 17px; 513 | color: #26282A; 514 | font-weight: 600; 515 | text-decoration: none !important; 516 | margin-bottom: 30px; 517 | max-width: 53px; 518 | } 519 | 520 | .logo span { 521 | margin-left: 8px; 522 | font-size: 40px; 523 | font-weight: 600; 524 | font-stretch: normal; 525 | font-style: italic; 526 | line-height: 1.4; 527 | color: #04c399; 528 | } 529 | 530 | .logo-closed { 531 | display: none!important; 532 | opacity: 0; 533 | visibility: hidden; 534 | } 535 | 536 | .logo img { 537 | max-width: 53px; 538 | height: auto; 539 | margin-right: 10px; 540 | } 541 | 542 | .header-logo { 543 | margin-top: 10px; 544 | display: none!important; 545 | max-width: 40px; 546 | } 547 | 548 | #bottom { 549 | display: flex; 550 | flex-direction: row; 551 | justify-content: space-between; 552 | } 553 | 554 | #edit-wrapper { 555 | margin-top: 40px; 556 | } 557 | 558 | #edit-wrapper a { 559 | color: #69737d!important; 560 | } 561 | 562 | #edit { 563 | font-weight: 200; 564 | font-size: 15px; 565 | color: #69737d!important; 566 | text-decoration: none !important; 567 | min-width: 100px; 568 | } 569 | 570 | #edit:hover { 571 | text-decoration: underline !important; 572 | } 573 | 574 | #edit img { 575 | margin-left: 6px; 576 | width: 8px; 577 | height: 8px; 578 | } 579 | 580 | .show-back { 581 | display: inline-inline; 582 | } 583 | 584 | .hide-back { 585 | display: none!important; 586 | } 587 | 588 | .next-back { 589 | text-align: right!important; 590 | } 591 | 592 | .next-back div img { 593 | margin-right: 20px!important; 594 | } 595 | 596 | #next { 597 | text-align: left; 598 | font-weight: 200; 599 | font-size: 15px; 600 | font-size: 17px; 601 | font-weight: 300; 602 | text-decoration: none !important; 603 | margin-top: 40px; 604 | margin-bottom: 40px; 605 | } 606 | 607 | #next div { 608 | color: #26282a!important; 609 | font-weight: 200!important; 610 | display: flex; 611 | flex-direction: row; 612 | align-items: center; 613 | } 614 | 615 | #next div img { 616 | height: 17px; 617 | margin-left: 20px; 618 | width: auto; 619 | } 620 | 621 | #next:hover { 622 | text-decoration: none !important; 623 | } 624 | 625 | #next span { 626 | font-weight: 200!important; 627 | font-size: 13px; 628 | color: #69737d; 629 | } 630 | 631 | .next-first { 632 | display: flex !important; 633 | } 634 | 635 | .next-second { 636 | display: none !important; 637 | } 638 | 639 | #toggle { 640 | display: none; 641 | } 642 | 643 | @media only screen and (max-width: 1200px) { 644 | #edit { 645 | display: none; 646 | } 647 | 648 | #header { 649 | padding-right: 8%; 650 | height: 80px; 651 | } 652 | 653 | #next { 654 | display: inline-block; 655 | position: static!important; 656 | margin-top: 40px; 657 | top: 40px; 658 | } 659 | 660 | #panel-wrapper { 661 | margin-left: 150px; 662 | } 663 | 664 | #content-wrapper { 665 | margin-left: 350px; 666 | } 667 | } 668 | 669 | @media only screen and (max-width: 1024px) { 670 | 671 | html, body { 672 | max-width: 100%; 673 | overflow-x: hidden; 674 | } 675 | 676 | #next span { 677 | display: none; 678 | } 679 | 680 | .next-first { 681 | display: none !important; 682 | } 683 | 684 | .next-second { 685 | display: flex !important; 686 | } 687 | 688 | #header { 689 | padding-top: 30; 690 | padding-left: 5%; 691 | padding-right: 5%; 692 | } 693 | 694 | #panel-wrapper a { 695 | font-size: 19px; 696 | } 697 | 698 | #search-wrapper { 699 | width: 100%; 700 | } 701 | 702 | #version { 703 | font-size: 19px; 704 | min-width: 80px; 705 | } 706 | 707 | #search { 708 | width: 100%; 709 | border-style: solid; 710 | font-size: 19px; 711 | margin-bottom: 20px; 712 | border-style: solid; 713 | } 714 | 715 | #search-wrapper img { 716 | width: 19px; 717 | height: 19px; 718 | } 719 | 720 | #panel-wrapper h2 a { 721 | cursor: default; 722 | pointer-events: none; 723 | } 724 | 725 | .group-header a { 726 | color: #69737d!important; 727 | } 728 | 729 | #panel-wrapper .link-not-open { 730 | color: #69737d!important; 731 | } 732 | 733 | .header-logo { 734 | display: flex!important; 735 | margin-bottom: 0px; 736 | } 737 | 738 | #panel-wrapper { 739 | display: none; 740 | right: 0px; 741 | margin-top: 20px; 742 | min-width: 85vw; 743 | border-right: none; 744 | margin-left: 0px; 745 | padding-right: 10%; 746 | overflow-x: hidden; 747 | } 748 | 749 | .logo-panel { 750 | margin-top: 10px; 751 | } 752 | 753 | #panel { 754 | min-width: 100%; 755 | margin-top: 20px; 756 | padding-left: 5%; 757 | padding-right: 6%; 758 | margin-left: 0px; 759 | overflow-x: hidden; 760 | } 761 | 762 | .panel-open { 763 | display: block!important; 764 | } 765 | 766 | .panel-closed { 767 | display: none!important; 768 | } 769 | 770 | #content { 771 | width: 90vw; 772 | } 773 | 774 | #content img { 775 | max-width: 80vw; 776 | } 777 | 778 | #content-wrapper { 779 | margin-left: 0px; 780 | } 781 | 782 | #toggle { 783 | display: block !important; 784 | } 785 | 786 | .nav-break { 787 | display: none; 788 | } 789 | 790 | .scroll-down { 791 | top: 0px!important; 792 | } 793 | 794 | #nav a { 795 | display: none !important; 796 | } 797 | } 798 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Fuel | Docs - %%title%% 8 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 104 | 105 |
106 | 127 | 128 |
129 |
130 |
131 | 132 |
133 | 157 |
158 |
159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /public/index.js: -------------------------------------------------------------------------------- 1 | import "regenerator-runtime"; 2 | import { h, app } from 'hyperapp'; 3 | import styled from 'hyperapp-styled-components'; 4 | import importRegex from 'esm-import-regex'; 5 | 6 | window.importRegex = importRegex; 7 | window.rinkebyTx = 'https://rinkeby.fuel.sh/tx/'; 8 | 9 | function linkify(text) { 10 | var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig; 11 | return text.replace(urlRegex, function(url) { 12 | return '' + url + ''; 13 | }); 14 | } 15 | 16 | window.consoleLog = (...args) => { 17 | document.getElementById('run-console').innerHTML += ` 18 |
${args.map((arg) => { 19 | try { 20 | if (typeof arg === 'object') { 21 | return JSON.stringify(arg, null, 2); 22 | } 23 | 24 | return linkify(arg); 25 | } catch (err) { 26 | return linkify(arg); 27 | } 28 | }).join('')}
29 | `; 30 | }; 31 | 32 | window.consoleError = (...args) => { 33 | document.getElementById('run-console').innerHTML += ` 34 |
${args.join('')}
35 | `; 36 | }; 37 | 38 | function is_numeric(str){ 39 | return /^\d+$/.test(str); 40 | } 41 | 42 | const normalize = file => file 43 | .split('/') 44 | .map(v => (is_numeric(v[0]) ? v.slice(v.indexOf('.') + 2) : v)) 45 | .join('/') 46 | .replace('&', 'and') 47 | .replace('.md', '.html'); 48 | 49 | const title = file => normalize(file.split('/').pop()) 50 | .trim() 51 | .replace('.md', '') 52 | .replace('.html', ''); 53 | 54 | 55 | function tree(list = []) { 56 | let result = []; 57 | let level = {result}; 58 | 59 | list.forEach(path => { 60 | path.slice(1).split('/').reduce((r, name, i, a) => { 61 | if(!r[name]) { 62 | r[name] = { result: [] }; 63 | r.result.push({ name, dir: normalize(path.slice(1).split('/').slice(0, i + 1).join('/')), path, children: r[name].result }); 64 | } 65 | return r[name]; 66 | }, level) 67 | }); 68 | 69 | return result; 70 | } 71 | 72 | const isOpen = (path, dir) => path.split('%20').join(' ').indexOf(dir) !== -1; 73 | 74 | // TODO if there's a space in the hierarchy then this doesn't work properly 75 | const arrow = require('./arrow.svg'); 76 | const arrowDark = require('./arrow-dark.svg'); 77 | 78 | const treeToPanel2 = (_tree, state = {}) => _tree 79 | .map(v => v.children.length 80 | ? (
81 |

({ ...state, open: v.dir })}> 82 | 83 | 86 | {title(v.name)} 87 | 88 |

89 |
{treeToPanel2(v.children, state)}
92 |
) 93 | : ( 100 | {title(v.name)} 101 | )); 102 | 103 | /* 104 | 105 | 106 | 107 | 108 | hljs.initHighlightingOnLoad(); 109 | 110 | 112 | 113 | document 114 | .getElementById('search') 115 | .addEventListener("keyup", event => { 116 | event.preventDefault(); 117 | if (event.keyCode === 13) { 118 | search(event.target.value); 119 | } 120 | }); 121 | */ 122 | 123 | const filterVersion = (_tree, version = 'v1.0.0') => _tree.filter(v => v.name === version)[0].children; 124 | 125 | // TODO fix search 126 | function search(pattern) { 127 | document.getElementById('content').innerHTML = '

Search Results

'; 128 | 129 | for (const file of window.files.map(normalize)) { 130 | window.axios.get('https://docs.fuel.sh' + file + '.md') 131 | .then(function (response) { 132 | 133 | const fuse = new Fuse([{ 134 | title: response.config.url, 135 | content: response.data, 136 | }], { 137 | keys: [ 138 | "title", 139 | "content", 140 | ], 141 | }); 142 | 143 | let result = fuse.search(pattern); 144 | const clean = v => v.replace('https://docs.fuel.sh/v1.0.0/', '') 145 | .split('__').join(': ').split('_').join(' '); 146 | 147 | if (result.length === 0 && response.data.indexOf(pattern) !== -1) { 148 | result.push({ item: { 149 | title: response.config.url, 150 | content: response.data, 151 | }}); 152 | } 153 | 154 | if (result.length) { 155 | result.map(({ item }) => { 156 | const itemHTML = ` 157 | 167 | `; 168 | 169 | document.getElementById('content').innerHTML += itemHTML; 170 | }); 171 | } 172 | }) 173 | .catch(function (error) { 174 | // handle error 175 | console.log(error); 176 | }); 177 | } 178 | } 179 | 180 | const editIcon = require('./edit.svg'); 181 | const searchIcon = require('./search.svg'); 182 | const searchIconLight = require('./search-gray.svg'); 183 | const logo = require('./logo.svg'); 184 | 185 | const view = state => ( 186 |
187 | 191 |
192 |
193 | { 194 | event.preventDefault(); 195 | if (event.keyCode === 13) { 196 | search(event.target.value); 197 | } 198 | return state; 199 | }} onkeypress={(state, event) => { 200 | if (event.keyCode === 13) { 201 | search(event.target.value); 202 | } 203 | }} /> 204 | 205 |
206 |
207 | {treeToPanel2(filterVersion(tree(window.files)), state)} 208 |
v 1.0.0
209 |
210 | ); 211 | 212 | const start = window.location.pathname === '/' 213 | ? '/v1.0.0/Introduction/Welcome.html' 214 | : window.location.pathname; 215 | 216 | app({ 217 | init: { 218 | started: false, 219 | open: start, 220 | pathname: start, 221 | }, 222 | view, 223 | subscriptions: state => [], 224 | node: document.getElementById('panel'), 225 | }); 226 | -------------------------------------------------------------------------------- /public/logo-old.svg: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /public/next.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /public/open-menu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/search-gray.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/v1.0.0/1. Introduction/1. Welcome.md: -------------------------------------------------------------------------------- 1 | Welcome 2 | === 3 | 4 | **Before we begin:** 5 | 6 | Try out our live interactive [🕹️ Fuel Plays Pokémon demo](https://fuelplayspokemon.com)! 7 | 8 | Check out the [⚡ Block Explorer](https://rinkeby.fuel.sh/network). 9 | 10 | Use the one-click [💻 Wallet SDK Example](../2.%20Getting%20Started/1.%20One-Click%20Example.md). 11 | 12 | We are always available to... [![Community](/assets/images/discord.svg)](https://discord.gg/xfpK4Pe) 13 | 14 | Introduction 15 | --- 16 | 17 | Fuel is a permissionless and trustless layer-2 protocol for Ethereum, targeted at low-cost high-throughput value-transfer transactions. Fuel is powered by a highly-optimized _optimistic rollup design_. 18 | 19 | Fuel's Features 20 | --- 21 | 22 | - Completely decentralized: non-custodial, censorship resistant, and permissionless 23 | - The most scalable optimistic rollup in the world, with unique UTXO-based design 24 | - 500 TPS maximum on-chain throughput (1,500-2,000 with BLS aggregate signatures) 25 | - Up to 10,000 TPS surge intake capacity 26 | - Send and receive using any Ethereum address, no registration required 27 | - ETH and all ERC-20 tokens are supported 28 | - Non-custodial token swaps between any tokens 29 | - Fees can be paid in any token, not just ETH 30 | - HTLCs for cross-chain atomic swaps and additional usecases 31 | - Withdrawals in under 10 minutes using atomic swaps 32 | 33 | What Makes Fuel Different 34 | --- 35 | 36 | - UTXO-based design optimized for maximum scalability 37 | - Parallelism: transactions can be validated in parallel on consumer-grade hardware 38 | - No state bottleneck: unique fraud proof scheme doesn't require state serialization 39 | - No special key formats or on-chain account registration required 40 | - No upfront collateral requirements (unlike channels) 41 | - Permissionless and censorship-resistant (unlike Plasma/Validium) 42 | - No burdensome proof generation with high latency (unlike ZK rollups and Validium) 43 | - No exotic cryptography (unlike ZK rollups and Validium) 44 | - No trusted setup (unlike SNARK-based ZK rollups and Validium) 45 | - No worse-than-useless protocol-specific token (unlike...too many to count) 46 | - Care and attention to user-level issues 47 | - Can deposit using simple transfers from any account (including exchange accounts) using Funnel contracts 48 | - Can use a smart contract wallet to authorize transactions on Fuel 49 | 50 | What To Read Next? 51 | --- 52 | 53 | System benchmarks can be found [on the next page](2.%20Benchmarks.md). 54 | 55 | If you want to know more about the fundamentals of Fuel's architecture, our [Technical Fundamentals](./../3.%20Concepts/0.%20Fundamentals/1.%20Fuel%20Overview.md) is your next stop. A detailed analysis on the security and scalability of Fuel [is available](./../3.%20Concepts/0.%20Fundamentals/2.%20Security%20Analysis.md). 56 | 57 | If you're a developer and want to build on top of, or integrate with, Fuel, check out our [Getting Started](../2.%20Getting%20Started/0.%20Using%20the%20Wallet%20SDK.md) guide and [wallet SDK documentation](../2.%20SDK/1.%20Wallet.md). 58 | 59 | For examples of tools and applications that can built on top of Fuel, start [here](../4.%20Tools%20and%20Applications/1.%20Token%20Minting.md). 60 | 61 | Finally, our technical roadmap can be found [here](../5.%20Future%20Roadmap/1.%20Planned%20Features.md). 62 | -------------------------------------------------------------------------------- /src/v1.0.0/1. Introduction/2. Benchmarks.md: -------------------------------------------------------------------------------- 1 | Benchmarks 2 | === 3 | 4 | - [Simulations](#simulations) 5 | - [Running Locally](#running-locally) 6 | - [Benchmarks](#benchmarks) 7 | - [Fuel v1 on Ropsten](#fuel-v1-on-ropsten) 8 | - [Audits](#audits) 9 | 10 | Simulations 11 | --- 12 | 13 | Below are simulation results for Fuel [v1](../5.%20Future%20Roadmap/1.%20Planned%20Features.md), for a number of different representative usecases. Usecase-specific and context-sensitive optimizations _are not_ done, so these numbers are representative of normal usage. Such optimizations include batching multiple transactions from the same sender in the same rollup block to save space, or reducing the number of bits to represent token types to only handle a tiny number of tokens. 14 | 15 | ### Running Locally 16 | 17 | The simulation can be ran locally: 18 | 19 | ```bash 20 | git clone git@github.com:FuelLabs/fuel.git 21 | npm install 22 | npm run benchmark 23 | ``` 24 | 25 | **100k Transfers** 26 | 27 | Standard one-input two-output [transfers](../3.%20Concepts/0.%20Fundamentals/4.%20Transaction%20Architecture.md#simple-send-example). 28 | 29 | - Transactions Submitted: 100000 30 | - Roots committed: 360 31 | - Blocks committed: 3 32 | - Cumulative gas used: 185387356 33 | - Ethereum blocks used: 23 34 | - @100 Gwei: 18.539 ETH 35 | - @$300 USD / ETH: $5562 36 | 37 | **100k Token Minting** 38 | 39 | One-input eight-output [mass token minting transactions](../4.%20Tools%20and%20Applications/1.%20Token%20Minting.md). 40 | 41 | - Claims Processed: 100000 42 | - Transactions Submitted: 12500 43 | - Roots committed: 134 44 | - Blocks committed: 2 45 | - Cumulative gas used: 72457791 46 | - Ethereum blocks used: 9 47 | - @100 Gwei: 7.246 ETH 48 | - @$300 USD / ETH: $2174 49 | 50 | **75k Token Burns** 51 | 52 | One-input three-output (burn, memo, change). 53 | 54 | - Transactions Submitted: 75000 55 | - Roots committed: 275 56 | - Blocks committed: 3 57 | - Cumulative gas used: 140909433 58 | - Ethereum blocks used: 17.613679125 59 | - @100 Gwei: 14.091 ETH 60 | - @$300 USD / ETH: $4227 61 | 62 | **25k Subscriptions** 63 | 64 | One-input two-output. 65 | 66 | - Transactions Submitted: 25000 67 | - Roots committed: 87 68 | - Blocks committed: 1 69 | - Cumulative gas used: 45442233 70 | - Ethereum blocks used: 5 71 | - @100 Gwei: 4.544 ETH 72 | - @$300 USD / ETH: $1363 73 | 74 | Benchmarks 75 | --- 76 | 77 | Benchmarks use the same transaction types as the simulations above (i.e. they are representative of normal usage). 78 | 79 | ### Fuel v1 on Ropsten 80 | 81 | **100k Transfers** 82 | 83 | Contract deployed at [`0x57f51C778Dd66153A44881Cc5E6e9da421c4dC85`](https://ropsten.etherscan.io/address/0x57f51c778dd66153a44881cc5e6e9da421c4dc85). 84 | 85 | - Cumulative gas used: 225360000 86 | - @100 Gwei: 22.536 ETH 87 | - @$300 USD / ETH: $6761 88 | 89 | **100k Token Minting** 90 | 91 | Contract deployed at [`0x47b13755d14BCEFC49C0606Aca5E62Dc2C1Da9eC`](https://ropsten.etherscan.io/address/0x47b13755d14bcefc49c0606aca5e62dc2c1da9ec). 92 | 93 | - Cumulative gas used: 89184000 94 | - @100 Gwei: 8.918 ETH 95 | - @$300 USD / ETH: $2675 96 | 97 | **75k Token Burns** 98 | 99 | Contract deployed at [`0xf73788cD87267c68dA5ed3e3a37c4A610a07513d`](https://ropsten.etherscan.io/address/0xf73788cd87267c68da5ed3e3a37c4a610a07513d). 100 | 101 | - Cumulative gas used: 176400000 102 | - @100 Gwei: 17.640 ETH 103 | - @$300 USD / ETH: $5292 104 | 105 | **25k Subscriptions** 106 | 107 | Contract deployed at [`0x232113aaC91Bab5b6351016497f966dA8C1BfB9C`](https://ropsten.etherscan.io/address/0x232113aac91bab5b6351016497f966da8c1bfb9c). 108 | 109 | - Cumulative gas used: 56112000 110 | - @100 Gwei: 5.611 ETH 111 | - @$300 USD / ETH: $1683 112 | 113 | Audits 114 | --- 115 | 116 | - An audit with [Hashcloak](https://hashcloak.com) is currently underway. 117 | - An audit with [Trail of Bits](https://www.trailofbits.com) is scheduled. 118 | -------------------------------------------------------------------------------- /src/v1.0.0/1. Introduction/3. Use Cases.md: -------------------------------------------------------------------------------- 1 | Use Cases 2 | === 3 | 4 | In this section we explore various use cases for the Fuel [v1](../5.%20Future%20Roadmap/1.%20Planned%20Features.md#fuelv1) optimistic rollup. All the use cases covered below are examined in more detail in the [Tools and Applications](../4.%20Tools%20and%20Applications/0.%20Fast%20Withdrawals.md) section. 5 | 6 | Transfers 7 | --- 8 | 9 | Fuel can be used for high-performance, low-latency global transfers with any ERC-20 token or Ether. 10 | 11 | **This is ideal for:** 12 | - Global payment settlement 13 | - Application-specific tokens 14 | - Virtual gaming tokens and rewards 15 | - Any situations where users are transferring ERC-20 tokens 16 | 17 | Please see our interactive [🕹️ Fuel Plays Pokémon demo](https://fuelplayspokemon.com) for a live example of transfers in action. 18 | 19 | Non-Custodial Exchange 20 | --- 21 | 22 | Fuel's unique **multi-user transactions and HTLC support** are a perfect foundation for non-custodial exchanges. 23 | 24 | **We support two kinds of exchange:** 25 | - Multi-user on-Fuel swaps 26 | - Cross-chain atomic swap with HTLCs 27 | 28 | For further reading, please see [Non-Custodial Exchanges](../4.%20Tools%20and%20Applications/3.%20Non-Custodial%20Exchanges.md). 29 | 30 | Mass Token Dispersal 31 | --- 32 | 33 | Fuel supports multi-input, multi-output transactions, making it perfect for pre-signed mass token dispersal scenarios where a single account must disperse tokens to a large number of unique recipients cost-efficiently. 34 | 35 | This is possible on Fuel with a Merkleized dispersal pattern and our deterministic transaction identifiers, allowing dispersal transactions to be pre-signed and distributed off-chain. Tokens are only actually dispersed when claimed, greatly reducing overhead costs for unclaimed tokens. 36 | 37 | For further reading on how we accomplish this with low overheads, please see [Token Minting](../4.%20Tools%20and%20Applications/1.%20Token%20Minting.md) 38 | 39 | Fast Withdrawals 40 | --- 41 | 42 | Fuel allows for fast (~10 minute) withdrawals using our unique HTLC output. Liquidity providers on the intended exit chain (e.g. Ethereum or Bitcoin) can allow users on Fuel to withdraw with minimal effort and at low cost. 43 | 44 | For further reading, please see [Fast Withdrawals](../4.%20Tools%20and%20Applications/0.%20Fast%20Withdrawals.md). 45 | 46 | Subscriptions 47 | --- 48 | 49 | Fuel's pre-signed transaction format is ideal for creating regular financial subscriptions, where a user can *sign up* to a subscription, pre-signing a set of transactions, and then allowing any service or system to collect payment on a regular basis non-interactively. 50 | 51 | This is allows for cheap, care-free subscriptions for magazines, blogs, forums, and more. 52 | 53 | For further reading, please see [Subscriptions](../4.%20Tools%20and%20Applications/2.%20Subscriptions.md). 54 | 55 | Burning 56 | --- 57 | 58 | Fuel has a "return data" transaction output, which can be used to store arbitrary data in Fuel such as: burn metadata, social media messages, timestamped hashes, or specific application data. 59 | 60 | The burning of a token by sending it to the zero address can be associated with a specific event using the return data output, all within in the same transaction. 61 | -------------------------------------------------------------------------------- /src/v1.0.0/2. Getting Started/0. Using the Wallet SDK.md: -------------------------------------------------------------------------------- 1 | Using the Wallet SDK 2 | === 3 | 4 | [![npm version](https://badge.fury.io/js/%40fuel-js%2Fwallet.svg)](https://badge.fury.io/js/%40fuel-js%2Fwallet) 5 | 6 | The wallet is how users and developers can interact with Fuel. 7 | 8 | Install 9 | --- 10 | 11 | The Fuel module is currently available as a UMD through CDN or NPM. 12 | 13 | **node.js** 14 | 15 | ```bash 16 | npm install --save @fuel-js/wallet 17 | ``` 18 | 19 | **browser (UMD)** 20 | 21 | ```html 22 | 24 | ``` 25 | 26 | **browser (ESM)** 27 | 28 | ```html 29 | 32 | ``` 33 | 34 | Creating a Wallet 35 | --- 36 | The Fuel wallet can be used with or without a standard `web3` or `ethers` provider. The provider will be used for account signing or any Ethereum related actions, such as deposits and withdrawals. 37 | 38 | If an override `privateKey` is not specified, the first `account` given by the provider will be used. 39 | 40 | If an Ethereum `network` is not specified (e.g. `rinkeby`), it will be requested from the provider. 41 | 42 | ```js 43 | import fuel from '@fueljs/wallet'; 44 | 45 | // no provider, privateKey is generated 46 | const wallet = fuel.wallet(null); 47 | 48 | // web3 provider, first account used, network gathered from provider 49 | const wallet = fuel.wallet(window.web3.currentProvider); 50 | 51 | // provider with override privateKey and network specified 52 | const wallet = fuel.wallet(window.web3.currentProvider, { 53 | privateKey: fuel.utils.hexlify(fuel.utils.randomBytes(32)), 54 | network: 'rinkeby', 55 | }); 56 | ``` 57 | 58 | Fauceting 59 | --- 60 | 61 | All Fuel test networks have a token faucet that will dispense fake tokens to requesting accounts (within several seconds to minutes). 62 | 63 | The faucet will dispense `1000` `faucetTokens`. 64 | 65 | The faucet test token identifier will always be available in `fuel.contants.faucetToken`. 66 | 67 | ```js 68 | import fuel from '@fueljs/wallet'; 69 | 70 | // new wallet 71 | const wallet = fuel.wallet(null, { 72 | network: 'rinkeby', 73 | }); 74 | 75 | // faucet fake tokens 76 | await wallet.faucet(); 77 | 78 | // check your balance 79 | console.log('my balance: ', await wallet.balance(fuel.constants.faucetToken)); 80 | ``` 81 | 82 | 83 | Depositing 84 | --- 85 | 86 | You can deposit ERC-20 tokens or Ether into Fuel by using the `deposit` method. Simply specify the `token` and `amount` to deposit. Since Fuel uses Ethereum key pairs, this process can be done directly with your provided MetaMask account, for example. 87 | 88 | The `deposit` method will make two Ethereum transactions, depositing your funds into Fuel and making them accessible for Fuel activities (e.g. transfers and swaps). 89 | 90 | ```js 91 | import fuel from '@fuel-js/wallet'; 92 | 93 | const wallet = new fuel.Wallet(window.web3.currentProvider); 94 | 95 | (async () => { 96 | 97 | // rinkeby dai address 98 | const daiAddress = '0xc3dbf84Abb494ce5199D5d4D815b10EC29529ff8'; 99 | 100 | // deposit funds 101 | await wallet.deposit(daiAddress, fuel.utils.parseEther('1.0')); 102 | 103 | })(); 104 | ``` 105 | 106 | Transferring 107 | --- 108 | 109 | Now that you have funds in Fuel, either by `deposit` or `faucet` you can begin to transfer them around. 110 | 111 | Let's try transferring `1` Fuel token to our own wallet address and check the submission by its transaction ID. 112 | 113 | ```js 114 | import fuel from '@fuel-js/wallet'; 115 | 116 | const wallet = new fuel.Wallet(window.web3.currentProvider); 117 | 118 | (async () => { 119 | 120 | await wallet.faucet(); 121 | 122 | // transfer one faucet token to our own wallet 123 | const { transactionId } = await wallet.transfer( 124 | fuel.constants.faucetToken, 125 | wallet.address, 126 | fuel.utils.parseEther('1.0')); 127 | 128 | console.log('view my transaction: https://rinkeby.fuel.sh/tx/' + transactionId); 129 | 130 | })(); 131 | ``` 132 | 133 | Withdrawing 134 | --- 135 | 136 | Currently, the Fuel wallet only supports standard withdrawals, which means you will send an initial withdraw transaction on Fuel first, than release it after the finality delay of 1 week has expired. In the future, the wallet will support fast withdrawals via atomic swaps, where total withdraw time can be reduced safely to as little as 5-10 minutes. 137 | 138 | In order to release the tokens on Ethereum, you must have some Ether for the transaction. 139 | 140 | ```js 141 | import fuel from '@fuel-js/wallet'; 142 | 143 | const wallet = new fuel.Wallet(window.web3.currentProvider); 144 | 145 | (async () => { 146 | 147 | await wallet.faucet(); 148 | 149 | // withdraw one faucet token 150 | await wallet.withdraw(fuel.constants.faucetToken, utils.parseEther('1.0')); 151 | 152 | // wait one week... 153 | 154 | // release any withdrawals onto Ethereum 155 | await wallet.release(); 156 | })(); 157 | ``` 158 | -------------------------------------------------------------------------------- /src/v1.0.0/2. Getting Started/1. One-Click Example.md: -------------------------------------------------------------------------------- 1 | One-Click Example 2 | === 3 | 4 | Below is our one-click **Wallet SDK example** using the Fuel test faucet on *Rinkeby*. 5 | 6 | #### Try it out! 7 | 8 | 98 | 99 |
await import('https://unpkg.com/@fuel-js/wallet@latest/umd/fuel.umd.min.js'); 100 | 101 | // Create a new wallet with a new key 102 | // Tip: try setting `null` to `web3.currentProvider` to run with MetaMask 103 | const wallet = new fuel.Wallet(null, { 104 | network: 'rinkeby', 105 | }); 106 | 107 | // Get yourself some fake Moons 108 | await wallet.faucet(); 109 | 110 | // Establish faucet token id 111 | const faucetToken = fuel.constants.faucetToken; 112 | 113 | // Get your fake moons balance 114 | console.log('my balance: ', 115 | await wallet.balance(faucetToken, { format: 'ether' })); 116 | 117 | // Send yourself some faucet token 118 | const tx = await wallet.transfer(faucetToken, wallet.address, '4.5', { units: 'ether' }); 119 | 120 | // Checkout your transaction on the Block Explorer 121 | console.log('check out your tx: ' + window.rinkebyTx + tx.transactionId); 122 |
123 | 124 |
125 |
126 |
run
127 |
128 |
129 | 130 | 131 | 132 | 179 | -------------------------------------------------------------------------------- /src/v1.0.0/2. Getting Started/2. Running a Node.md: -------------------------------------------------------------------------------- 1 | Running a Node 2 | === 3 | 4 | [![npm version](https://badge.fury.io/js/%40fuel-js%2Fclient.svg)](https://badge.fury.io/js/%40fuel-js%2Fclient) 5 | 6 | The Fuel client can be used to sync with Fuel and fully validate the chain. 7 | 8 | Binary Releases 9 | --- 10 | 11 | Binary releases can be found at [https://github.com/FuelLabs/fuel-js/releases](https://github.com/FuelLabs/fuel-js/releases) 12 | 13 | Running from Command Line 14 | --- 15 | 16 | Download a release ([above](#releases)) and use an available network specifier and RPC endpoint to get started. 17 | 18 | ```bash 19 | fuel --network="rinkeby" --rpc="https://localhost:8545" 20 | ``` 21 | 22 | ### Additional Parameters 23 | 24 | ```bash 25 | ⚡ fuel [options] 26 | 27 | Options: 28 | 29 | -n, --network the ethereum network "rinkeby"; default "rinkeby" 30 | -r, --rpc a standard Ethereum RPC provider (i.e. local go-ethereum) 31 | -i, --infura an Infura service API key (--network must also be specified) 32 | -es, --etherscan an Etherscan service API key (--network must also be specified) 33 | -e, --environment use the environment variables to specify node parameters 34 | -o, --operators a comma-separated list or seed phrase of Ethereum private keys used for block, root, and fraud commitments 35 | 36 | Examples: 37 | 38 | $ fuel --network="ropsten" --rpc="http://localhost:8545" 39 | ``` 40 | 41 | Running from GUI 42 | --- 43 | 44 | Coming Soon™... 45 | -------------------------------------------------------------------------------- /src/v1.0.0/2. SDK/1. Wallet.md: -------------------------------------------------------------------------------- 1 | 2 | Wallet SDK 3 | === 4 | 5 | [![npm version](https://badge.fury.io/js/%40fuel-js%2Fwallet.svg)](https://badge.fury.io/js/%40fuel-js%2Fwallet) 6 | 7 | new 8 | --- 9 | 10 | **new _fuel_ . Wallet** ( provider [, options ] ) 11 | 12 | ### Installation 13 | **node.js** 14 | 15 | ```bash 16 | npm install --save @fuel-js/wallet 17 | ``` 18 | 19 | **browser (UMD)** 20 | 21 | ```html 22 | 24 | ``` 25 | 26 | **browser (ESM)** 27 | 28 | ```html 29 | 32 | ``` 33 | 34 | ### Usage 35 | ```js 36 | import fuel from '@fuel-js/wallet'; 37 | 38 | // use the window provider key / account / eth_signTypedData_v4 for transaction signing 39 | const wallet = new fuel.Wallet(window.web3.currentProvider); 40 | 41 | 42 | (async () => { 43 | 44 | // make a deposit 45 | await wallet.deposit(daiAddress, fuel.utils.parseEther('1.0')); 46 | 47 | // make a transfer 48 | await wallet.transfer(daiAddress, recipientAddress, fuel.utils.parseEther('1.0')); 49 | 50 | // listen for new inputs and balance changes 51 | wallet.on('input', input => { 52 | console.log('listening for new inputs: ', input); 53 | }); 54 | 55 | // get your address 56 | console.log('my address', wallet.address); 57 | 58 | })(); 59 | ``` 60 | 61 | ### Description 62 | The **Wallet** object allows you to interact with a Fuel instance. 63 | 64 | This object is heavily powered by the [ethers](https://github.com/ethers-io/ethers.js/) library. [web3.js](https://github.com/ethereum/web3.js/) providers are also supported. 65 | 66 | The **Wallet** wrapper will simply use the provided **provider** object's *eth_signTypedData_v4* method for signing transactions. 67 | 68 | If neither are available, you can use the **Wallet** object as a read-only wallet. You may also provide an override **privateKey** which will be used in place of the provider. The storage and management of this privateKey is up to the developer. 69 | 70 | Ethereum **gasPrice** and **gasLimit** options are only needed when using the **force** feature of SDK methods, which will allow users the option of creating their own rollup blocks. 71 | 72 | ### Params 73 | - **provider** : ***Web3Provider*** | ***EthersProvider***; a web3 or ethers `Provider` object 74 | - **options** : ***Object*** 75 | 76 | 77 | - **privateKey** : `Hex` | `Uint8Array` | `SignerKey`; the override 32 byte Ethereum standard private key used for signing transactions. Used instead of the provider signing using `eth_signTypedData_v4` 78 | - **gasPrice** : `Hex` | `BigNumber`; the Ethereum gas price for forced transactions 79 | - **gasLimit** : `Hex` | `BigNumber`; the Ethereum gas limit for forced transactions 80 | - **address** : `Hex`; the read-only 20-byte hex string address for watching balances 81 | - **db** : `LevelDown`; a [leveldown-compliant database instance](https://github.com/Level/leveldown) for storing inputs and outputs temporarily or persistently 82 | - **sync** : `Boolean`; sync before each wallet action, this can be turned off for better performance but you will have to manage `sync` manually by using `await wallet.sync()`, see [Performance and Syncing](#performanceandsyncing) for more details. 83 | 84 | ### Throws 85 | - If the `db` is invalid or will not open 86 | - If the `privateKey` is invalid or incorrect, if provided 87 | 88 | ```js 89 | const wallet = new fuel.Wallet(window.web3.currentProvider, { 90 | db: require('level-js')(), // a leveldown-compliant database 91 | }); 92 | ``` 93 | 94 | deposit 95 | --- 96 | 97 | **_wallet_ . deposit** ( token, amount [, options] ) => Promise<[`TransactionResponse`](#transactionresponse)> 98 | 99 | ### Description 100 | The `deposit` method will deposit ERC-20 tokens or ETH into the Fuel. 101 | 102 | ### Params 103 | - **token** : `Hex`; `Number`; `BigNumber`; the 20-byte ERC-20 token address or ID number 104 | - **amount** : `Number` | `Hex` | `BigNumber`; the amount to deposit into Fuel 105 | - **options** : [`OptionsObject`](#optionsobject) 106 | 107 | ### Returns 108 | This method returns a [`TransactionResponse`](#transactionresponse) object. 109 | - **response** : [`TransactionResponse`](#transactionresponse); the transaction response object 110 | 111 | ### Throws 112 | - If there is insufficient balance of the ERC-20 token or ETH to cover amount and gas fees 113 | - If the timeout has passed and no Fuel block producer has picked up the deposit 114 | 115 | ```js 116 | await wallet.deposit(daiAddress, 500000, { 117 | // gasPrice: ..., 118 | // gasLimit: ..., 119 | // from: '0x...', 120 | // timeout: 10000, // seconds 121 | }); 122 | ``` 123 | 124 | 125 | faucet 126 | --- 127 | 128 | **_wallet_ . faucet** ( [, options] ) => Promise 129 | 130 | ### Description 131 | This method will call the Fuel network faucet, based upon your network, and send the `wallet.address` test tokens to play with. 132 | 133 | Note, this method might take up to a few minutes to work and is rate-limited. 134 | 135 | ### Params 136 | - **options** : [`OptionsObject`](#optionsobject) 137 | 138 | ### Throws 139 | - If the `options.timeout`, default `100` seconds (or `100000` micro-seconds) times out. 140 | 141 | ```js 142 | await wallet.faucet(); 143 | ``` 144 | 145 | balance 146 | --- 147 | 148 | **_wallet_ . balance** ( token, [, options] ) => Promise<[`BigNumber`](#bignumber)> 149 | 150 | ### Description 151 | This method will give you your current balance for a specific token. 152 | 153 | ### Params 154 | - **token** : `Hex`; `Number`; `BigNumber`; the 20-byte ERC-20 token address or ID number 155 | - **options** : [`OptionsObject`](#optionsobject) 156 | 157 | ### Returns 158 | This method returns a [`BigNumber`](#bignumber) object containing the balance. 159 | - **balance** : [`BigNumber`](#bignumber); the balance for the token 160 | 161 | ### Throws 162 | - If the token is invalid or is not registered with Fuel 163 | 164 | ```js 165 | await wallet.balance(daiAddress); 166 | ``` 167 | 168 | transfer 169 | --- 170 | 171 | **_wallet_ . transfer** ( token, to, amount [, options] ) => Promise<[`TransactionResponse`](#transactionresponse)> 172 | 173 | ### Params 174 | - **token** : `Hex`; `Number`; `BigNumber`; the 20-byte ERC-20 token address or ID number 175 | - **to** : `Hex`; the 20-byte recipient address 176 | - **amount** : `Number` | `Hex` | `BigNumber`; the amount to transfer 177 | - **options** : [`OptionsObject`](#optionsobject) 178 | 179 | ### Returns 180 | This method returns a [`TransactionResponse`](#transactionresponse) object. 181 | - **response** : [`TransactionResponse`](#transactionresponse); the transaction response object 182 | 183 | ### Throws 184 | - If there is insufficient balance of the ERC-20 token or ETH to cover amount and fees 185 | - If there is a connection or provider issue 186 | 187 | ```js 188 | await wallet.transfer(daiAddress, someAddress, 250000, { 189 | // inputs: [], // specify explicit array of UTXO IDs to spend 190 | // feeLimit: 2000, 191 | // from: '0x....', 192 | // gasPrice: ..., // only used if forcing a tx 193 | // gasLimit: ..., // only used if forcing a tx 194 | // force: true, // will attempt for force tx on-chain 195 | }); 196 | ``` 197 | 198 | withdraw 199 | --- 200 | 201 | **_wallet_ . withdraw** ( token, amount [, options] ) => Promise<[`TransactionResponse`](#transactionresponse)> 202 | 203 | ### Description 204 | This function allows you to start a long withdraw from Fuel. You first send the withdraw transaction on Fuel, then you complete the withdrawal on Ethereum [2 weeks later](./../3.%20Concepts/0.%20Fundamentals/7.%20Deployment%20Parameters.md). 205 | 206 | ### Params 207 | - **token** : `Hex`; `Number`; `BigNumber`; the 20-byte ERC-20 token address or ID number 208 | - **amount** : `Number` | `Hex` | `BigNumber`; the amount to withdraw 209 | - **options** : [`OptionsObject`](#optionsobject) 210 | 211 | ### Returns 212 | This method returns a [`TransactionResponse`](#transactionresponse) object. 213 | - **response** : [`TransactionResponse`](#transactionresponse); the transaction response object 214 | 215 | ### Throws 216 | - If there is insufficient balance of the ERC-20 token or ETH to cover amount and fees 217 | - If there is a connection or provider issue 218 | 219 | ```js 220 | await wallet.withdraw(daiAddress, 250000, { 221 | // inputs: [], // specify explicit array of UTXO IDs to spend 222 | // feeLimit: 2000, 223 | // from: '0x....', 224 | // gasPrice: ..., // only used if forcing a tx 225 | // gasLimit: ..., // only used if forcing a tx 226 | // force: true, // will attempt for force tx on-chain 227 | }); 228 | ``` 229 | 230 | retrieve 231 | --- 232 | 233 | **_wallet_ . retrieve** ( [options] ) => Promise<[`TransactionResponse`](#transactionresponse)> 234 | 235 | ### Description 236 | This will complete finalized withdrawals. Withdrawals must first be started using [`withdraw`](#withdraw). 237 | 238 | ### Params 239 | - **options** : [`OptionsObject`](#optionsobject) 240 | 241 | ### Returns 242 | This method returns a [`TransactionResponse`](#transactionresponse) object. 243 | - **response** : [`TransactionResponse`](#transactionresponse); the transaction response object 244 | 245 | ### Throws 246 | - If there is insufficient balance of the ERC-20 token or ETH to cover amount and gas fees 247 | - If there is a connection or provider issue 248 | 249 | ```js 250 | // after 2 weeks... 251 | await wallet.retrieve({ 252 | // inputs: [], // specify explicit array of utxo hashes to retrieve 253 | // from: '0x....', 254 | // gasPrice: ..., // only used if forcing a tx 255 | // gasLimit: ..., // only used if forcing a tx 256 | }); 257 | ``` 258 | 259 | sync 260 | --- 261 | 262 | **_wallet_ . sync** ( [options] ) => Promise<`Void`> 263 | 264 | ### Description 265 | The `sync` method will simply download the current UTXOs for this wallet from the Fuel provider. 266 | 267 | ### Throws 268 | - If there is a connection or provider issue 269 | - If there was an issue getting the private account via `eth_getAccounts` 270 | - If there was an issue getting the current Ethereum network from the provider 271 | 272 | ```js 273 | // sync your wallet with the Fuel api 274 | await wallet.sync(); 275 | ``` 276 | 277 | on 278 | --- 279 | 280 | **_wallet_ . on** ( type, listener ) 281 | 282 | ### Description 283 | The `on` method is used to register listeners for incoming transactions from the Fuel API. Once an `on` listener is registered, the wallet becomes _live_, and balances will automatically update. 284 | 285 | If there is a problem with the listener at any time or it fails to bind, the `error` type will be used. 286 | 287 | ### Params 288 | - **type** : `String`; either `input` or `error` 289 | - **listener** : `Function`; a callback function which will include a single argument: a `UTXO`, `Root` or `Deposit` proof object 290 | 291 | ```js 292 | wallet.on('input', utxoOrRootProof => { 293 | console.log(utxoOrRootProof); 294 | }); 295 | 296 | wallet.on('error', error => { 297 | console.log(error); 298 | }); 299 | ``` 300 | 301 | fee 302 | --- 303 | 304 | **_wallet_ . fee** ( token ) => Promise<`BigNumber`> 305 | 306 | ### Description 307 | Get the current feerate for an ERC-20 token. 308 | 309 | ### Params 310 | - **token** : `Hex`; `Number`; `BigNumber`; the 20-byte ERC-20 token address or ID number 311 | 312 | ### Returns 313 | - **fee** : `BigNumber`; the feerate for this ERC-20 token 314 | 315 | ### Throws 316 | - If this token has no feerate available, i.e. the Fuel operator has not allowed this token yet 317 | 318 | ```js 319 | // get the current fee for processing a specific token 320 | await wallet.fee(daiAddress); 321 | ``` 322 | 323 | Performance and Syncing 324 | --- 325 | 326 | Note, that the **Wallet** by default will **sync** before each action (i.e. **transfer**, **balance** etc), you may turn this off by setting `{ ..., sync: false }` in either the global wallet options or per each method. 327 | 328 | If you do this, you must manually manage **sync** operations using the **wallet.sync()** method when needed (e.g. upon account load or when the wallet balance is zero). 329 | 330 | Objects 331 | --- 332 | 333 | ### OptionsObject 334 | - **inputs** : `Array [ Hex, ... ]`; an array of 32-byte hex values specifying either the `Root`, `Deposit` or `UTXO` IDs you would like to spend 335 | - **feeLimit**: `BigNumber`; the maximum feerate to accept for submitting the transaction 336 | - **gasPrice** : `Hex` | `BigNumber`; the Ethereum gas price for forced transactions 337 | - **gasLimit** : `Hex` | `BigNumber`; the Ethereum gas limit for forced transactions 338 | - **from** : `Hex`; the 20-byte sender address to specify either the provider signer or the override private key 339 | - **timeout** : `Number`; the timeout to wait in seconds for the `Promise` to either fail or be accepted 340 | - **force** : `Boolean`; force this method into a single `Root` on Ethereum 341 | - **sync** : `Boolean`; do an account `sync` before the given method or action. 342 | 343 | ### UTXO 344 | - **transactionId** : `Hex`; 345 | - **outputIndex** : `BigNumber`; 346 | - **outputType** : `BigNumber`; 347 | - **owner** : `Hex`; 348 | - **amount** : `BigNumber`; 349 | - **token** : `BigNumber`; 350 | - **digest** : `Hex`; 351 | - **expiry** : `BigNumber`; 352 | - **returnOwner** : `Hex`; 353 | 354 | ### Root 355 | - **producer** : `Hex`; 356 | - **merkleTreeRoot** : `Hex`; 357 | - **commitmentHash** : `Hex`; 358 | - **length** : `BigNumber`; 359 | - **feeToken** : `BigNumber`; 360 | - **fee** : `BigNumber`; 361 | 362 | ### Deposit 363 | - **owner** : `Hex`; 364 | - **token** : `BigNumber`; 365 | - **blockNumber** : `BigNumber`; 366 | - **value** : `BigNumber`; 367 | 368 | ### BigNumber 369 | - This is an `ethers` wrapped BigNumber object, using BN.js under the hood. 370 | 371 | Response Objects 372 | --- 373 | 374 | ### TransactionResponse 375 | - **transactionId** : `Hex`; the Ethereum transaction hash 376 | - **receipts** : `Array`; an array of Ethereum transactions receipts, if any. Namely for deposits, withdrawals or forced transfers. 377 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/0. Fundamentals/1. Fuel Overview.md: -------------------------------------------------------------------------------- 1 | Fuel Overview 2 | === 3 | 4 | This section of the docs goes over the fundamental technical details of the Fuel rollup chain: what it is, how it works, and why it is scalable and secure. 5 | 6 | Background 7 | --- 8 | 9 | Fuel is an _optimistic rollup_, a special sidechain architecture that is both trust-minimized and permissionless. Unlike a [traditional sidechain](https://blockstream.com/sidechains.pdf), where the safety of user funds is dependent on the honest majority of some set of validators that is disjoint from the main chain's miners, optimistic rollups borrow security directly from the main chain (Ethereum). 10 | 11 | The simplified version of [optimistic rollups](https://ethresear.ch/t/minimal-viable-merged-consensus/5617) is as follows. Anyone may construct a rollup block off-chain and [submit it to Ethereum as _calldata_](https://vitalik.ca/general/2019/08/28/hybrid_layer_2.html) (i.e. simple binary data attached to a transaction). Each block submitted in this manner must build upon the previous rollup block (a contract keeps track of block header hashes for the rollup chain) and include a parametrizable bond. If a block is invalid, a [compact fraud proof](https://arxiv.org/abs/1809.09044) can be submitted and processed on-chain by anyone, which will roll back the rollup chain to the previous block, burn a portion of the bond, and reward the fraud prover with the rest. After a parametrizable timeout, rollup blocks are _finalized_, and are considered valid (i.e. can no longer be proven fraudulent) and their bond unlocked. Withdrawals are initiated by burning coins on the rollup, then completing the withdrawal after that rollup block has finalized. 12 | 13 | Interacting with Fuel 14 | --- 15 | 16 | | ![Node](/assets/images/fig_node.png) | 17 | | :------------------------------------: | 18 | | _Fuel node interacting with Ethereum._ | 19 | 20 | Users send Fuel transactions to a Fuel node, which enters the node's mempool as an unconfirmed transaction. The client combines transactions into a Fuel block, which is then sent to Ethereum as _calldata_, at which point the Fuel block is confirmed. The node also reads deposit events from Ethereum, adding deposits as spendable state elements on Fuel. 21 | 22 | | ![Transactions](/assets/images/fig_fuel_transactions.png) | 23 | | :-------------------------------------------------------: | 24 | | _Fuel normal (above) and forced (below) transactions._ | 25 | 26 | There are two ways of getting Fuel transactions included in blocks. In the first, under normal operation, the users send transactions to a Fuel node, which then combines them into batches (roots), and finally into a block (which contains several roots). In the second, a user wants to use their own Fuel node to submit a new block, i.e. a forced transaction. In this case, they can create a root and block independently of any other node and submit it to Ethereum directly. 27 | 28 | | ![Entering](/assets/images/fig_entering.png) | 29 | | :------------------------------------------: | 30 | | _Entering Fuel._ | 31 | 32 | Depositing funds into Fuel is done by simply sending them to the Fuel contract (or optionally through a [token funnel](./../4.%20Additional%20Modules/Funnels.md)), at which point the deposits will be added to the state of the Fuel chain. 33 | 34 | | ![Exiting](/assets/images/fig_exiting.png) | 35 | | :---------------------------------------------------: | 36 | | _Exiting Fuel normally (above) with quickly (below)._ | 37 | 38 | Withdrawing funds from Fuel can be done in two ways: standard and fast. For standard withdrawals, a user simply burns their coins on Fuel, then after a [delay](./7.%20Deployment%20Parameters.md), can complete the withdrawal on Ethereum. For [fast withdrawals](./../../4.%20Tools%20and%20Applications/0.%20Fast%20Withdrawals.md), a user contacts a liquidity provider and atomic swaps funds from Fuel to Ethereum in a matter of minutes. 39 | 40 | Architecture: A High-Level View 41 | --- 42 | 43 | Fuel is unique among Ethereum rollups in that it uses a [UTXO](https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch06.asciidoc#transaction-outputs-and-inputs)-based transaction system. This allows for parallel transaction validation, and in the future stateless predicate validation for spending conditions, greatly increasing scalability compared to contemporary accounts-based blockchains and rollups. 44 | 45 | Each transaction can spend [up to eight inputs and produce up to eight outputs](./4.%20Transaction%20Architecture.md). This allows atomic multi-user transactions, e.g. for an on-chain atomic exchange, which also means that non-custodial exchanges [can be built on top of Fuel](./../../4.%20Tools%20and%20Applications/3.%20Non-Custodial%20Exchanges.md). The deterministic and stateless nature of computing state element (UTXO) IDs produced and consumed by transactions enables long chains and [even trees of pre-signed transactions](../../4.%20Tools%20and%20Applications/1.%20Token%20Minting.md) to be constructed. 46 | 47 | State elements (UTXOs and deposits) can be [_colored_](https://en.bitcoin.it/wiki/Colored_Coins), i.e. represent different assets. This allows transactions to natively handle both ETH and any ERC-20 token. 48 | 49 | Fuel supports a number of spending conditions that allow for powerful implicit expressivity: 50 | - [HTLC outputs](https://en.bitcoin.it/wiki/Hash_Time_Locked_Contracts), which have both a hashlock and a timelock. These enable cross-chain atomic swaps (including between Fuel and Ethereum for [instant withdrawals](./../../4.%20Tools%20and%20Applications/0.%20Fast%20Withdrawals.md)). They can also be used as a signaling mechanism (e.g. to vote in a DAO), and when combined with a chain of pre-signed transactions, for cancellable subscriptions. 51 | - [Return outputs](https://en.bitcoin.it/wiki/OP_RETURN), which are unspendable and can include a long binary blob. These can be used to build applications that are executed client-side and use Fuel for timestamping messages cheaply. 52 | 53 | The fraud proof scheme used by Fuel is unique in that [it does not require state serialization](https://ethresear.ch/t/compact-fraud-proofs-for-utxo-chains-without-intermediate-state-serialization/5885) (computing the Merkle root of the state) after every transaction, or even after every block. State serialization is one of the biggest bottlenecks for Ethereum and accounts-based rollups today, and remains a Herculean challenge to optimize implementations around. This, along with parallelizable transaction validation, make Fuel the most scalable rollup in the world. 54 | 55 | Fuel's block production model is entirely permissionless, and requires no token (and will never require a token). Anyone may start by submitting a [_root_](./../1.%20Data%20Structures/Roots.md), a bundle of Fuel transactions, to Ethereum. The root can then be included in a [Fuel block](../1.%20Data%20Structures/Blocks.md) by anyone, with a small caveat. The Fuel operator has a short period of time (on the order of minutes, a parameter) where they are the only one that can use this root in a block. This allows the operator to reliably provide a soft confirmation to a recipient that a transaction will be included in the next Fuel block. While this is the default and preferred configuration, using an operator is a system parameter that can be disabled trivially on contract creation if soft confirmations aren't needed. 56 | 57 | What To Read Next 58 | --- 59 | 60 | For a detailed analysis of Fuel's security guarantees, and how it compares to other scaling technologies, see [the next page](2.%20Security%20Analysis.md). (_Warning: this document assumes a high level of technical proficiency._) 61 | 62 | A more in-depth survey of Fuel's components is given [here](6.%20System%20Description%20Primer.md), with [block](3.%20Block%20Architecture.md) and [transaction](4.%20Transaction%20Architecture.md) architecture descriptions also available. 63 | 64 | The canonical serialization scheme is defined [here](5.%20Serialization.md). 65 | 66 | Finally, the parameters used for deployments across different networks is found [here](7.%20Deployment%20Parameters.md). 67 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/0. Fundamentals/3. Block Architecture.md: -------------------------------------------------------------------------------- 1 | Block Architecture 2 | === 3 | 4 | Being a UTXO-based blockchain, Fuel is designed with a number of similarities to existing UTXO-based chains, such as Bitcoin. Consult the [Bitcoin developer reference](https://developer.bitcoin.org/reference/) for an overview of the minimal block layout required for such a chain. 5 | 6 | | ![Overview](/assets/images/fig_structs.png) | 7 | | :-----------------------------------------: | 8 | | _Overview of block contents._ | 9 | 10 | This page describes intuitions behind the top-level data structures, from blocks to leaves in the transaction tree. Discussion on the transaction architecture is relegated to [the next page](4.%20Transaction%20Architecture.md). 11 | 12 | Block Header 13 | --- 14 | 15 | In any blockchain, [block headers](../1.%20Data%20Structures/Blocks.md) commit to a list of transactions, and contain other important metadata. Blocks are block headers plus the explicit list of transactions, but do not exist as an independent data structure in Fuel. 16 | 17 | Each block header in Fuel contains the usual suspects: an identifier for the block producer, the previous block header's hash, and the _block height_ (the index of this rollup block in the rollup chain). A few other fields, that diverge from traditional blockchains, are also present. 18 | 19 | First, the _block number_, i.e. the Ethereum block number when this rollup block was submitted to Ethereum, is included. Note that the expressions **\[block\] height** and **\[block\] number** are used to refer to the rollup block height and the Ethereum block number, respectively. 20 | 21 | > **Note:** Including the block number in the header (or, more specifically, requiring an Ethereum block number and Ethereum block hash to match [when committing a new rollup block](../1.%20Data%20Structures/Blocks.md)) prevents miners from re-organizing Ethereum and moving a submission transaction to an earlier block number, which could invalidate the timelock conditions of Fuel transactions. 22 | 23 | Additionally, the maximum [token ID](../1.%20Data%20Structures/Tokens.md) and [address ID](../1.%20Data%20Structures/Addresses.md) used through the rollup block (i.e. in this and all previous rollup blocks) is included in the header. The [transaction architecture page](4.%20Transaction%20Architecture.md) will discuss these in more details, but for now it is sufficient to know that addresses (token are identified by an address as well) can be _registered_, which allows them be to referenced by a short numerical ID rather than a full 20-byte address, resulting in smaller (and thus cheaper) transactions. 24 | 25 | > **Note:** An attacker can craft a rollup block that includes a transaction with a not-yet-registered ID (i.e. an invalid block). When they see a transaction that proves that block is invalid, they can front-run it with a transaction that registers the ID. Checking for maximum IDs as a block is submitted prevents this griefing vector. 26 | 27 | Finally, rather than a single Merkle root of a list of transactions, a list of _root header_ hashes is included. Each root header commits to a list of transactions (in other words, the block header still commits to a list of transactions, though indirectly), and is discussed in [the next section](#root-header). 28 | 29 | Fields that are usually seen in layer-1 Proof-of-Work chains, such as a timestamp and a nonce, are omitted. The former is implicit in the form of the Ethereum block number, and the latter is unnecessary since work is not used in the rollup. 30 | 31 | Root Header 32 | --- 33 | 34 | Each [root header](../1.%20Data%20Structures/Roots.md) commits to a list of transactions directly in two forms, and contains additional metadata that will be discussed shortly. Roots are root headers plus the explicit list of transactions, but do not exist as an independent data structure. 35 | 36 | A list of transactions is committed to as both a Merkle root and a simple hash. The simple hash is checked when a new root is submitted on-chain, but not the Merkle root. This avoids the need to Merkleize transactions all the time, and saves on gas costs. If the Merkle root is incorrect, this can be proven with [a fraud proof](../3.%20Provers/Malformed%20Block.md) (which uses the simple hash to authenticate the data that will be Merkleized). 37 | 38 | > **Note:** Separating block submission into two steps—first submitting one or more roots, then submitting the block header that includes those roots—reduces the costs of a race condition where multiple block producers submit a block at the same time and only one is valid (and the other transactions would fail and cost gas). By making block submission extremely gas-cheap, this race condition is no a longer costly mistake. There is no race condition on submitting roots. 39 | 40 | > **Note:** The size bound on the list of transactions is chosen such that Merkleizing any individual list of transactions can be done within the gas limit of a single Ethereum block (with a large margin of safety). 41 | 42 | Two transaction fields are [_hoisted_](https://en.wikipedia.org/wiki/Loop-invariant_code_motion) into the root header: the fee token ID and the feerate. By enforcing that all transactions under a single root pay fees in the same token at the same rate, we can avoid needing to repeat these values for every transaction, and instead only specify them once in the root header. 43 | 44 | > **Note:** Transactions still sign over the fee token ID and feerate values, to avoid malicious root submissions. The values are [_implicitly_](./../1.%20Data%20Structures/Transactions.md) part of the transaction data that is signed. See the next section for implicit vs explicit transaction data. 45 | 46 | Transaction Leaves 47 | --- 48 | 49 | The [transaction architecture](4.%20Transaction%20Architecture.md) can be found in the next page. It is recommended to read it first, before returning to complete this section. 50 | 51 | Each [transaction leaf](../1.%20Data%20Structures/Transactions.md) (i.e. leaf in the Merkle tree of transactions that are committed to in a root header) contains all the required data to reconstruct the state transition defined by the transaction unambiguously. 52 | 53 | 1. A list of witnesses, which authorize spending a state element in this transaction. 54 | 1. A list of inputs and metadata (one metadata per input). Each input provides enough information to "unlock" the state element being spent, but does not explicitly identify the state element by ID. 55 | 1. A list of outputs, which each describe the spending conditions for a new state element. 56 | 57 | _Metadata_ is inserted by the root submitter as a means of uniquely identifying the state element being spent at each input. For regular UTXOs this would be the block height, root index, transaction index, then output index. This replaces the traditional UTXO ID (usually: a hash of the transaction and output index) with a much more compact representation. 58 | 59 | > **Note:** Metadata is malleable by the root submitter, and is thus not signed over by the transaction sender. 60 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/0. Fundamentals/4. Transaction Architecture.md: -------------------------------------------------------------------------------- 1 | Transaction Architecture 2 | === 3 | 4 | | ![Transaction](/assets/images/fig_tx.png) | 5 | | :------------------------------------------------------: | 6 | | A transaction with up to eight inputs and eight outputs. | 7 | 8 | A [transaction](../1.%20Data%20Structures/Transactions.md) in Fuel specifies a _state transition_: inputs tell which state elements are consumed and outputs tell which state elements are produced. As with any UTXO-based system, each state element can only be produced and consumed at most once. Modeling the rollup chain's state as a key-value store, this means that keys can never be re-used, and keys commit to values in some way. 9 | 10 | > **Note:** Up to eight inputs and outputs are allowed per transaction, to keep the worst-case cost of fraud proofs low while simultaneously enabling a number of applications that require multiple inputs or outputs. 11 | 12 | Each [input](../1.%20Data%20Structures/Inputs.md) specifies the state element to spend, and unlocks it. For plain UTXOs and deposits, this is the UTXO/deposit ID and a valid digital signature. For HTLC UTXOs, this is the UTXO ID and a preimage (if using the hashlock spending condition) and a valid digital signature. 13 | 14 | Each [output](../1.%20Data%20Structures/Outputs.md) specifies the new state element to produce (including amounts, token type, etc.), and its spending conditions (recipient address, timelock and hashlock). 15 | 16 | Transactions can be validated statelessly, and the state database only needs to be checked for the _existence_ of each consumed state element. In addition, there is no inherent limitation on which accounts sign a transaction, so a transaction can represent an atomic interaction between more than one user (e.g. an on-chain atomic exchange). 17 | 18 | The _transaction ID_ (a unique identifier for each transaction) is computed as the [EIP-712 hash](./5.%20Serialization.md) of the hash of the transaction data _without witnesses_. We will see in the next section why excluding witness data has some nice properties. 19 | 20 | Inputs: Witnesses and Metadata 21 | --- 22 | 23 | | ![Witness and metadata](/assets/images/fig_witnesses.png) | 24 | | :-------------------------------------------------------: | 25 | | Input witness and metadata. | 26 | 27 | Each input is linked to a [witness](../1.%20Data%20Structures/Witness.md) (generalization of a digital signature) and [metadata](../1.%20Data%20Structures/Metadata.md). 28 | 29 | Witnesses are either a digital signature, or an authorization from a smart contract on Ethereum (e.g. a smart contract wallet can be used to authorize Fuel transactions). In either case, authorization is performed on a transaction ID (as the in previous section, the non-witness transaction data), i.e. signatures are over the transaction ID. 30 | 31 | > **Note:** Signing over the transaction ID means that the transaction only has to be hashed once when verified, regardless of the number of inputs or outputs. This avoids the [quadratic hashing issue seen in Bitcoin](https://bitcoin.stackexchange.com/questions/54548/scriptsig-content-during-signature-quadratic-hashing). 32 | 33 | Each input specifies a state element to consume (i.e. a UTXO ID, or a deposit ID), which is a 32-byte hash. This value is part of the non-witness transaction data, and is signed over. However, when posting transactions on Ethereum, explicit state element identifiers are stripped and replaced by more compact _metadata_, which "point" to a unique entry in the ledger (or a deposit). In other words, metadata will point to an _exact_ output in the totally ordered outputs, transactions, roots, and blocks. 34 | 35 | > **Note:** Given the one-to-one mapping between ledger entries and state element identifiers, it is easy to show the state element produced by an exact entry with a simple inclusion proof, leveraging the property that computing state element identifiers is a stateless operation. 36 | 37 | > **Note:** Extending the above, transaction IDs are not immediately obvious with only the data posted to Ethereum, since state element identifiers are missing. However, they can be proven, and the transaction IDs computed, with inclusion proofs for the entires pointed to by metadata. 38 | 39 | Segregated Witnesses 40 | --- 41 | 42 | | ![Segregated witnesses](/assets/images/fig_segwit.png) | 43 | | :----------------------------------------------------: | 44 | | Segregated witnesses. | 45 | 46 | Fuel is designed with a form of _segregated witness_, where witness data is not bundled with inputs. While the previous sections provided intuition, they did not precisely describe where witnesses are placed in transactions. 47 | 48 | Each input actually specifies a _witness index_ that authorizes spending the referenced state element. This means that multiple inputs could use the same witness, which greatly reduces the cost of spending multiple state elements owned by the same account. 49 | 50 | Simple Send Example 51 | --- 52 | 53 | | ![Simple send](/assets/images/fig_send.png) | 54 | | :-----------------------------------------: | 55 | | A simple send. | 56 | 57 | As an example, the above is a simple one-input two-output simple send. One output is returned to the sender as change (there is no special change output type, so it looks like any other output). The other is sent to the recipient. 58 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/0. Fundamentals/5. Serialization.md: -------------------------------------------------------------------------------- 1 | # Fuel EIP-712 Specification 2 | 3 | This document describes the Fuel EIP-712 specification, including `encodeTypes`, and `encodeData` functions. 4 | EIP-712 improves usability of off-chain message signatures for use on-chain by specifying a standard for hashing and signing of typed (semi-)structured data (not just bytes). 5 | 6 | ## encodeTypes 7 | 8 | ### Address 9 | 10 | `encodeData`: 11 | 12 | * require `Output.owner.length > 0` 13 | * require `Output.owner.length <= 20` 14 | * `Output.owner =` 15 | * `if Output.owner.length == 20 then Output.owner` 16 | * `else Output.owner[:Output.owner.length]` 17 | 18 | ### Input 19 | 20 | ``` 21 | Input( 22 | uint8 type, 23 | uint8 witnessReference 24 | ) 25 | ``` 26 | 27 | ### InputDeposit 28 | 29 | ``` 30 | InputDeposit( 31 | uint8 type, 32 | uint8 witnessReference, 33 | address owner 34 | ) 35 | ``` 36 | 37 | ### InputHTLC 38 | 39 | ``` 40 | InputHTLC( 41 | uint8 type, 42 | uint8 witnessReference, 43 | bytes32 preImage 44 | ) 45 | ``` 46 | 47 | #### Metadata 48 | 49 | ``` 50 | Metadata( 51 | uint32 blockHeight, 52 | uint8 rootIndex, 53 | uint16 transactionIndex, 54 | uint8 outputIndex 55 | ) 56 | ``` 57 | 58 | ### MetadataDeposit 59 | 60 | ``` 61 | MetadataDeposit( 62 | uint32 token, 63 | uint32 blockNumber 64 | ) 65 | ``` 66 | 67 | ### Output 68 | 69 | ``` 70 | Output( 71 | uint8 type, 72 | uint8 tokenLength, 73 | bytes1[] token, 74 | uint8 amountShift, 75 | uint8 amountLength, 76 | uint8[] amount, 77 | uint8 ownerLength, 78 | bytes1[] owner 79 | ) 80 | ``` 81 | 82 | encodeData for `Output`: 83 | 84 | * require `amountLength <= 32` 85 | * require `amountShift <= 256` 86 | * require `((amountLength * 8) + amountShift) <= 256` 87 | * `Output.amount = Output.amount.data[:Output.amountLength] << Output.amountShift` 88 | 89 | ### OutputHTLC 90 | 91 | ``` 92 | OutputHTLC( 93 | uint8 type, 94 | uint8 tokenLength, 95 | bytes1[] token, 96 | uint8 amountShift, 97 | uint8 amountLength, 98 | uint8[] amount, 99 | uint8 ownerLength, 100 | bytes1[] owner, 101 | bytes32 digest, 102 | uint32 expiry, 103 | uint8 returnOwnerLength, 104 | bytes1[] returnOwner 105 | ) 106 | ``` 107 | 108 | ### OutputReturn 109 | 110 | ``` 111 | OutputReturn( 112 | uint8 type, 113 | uint16 dataLength, 114 | bytes1[] data 115 | ) 116 | ``` 117 | 118 | ### Storage 119 | 120 | Base type for stored types. Computes index into storage of 1-, 2-, or 3-element items: 121 | 122 | * mapping key for 1-element item is: `keccak256(0, 64)` 123 | * mapping key for 2-element item is: `keccak256(0, 96)` 124 | * mapping key for 3-element item is: `keccak256(0, 128)` 125 | 126 | ### TransactionProof 127 | 128 | ``` 129 | TransactionProof( 130 | address blockProducer, 131 | bytes32 previousBlockHash, 132 | uint256 blockHeight, 133 | uint256 blockNumber, 134 | uint256 numTokens, 135 | uint256 numAddresses, 136 | uint16 rootsLength, 137 | bytes32[] roots, 138 | address rootProducer, 139 | bytes32 merkleTreeRoot, 140 | bytes32 commitmentHash, 141 | uint256 rootLength, 142 | uint256 feeToken, 143 | uint256 fee, 144 | uint16 rootIndex, 145 | uint16 merkleProofLength, 146 | bytes32[] merkleProof, 147 | uint8 inputOutputIndex, 148 | uint16 transactionIndex, 149 | uint16 transactionLength, 150 | bytes1[] transaction, 151 | uint8 dataLength, 152 | bytes32[] data, 153 | uint256 signatureFeeToken, 154 | uint256 signatureFee, 155 | address tokenAddress, 156 | address selector 157 | ) 158 | ``` 159 | 160 | ### TransactionLeaf 161 | 162 | ``` 163 | TransactionLeaf( 164 | uint16 length, 165 | uint8 metadataLength, 166 | bytes8[] metadata, 167 | uint16 witnessesLength, 168 | bytes1[] witnesses, 169 | uint16 inputsLength, 170 | bytes1[] inputs, 171 | uint16 outputsLength, 172 | bytes1[] outputs 173 | ) 174 | ``` 175 | 176 | ### UTXO 177 | 178 | ``` 179 | UTXO( 180 | bytes32 transactionId, 181 | uint256 outputIndex, 182 | uint256 outputType, 183 | bytes32 owner, 184 | uint256 amount, 185 | uint256 token, 186 | bytes32 digest, 187 | uint256 expiry, 188 | bytes32 returnOwner 189 | ) 190 | ``` 191 | 192 | ### Witness 193 | 194 | There is no explicit `Witness` type, only its sub-types of Signature, Caller, and Producer. 195 | 196 | ``` 197 | Signature( 198 | uint8 type, 199 | bytes32 r, 200 | bytes32 s, 201 | uint8 v 202 | ) 203 | ``` 204 | 205 | ``` 206 | Caller( 207 | uint8 type, 208 | address owner, 209 | uint32 blockNumber 210 | ) 211 | ``` 212 | 213 | ``` 214 | Producer( 215 | uint8 type, 216 | bytes32 hash 217 | ) 218 | ``` 219 | 220 | ## Special notes 221 | 222 | ### `chainID` 223 | 224 | Fuel does not mandate the use of a `chainID` field. 225 | 226 | Applications can rely on existing secure `chainID` approaches, including EIP-155 Simple replay attack protection and EIP-1344 ChainID opcode. EIP-155 includes a `chainID` in the computation of a transaction's signature, and EIP-1344 defines a `chainID` smart contract opcode. 227 | 228 | An important sysops note is that the use of EIP-1344 in Fuel is fully backwards compatible with all chains which implement EIP-155 chain ID domain separator for transaction signing. 229 | 230 | ## References 231 | 232 | Vitalik Buterin, "EIP-155: Simple replay attack protection," Ethereum Improvement Proposals, no. 155, October 2016. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-155. 233 | 234 | Richard Meissner, Bryant Eisenbach, "EIP-1344: ChainID opcode," Ethereum Improvement Proposals, no. 1344, August 2018. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-1344. 235 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/0. Fundamentals/6. System Description Primer.md: -------------------------------------------------------------------------------- 1 | System Description Primer 2 | === 3 | 4 | System Components 5 | --- 6 | 7 | This page lists the different system components that are documented in the remainder of the `Concepts` section. 8 | 9 | Data Structures 10 | --- 11 | 12 | The core data structures are: 13 | 1. [Addresses](../1.%20Data%20Structures/Addresses.md): a registry for user account addresses. 14 | 1. [Blocks and block headers](../1.%20Data%20Structures/Blocks.md): top-level data structure. 15 | 1. [Deposits](../1.%20Data%20Structures/Deposits.md): deposits to Fuel from Ethereum. 16 | 1. [Inputs](../1.%20Data%20Structures/Inputs.md): transaction inputs. 17 | 1. [Metadata](../1.%20Data%20Structures/Metadata.md): point to state elements to consume. 18 | 1. [Outputs](../1.%20Data%20Structures/Outputs.md): transaction outputs. 19 | 1. [Roots and root headers](../1.%20Data%20Structures/Roots.md): commit to a batch of transactions. 20 | 1. [Tokens](../1.%20Data%20Structures/Tokens.md): a registry for token addresses. 21 | 1. [Transactions](../1.%20Data%20Structures/Transactions.md): transactions. 22 | 1. [Withdrawals](../1.%20Data%20Structures/Withdrawals.md): withdrawals from Fuel to Ethereum. 23 | 1. [Witnesses](./../1.%20Data%20Structures/Witness.md): authorize transactions. 24 | 25 | Verifiers 26 | --- 27 | 28 | If a fraud proof is submitted to the contract, it first needs to be validated for correct formatting. This is required to ensure that a maliciously-constructed fraud proof can never be processed, otherwise a valid block could be reverted. Parsing fraud proofs is handled by [verifiers](../2.%20Verifiers/Block%20Header.md). 29 | 30 | Provers 31 | --- 32 | 33 | Once a fraud proof has successfully been parsed by the appropriate verifier modules, it must be processed to prove that fraud occurred (or that the fraud proof is properly formatted but otherwise incorrect). This is handled by [provers](./../3.%20Provers/Double%20Spend.md). 34 | 35 | Additional Modules 36 | --- 37 | 38 | Outside the core components above, additional optional modules are provided to e.g. improve UX and add more functionality: 39 | 1. [Token funnels](../4.%20Additional%20Modules/Funnels.md): ephemeral contracts that accept token deposits without an `approve` step. 40 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/0. Fundamentals/7. Deployment Parameters.md: -------------------------------------------------------------------------------- 1 | Deployment Parameters 2 | === 3 | 4 | Constructor Parameters 5 | --- 6 | 7 | Here we will describe the Fuel contract's constructor parameters. 8 | 9 | | field name | description | 10 | | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 11 | | **operator** | `address`; The primary operator of the Fuel rollup. This account receives priority access on including roots in blocks production, however, anyone else may use roots with a delay specified by the `submissionDelay` parameter. | 12 | | **finalizationDelay** | `uint256`; The time to finalization in Ethereum blocks. | 13 | | **submissionDelay** | `uint256`; The number of Ethereum blocks a non-operator must wait before using a root in a block. | 14 | | **penaltyDelay** | `uint256`; The delay which the operator will face if they commit Fraud, until the time they may come back online as the primary operator. | 15 | | **bondSize** | `uint256`; The bond size required for block production, in wei. | 16 | | **name** | `string`; The name string used for contract identification and EIP-712 hashing. | 17 | | **version** | `string`; The version of the contract used for identification and EIP-712 hashing. | 18 | | **chainId** | `uint256`; The Ethereum network chain identifier used for identification, replay attack protection, and EIP-712 hashing. | 19 | | **genesis** | `bytes32`; The registered genesis block hash. This property is simply for vanity and can be set to any value as the minimum referenced block is always > 0. | 20 | 21 | ### Deploying in Operated Mode 22 | If you would like to deploy a Fuel chain in operated mode, use non-zero values for `operator` and `submissionDelay`. 23 | 24 | ### Deploying in Un-operated Mode 25 | If you would like to deploy Fuel in un-operated mode, where anyone may submit blocks at any time, use zero values for `operator` and `submissionDelay`. 26 | 27 | ### Finalization Delays 28 | In any optimistic rollup, finalization delay is a critical security parameter. A longer value provides more robustness against miner censorship attacks, but will result in longer withdrawals. 29 | 30 | We recommend 1 week at the minimum, or 2 weeks on the higher end, to protect against both chain congestion attacks and censorship attacks. 31 | 32 | Rinkeby Testnet 33 | --- 34 | 35 | Contract address: [0x669c63dDD6050838faf496F46EEb7378bff05d77](https://rinkeby.etherscan.io/address/0x669c63dDD6050838faf496F46EEb7378bff05d77) 36 | 37 | Name: `rinkeby` 38 | 39 | | field name | value | 40 | | --------------------- | --------------------------------------------------------------------------------- | 41 | | **operator** | `0x0ea6b5edc8905c85514b3676703f1bfe6ec260ad` | 42 | | **finalizationDelay** | `93046` (one week) | 43 | | **submissionDelay** | `6646` (one day) | 44 | | **penaltyDelay** | `0` (zero) | 45 | | **bondSize** | `100000000000000000` (0.1 ETH) | 46 | | **name** | `Fuel` | 47 | | **version** | `1.0.0` | 48 | | **chainId** | `4` | 49 | | **genesis** | `0x0000000000000000000000000000000000000000000000000000000000000000` (empty hash) | 50 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/1. Data Structures/Addresses.md: -------------------------------------------------------------------------------- 1 | Addresses 2 | === 3 | 4 | The address registry maintains a mapping of address (20 bytes) to address ID (unsigned integer up to and including 19 bytes). Each time a new address is registered, it is assigned the next address ID in sequence. 5 | 6 | Note that registering an address is not necessary to send or receive funds on Fuel. It is a purely optional way of reducing transaction sizes (and thus costs). 7 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/1. Data Structures/Blocks.md: -------------------------------------------------------------------------------- 1 | Blocks 2 | === 3 | 4 | BlockHeader 5 | --- 6 | 7 | | name | type | size | description | 8 | | ------------------- | ----------- | ---- | --------------------------------------------------- | 9 | | `producer` | `address` | 20 | Address of block proposer committing this block. | 10 | | `previousBlockHash` | `bytes32` | 32 | Previous block's header hash. | 11 | | `height` | `uint256` | 32 | Block height. | 12 | | `blockNumber` | `uint256` | 32 | Ethereum block number when this block is committed. | 13 | | `numTokens` | `uint256` | 32 | Maximum token ID used through this block. | 14 | | `numAddresses` | `uint256` | 32 | Maximum address ID used through this block | 15 | | `roots.length` | `uint16` | 2 | Number of transaction roots. | 16 | | `roots` | `bytes32[]` | 32* | List of root header hashes. | 17 | 18 | ### Number of Tokens 19 | 20 | Tokens IDs are registered contract-side to allow for more compact transactions. The maximum token ID used in this block and all previous blocks is included in the block header. 21 | 22 | This is needed to prevent a griefing attack where a fraudulent rollup block is committed that spends a token ID that is not yet registered. The fraud proof can then be front-run with a transaction that registers the token ID, thereby invalidating the fraud proof. 23 | 24 | See: [token registry](./Tokens.md). 25 | 26 | ### Number of Addresses 27 | 28 | Address IDs are registered contract-side to allow for more compact transactions. The maximum address ID used in this block and all previous blocks is included in the block header. 29 | 30 | This is needed to prevent a griefing attack where a fraudulent rollup block is committed that sends to an address ID that is not yet registered. The fraud proof can then be front-run with a transaction that registers the address ID, thereby invalidating the fraud proof. 31 | 32 | See: [address registry](./Addresses.md). 33 | 34 | ### Roots 35 | 36 | The block header includes a list of root header hashes, `roots`. Each individual root header hash is the hash of a [root header](./Roots.md), which commits to a list of transactions and other important metadata. For more information of why multiple roots are used instead of the more traditional single-transactions-root, see [Block Architecture](../0.%20Fundamentals/3.%20Block%20Architecture.md). 37 | 38 | The number of root header hashes is upper-bounded by the `TRANSACTION_ROOTS_MAX` parameter (`128`). 39 | 40 | Committing a New Block Header 41 | --- 42 | 43 | When a new block header is produced and committed to Ethereum, the following checks **must** pass, and are enforced by the smart contract. 44 | 45 | 1. The height `blockHeight` must be greater than `0` and at most the tip height. 46 | 1. The previous block hash `previousBlockHash` must match the previous block hash at `blockHeight`. 47 | 1. The number of transaction roots `roots.length` must be greater than `0` and at most `TRANSACTION_ROOTS_MAX`. 48 | 1. Every root in `roots` must exist in the root registry. 49 | 1. If the operator is _not_ in _penalty mode_ (discussed below): 50 | 1. If the block producer `producer` is not the operator: 51 | 1. At least the [submission delay parameter](../0.%20Fundamentals/7.%20Deployment%20Parameters.md) Ethereum blocks must have elapsed since the root was submitted. 52 | 53 | The penalty mode becomes active if a successful fraud proof against an operator-produced block is processed. It remains active for the [penalty delay parameter](./../0.%20Fundamentals/7.%20Deployment%20Parameters.md) Ethereum blocks. 54 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/1. Data Structures/Deposits.md: -------------------------------------------------------------------------------- 1 | Deposits 2 | === 3 | 4 | The deposit registry uniquely indexes deposits so they can be spent on Fuel. 5 | 6 | Deposit 7 | --- 8 | 9 | | name | type | size | description | 10 | | ------------- | --------- | ---- | --------------------------------------- | 11 | | `owner` | `address` | 20 | Owner of deposit. | 12 | | `token` | `uint256` | 32 | 4-byte [Token ID](./Tokens.md). | 13 | | `blockNumber` | `uint256` | 32 | Ethereum block number deposit was made. | 14 | | `value` | `uint256` | 32 | Amount of tokens. | 15 | 16 | Deposits are uniquely keyed by `{ owner, token, blockNumber }`, with value `value`. 17 | 18 | Since the granularity of deposits is in Ethereum blocks, multiple deposits from the same owner of the same token in the same Ethereum block simply update the deposited amount. 19 | 20 | Deposits can be spent no earlier than in a Fuel block committed in the next Ethereum block. 21 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/1. Data Structures/Inputs.md: -------------------------------------------------------------------------------- 1 | Inputs 2 | === 3 | 4 | Inputs indicate which state elements (usually: UTXOs) are consumed by a [transaction](./Transactions.md). Each state element can be consumed and produced at most once. 5 | 6 | InputType 7 | --- 8 | 9 | ``` 10 | enum InputType : uint8 { 11 | Transfer = 0, 12 | Deposit = 1, 13 | HTLC = 2, 14 | Root = 3, 15 | } 16 | ``` 17 | 18 | Input 19 | --- 20 | 21 | | name | type | size | description | 22 | | -------------- | ----------- | ---- | ------------------------------------------------------------ | 23 | | `type` | `InputType` | 1 | `InputType.Transfer` or `InputType.Root`. | 24 | | `witnessIndex` | `uint8` | 1 | Index of witness that authorizes spending the state element. | 25 | 26 | There are no spending conditions on plain transfer UTXOs and root UTXOs (collected fees) other than a valid signature from the owner of the UTXO. 27 | 28 | InputDeposit 29 | --- 30 | 31 | | name | type | size | description | 32 | | -------------- | ----------- | ---- | ------------------------------------------------------ | 33 | | `type` | `InputType` | 1 | `InputType.Deposit`. | 34 | | `witnessIndex` | `uint8` | 1 | Index of witness that authorizes spending the deposit. | 35 | | `owner` | `address` | 20 | Deposit owner address. | 36 | 37 | There are no spending conditions on deposits other than a valid signature from the owner of the UTXO. The owner of the deposit must be provided as it is needed to compute the unique [deposit ID](./Deposits.md). 38 | 39 | InputHTLC 40 | --- 41 | 42 | | name | type | size | description | 43 | | -------------- | ----------- | ---- | ------------------------------------------------------------ | 44 | | `type` | `InputType` | 1 | `InputType.HTLC`. | 45 | | `witnessIndex` | `uint8` | 1 | Index of witness that authorizes spending the state element. | 46 | | `preImage` | `bytes32` | 32 | Preimage of digest if spending through hashlock. | 47 | 48 | HTLC UTXOs require a valid signature from the owner of the UTXO. In addition, if using the hashlock condition, the preimage must be provided. If using the timelock condition, HTLC UTXOs are only spendable after the [output](./Outputs.md)'s timelock has expired. 49 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/1. Data Structures/Metadata.md: -------------------------------------------------------------------------------- 1 | Metadata 2 | === 3 | 4 | Each [transaction](./Transactions.md) can have metadata attached to it by the block producer. One metadata is attached per [input](./Inputs.md). This allows for fraud proofs without state commitments. (See also: [Compact Fraud Proofs for UTXO Chains Without Intermediate State Serialization](https://ethresear.ch/t/compact-fraud-proofs-for-utxo-chains-without-intermediate-state-serialization/5885).) 5 | 6 | Note that all metadata objects are exactly `8` bytes. 7 | 8 | Metadata 9 | --- 10 | 11 | | name | type | size | description | 12 | | ------------------ | -------- | ---- | ---------------------------- | 13 | | `blockHeight` | `uint32` | 4 | Rollup block height. | 14 | | `rootIndex` | `uint8` | 1 | Root index in block. | 15 | | `transactionIndex` | `uint16` | 2 | Transaction index in root. | 16 | | `outputIndex` | `uint8` | 1 | Output index in transaction. | 17 | 18 | Metadata uniquely identifies an exact [output](./Outputs.md) in the ledger, first by the [block height](./Blocks.md), then the [root](./Roots.md), [transaction index](./Roots.md), and finally [output index](./Transactions.md). Essentially, metadata "references" an exact output. This allows for both compact fraud proofs without serializing the state, leveraging the property that UTXOs are produced and consumed at most once, and smaller transaction payloads than using [UTXO IDs](./Outputs.md) directly (a 32-byte hash). 19 | 20 | MetadataDeposit 21 | --- 22 | 23 | | name | type | size | description | 24 | | ------------- | -------- | ---- | ---------------------- | 25 | | `token` | `uint32` | 4 | Token ID. | 26 | | `blockNumber` | `uint32` | 4 | Ethereum block number. | 27 | 28 | Deposit metadata partially uniquely identifies a [deposit](Deposits.md). The last part of the deposit registry key is the owner address, which can be recovered from the witness (of valid transactions). 29 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/1. Data Structures/Outputs.md: -------------------------------------------------------------------------------- 1 | Outputs 2 | === 3 | 4 | Outputs define which state elements (usually: UTXOs) are produced by a [transaction](./Transactions.md). Each state element can be produced and consumed at most once. 5 | 6 | OutputType 7 | --- 8 | 9 | ``` 10 | enum OutputType : uint8 { 11 | Transfer = 0, 12 | Withdraw = 1, 13 | HTLC = 2, 14 | Return = 3, 15 | } 16 | ``` 17 | 18 | Output 19 | --- 20 | 21 | | name | type | size | description | 22 | | --------------- | ------------ | ---- | ------------------------------------------------------------------------------------------------------------------ | 23 | | `type` | `OutputType` | 1 | `OutputType.Transfer` or `OutputType.Withdraw`. | 24 | | `token.length` | `uint8` | 1 | Next field number of bytes. | 25 | | `token` | `bytes1[]` | 1* | The token ID (`<= 4` bytes). See: [token registry](./Tokens.md). | 26 | | `amount.shift` | `uint8` | 1 | Amount shifted bytes. See: [serialization](../0.%20Fundamentals/5.%20Serialization.md). | 27 | | `amount.length` | `uint8` | 1 | Next field number of bytes. | 28 | | `amount` | `uint8[]` | 1* | Amount of tokens. See: [serialization](../0.%20Fundamentals/5.%20Serialization.md). | 29 | | `owner.length` | `uint8` | 1 | Next field number of bytes. | 30 | | `owner` | `bytes1[]` | 1* | Either address ID (`<= 19` bytes) or address (`= 20` bytes) of recipient. See: [address registry](./Addresses.md). | 31 | 32 | A simple transfer between two users on Fuel or a withdrawal from Fuel back to Ethereum. 33 | 34 | OutputHTLC 35 | --- 36 | 37 | | name | type | size | description | 38 | | -------------------- | ------------ | ---- | ------------------------------------------------------------------------------------------------------------------------------ | 39 | | `type` | `OutputType` | 1 | `OutputType.HTLC`. | 40 | | `token.length` | `uint8` | 1 | Next field number of bytes. | 41 | | `token` | `bytes1[]` | 1* | The token ID (`<= 4` bytes). See: [token registry](./Tokens.md). | 42 | | `amount.shift` | `uint8` | 1 | Amount shifted bytes. See: [serialization](../0.%20Fundamentals/5.%20Serialization.md). | 43 | | `amount.length` | `uint8` | 1 | Next field number of bytes. | 44 | | `amount` | `uint8[]` | 1* | Amount of tokens. See: [serialization](../0.%20Fundamentals/5.%20Serialization.md). | 45 | | `owner.length` | `uint8` | 1 | Next field number of bytes. | 46 | | `owner` | `bytes1[]` | 1* | Either address ID (`<= 19` bytes) or address (`= 20` bytes) of recipient. See: [address registry](./Addresses.md). | 47 | | `digest` | `bytes32` | 32 | Hashlock digest. The preimage to this digest must be revealed to spend this output. | 48 | | `expiry` | `uint32` | 4 | Timelock as an Ethereum block number. | 49 | | `returnOwner.length` | `uint8` | 1 | Next field number of bytes. | 50 | | `returnOwner` | `bytes1[]` | 1* | Either address ID (`<= 19` bytes) or address (`= 20` bytes) of owner if HTLC expires. See: [address registry](./Addresses.md). | 51 | 52 | The timelock expiry is an _absolute_ Ethereum block number. Any rollup block committed _at or after_ this Ethereum block number can spend the UTXO with the timelock condition. 53 | 54 | See also: [HTLC explainer on Bitcoin Wiki](https://en.bitcoin.it/wiki/Hash_Time_Locked_Contracts). 55 | 56 | OutputReturn 57 | --- 58 | 59 | | name | type | size | description | 60 | | ------------- | ------------ | ---- | -------------------------------------------------- | 61 | | `type` | `OutputType` | 1 | `OutputType.Return`. | 62 | | `data.length` | `uint16` | 2 | Next field number of bytes. | 63 | | `data` | `bytes1[]` | 1* | Data blob. Between `1` and `512` bytes, inclusive. | 64 | 65 | Return outputs are provably prunable, i.e. they are not inserted into the state (the UTXO set). They can be used to record and timestamp arbitrary information to the Fuel chain, useful for building applications with client-side execution. 66 | 67 | See also: [Bitcoin's OP_RETURN](https://en.bitcoin.it/wiki/OP_RETURN). 68 | 69 | UTXO 70 | --- 71 | 72 | | name | type | size | description | 73 | | --------------- | --------- | ---- | ------------------------------------------------------------------------------------------ | 74 | | `transactionId` | `bytes32` | 32 | [Transaction ID](./Transactions.md), the hash of the serialized unsigned transaction data. | 75 | | `outputIndex` | `uint256` | 32 | Index of output in transaction. | 76 | | `outputType` | `uint256` | 32 | Output's type. | 77 | | `owner` | `bytes32` | 32 | Owner of UTXO, either a raw address or an [address ID](./Addresses.md). | 78 | | `amount` | `uint256` | 32 | Amount of tokens. | 79 | | `token` | `uint256` | 32 | [Token ID](./Tokens.md). | 80 | | `digest` | `bytes32` | 32 | HTLC only: hashlock. | 81 | | `expiry` | `uint256` | 32 | HTLC only: timelock. | 82 | | `returnOwner` | `bytes32` | 32 | HTLC only: return owner. | 83 | 84 | The UTXO ID is simply the hash of the UTXO. 85 | 86 | The HTLC-only fields are set to zero (`0`) if the output is not an HTLC output. 87 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/1. Data Structures/Roots.md: -------------------------------------------------------------------------------- 1 | Roots 2 | === 3 | 4 | RootHeader 5 | --- 6 | 7 | | name | type | size | description | 8 | | ---------------- | --------- | ---- | ----------------------------------------------------------------- | 9 | | `rootProducer` | `address` | 20 | Address of root producer. | 10 | | `merkleTreeRoot` | `bytes32` | 32 | Claimed Merkle root of list of [transactions](./Transactions.md). | 11 | | `commitmentHash` | `bytes32` | 32 | Simple hash of list of [transactions](./Transactions.md). | 12 | | `rootLength` | `uint256` | 32 | Number of roots. | 13 | | `feeToken` | `uint256` | 32 | [Token ID](./Tokens.md) of all fees paid in this root. | 14 | | `fee` | `uint256` | 32 | Feerate of all fees paid in this root. | 15 | 16 | Each _root header_ commits to a list of transactions. Each _root_ is a root header and a list of transactions (and does not exist as a canonical data structure). [Blocks](./Blocks.md) contain one or more root header hashes (i.e. hashes of root headers), and so implicitly commit to a list of transactions. For more information of why multiple roots are used instead of the more traditional single-transactions-root, see [Block Architecture](../0.%20Fundamentals/3.%20Block%20Architecture.md). 17 | 18 | When committing a new root to the contract, the root header minus the `commitmentHash` is provided, along with a list of transactions. The `commitmentHash` is then computed by simply hashing the list of transactions. This means that root headers _claim_ a Merkle root of their transactions, which is assumed to be correct optimistically to save gas. If the claimed Merkle root is incorrect, [a fraud proof](../3.%20Provers/Malformed%20Block.md) can be constructed to show this. 19 | 20 | The maximum size in bytes of the list of transactions in a single root is the `MAX_ROOT_SIZE` parameter (`57600`). This limit is placed to ensure that the transactions can always be Merkleized within the gas limit of a single Ethereum block in a fraud proof. 21 | 22 | The maximum number of transactions in a single root is the `MAX_TRANSACTIONS_IN_ROOT` parameter (`2048`). 23 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/1. Data Structures/Tokens.md: -------------------------------------------------------------------------------- 1 | Tokens 2 | === 3 | 4 | The token registry maintains a mapping of token contract address (20 bytes) to token ID (unsigned integer up to and including 4 bytes). Each time a new token is registered, it is assigned the next token ID in sequence. 5 | 6 | New tokens deposited to the contract are automatically assigned a new token ID without any additional interaction. 7 | 8 | Native ether (ETH) has token ID `0`. 9 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/1. Data Structures/Transactions.md: -------------------------------------------------------------------------------- 1 | Transactions 2 | === 3 | 4 | Transactions consume [inputs](./Inputs.md) and produce [outputs](./Outputs.md). 5 | 6 | UnsignedTransaction 7 | --- 8 | 9 | | name | type | size | description | 10 | | ------------------- | ----------- | ---- | -------------------------------------------- | 11 | | `inputs.length` | `uint16` | 2 | Next field number of bytes. | 12 | | `inputs` | `bytes1[]` | 1* | List of [inputs](./Inputs.md). | 13 | | `outputs.length` | `uint16` | 2 | Next field number of bytes. | 14 | | `outputs` | `bytes1[]` | 1* | List of [outputs](./Outputs.md). | 15 | | `data.length` | `uint8` | 1 | Next field number of elements. | 16 | | `data` | `bytes32[]` | 32* | Implicit unique identifier of what to spend. | 17 | | `signatureFeeToken` | `uint256` | 32 | Implicit [fee token ID](./Roots.md). | 18 | | `signatureFee` | `uint256` | 32 | Implicit [fee rate](./Roots.md). | 19 | 20 | Transaction data that is signed off-chain. The unsigned transaction data is [serialized](../0.%20Fundamentals/5.%20Serialization.md) then hashed to get a unique transaction ID, which is then signed over to get a [witness](./Witness.md). Essentially, each witness authorizes an _entire_ transaction. This scheme avoids the [quadratic hashing issue present in Bitcoin](https://bitcointalk.org/index.php?topic=102487.0). 21 | 22 | Implicit data (`data`) is one 32-byte hash _per input_, and uniquely identifies what is being spent by that input (a [UTXO ID](./Outputs.md) or a [deposit ID](./Deposits.md)). 23 | 24 | The transaction ID is the [EIP-712 hash](../0.%20Fundamentals/5.%20Serialization.md) of the hash of the [serialized](../0.%20Fundamentals/5.%20Serialization.md) unsigned transaction data. 25 | 26 | TransactionLeaf 27 | --- 28 | 29 | | name | type | size | description | 30 | | ------------------ | ---------- | ---- | ---------------------------------- | 31 | | `length` | `uint16` | 2 | Total length of leaf in bytes. | 32 | | `metadata.length` | `uint8` | 1 | Next field number of elements. | 33 | | `metadata` | `bytes8[]` | 8* | List of metadata, one per input. | 34 | | `witnesses.length` | `uint16` | 2 | Next field number of bytes. | 35 | | `witnesses` | `bytes1[]` | 1* | List of [witnesses](./Witness.md). | 36 | | `inputs.length` | `uint16` | 2 | Next field number of bytes. | 37 | | `inputs` | `bytes1[]` | 1* | List of [inputs](./Inputs.md). | 38 | | `outputs.length` | `uint16` | 2 | Next field number of bytes. | 39 | | `outputs` | `bytes1[]` | 1* | List of [outputs](./Outputs.md). | 40 | 41 | A leaf in a transaction [Merkle tree](./../2.%20Verifiers/Merkle%20Proof.md), which is committed to in a [root](./Roots.md). 42 | 43 | Note that the implicit data is not included in the leaf, as it can be reconstructed from metadata. Rather, the root producer replaces the larger data (state element) with the smaller metadata (a pointer to an entry in the ledger or a deposit). 44 | 45 | Note that the implicit fee token ID and feerate are not included in the leaf. Since the value of those fields must be identical for all transaction under a root, they can be hoisted and declared once [at the root header level](./Roots.md). 46 | 47 | The minimum transaction leaf size in bytes is set by the parameter `TRANSACTION_SIZE_MIN` (`44`). 48 | The maximum transaction leaf size in bytes is set by the parameter `TRANSACTION_SIZE_MAX` (`896`). 49 | The maximum number of inputs in a single transaction is `INPUTS_MAX` (`8`). 50 | The maximum number of outputs in a single transaction is `OUTPUTS_MAX` (`8`). 51 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/1. Data Structures/Withdrawals.md: -------------------------------------------------------------------------------- 1 | Withdrawals 2 | === 3 | 4 | Withdrawal Metadata 5 | --- 6 | 7 | | name | padded type | compact type | size | description | 8 | | --------------------- | ----------- | ------------ | ---- | -------------------------------------------------------------------------- | 9 | | `rootIndex` | `uint256` | `uint32` | 4 | Index of root in list of roots. | 10 | | `transactionLeafHash` | `bytes32` | `bytes32` | 32 | Hash of transaction leaf in tree rooted at `rootIndex`. | 11 | | `outputIndex` | `bytes32` | `uint8` | 1 | Index of output in list of outputs of transaction in the transaction leaf. | 12 | 13 | Withdrawal metadata is represented in padded form on Ethereum to simplify processing, and compact form on Fuel. The ID of a withdrawal is the hash of the padded-form withdrawal metadata. 14 | 15 | A withdrawal registry keep track of whether a withdrawal has been processed or not (a Boolean value), indexed by the rollup block height and unique withdrawal ID. "Processed" withdrawals are completed withdrawals (i.e. the tokens have been withdrawn from the contract). 16 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/1. Data Structures/Witness.md: -------------------------------------------------------------------------------- 1 | Witness 2 | === 3 | 4 | WitnessType 5 | --- 6 | 7 | ``` 8 | enum WitnessType : uint8 { 9 | Signature = 0, 10 | Caller = 1, 11 | Producer = 2, 12 | } 13 | ``` 14 | 15 | Witnesses come in different types, depending on the origin of the authorization. 16 | 17 | Signature 18 | --- 19 | 20 | | name | type | size | description | 21 | | ------ | ------------- | ---- | -------------------- | 22 | | `type` | `WitnessType` | 1 | Witness type. | 23 | | `r` | `bytes32` | 32 | Signature `r` value. | 24 | | `s` | `bytes32` | 32 | Signature `s` value. | 25 | | `v` | `uint8` | 1 | Signature `v` value. | 26 | 27 | This is a normal signature that signs over the [transaction ID](./Transactions.md) to authorize. 28 | 29 | See: [EIP-155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md). 30 | 31 | Caller 32 | --- 33 | 34 | | name | type | size | description | 35 | | ------------- | ------------- | ---- | ------------------------------------------------ | 36 | | `type` | `WitnessType` | 1 | Witness type. | 37 | | `owner` | `address` | 20 | Caller address. | 38 | | `blockNumber` | `uint32` | 4 | Ethereum block number witness was registered at. | 39 | 40 | This witness type is for when a contract on Ethereum authorizes a Fuel transaction. One use is smart contract wallets, rather than externally-owned accounts, authorizing transactions. 41 | 42 | Caller witnesses in the witness registry are indexed by owner and block number. 43 | 44 | Producer 45 | --- 46 | 47 | | name | type | size | description | 48 | | ------ | ------------- | ---- | ------------------------------- | 49 | | `type` | `WitnessType` | 1 | Witness type. | 50 | | `hash` | `bytes32` | 32 | Transaction ID being witnessed. | 51 | 52 | Block producers can spend fee outputs (i.e. [Root outputs](./Roots.md)) in blocks they produce without an explicit signature. 53 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/2. Verifiers/Block Header.md: -------------------------------------------------------------------------------- 1 | Verifier: Block Headers 2 | === 3 | 4 | Validates the [block header](../1.%20Data%20Structures/Blocks.md) component of a [transaction proof](./Transaction%20Proof.md) is properly formatted. 5 | 6 | 1. The hash of the block header must be the block hash at `proof.blockHeader.blockHeight`. 7 | 1. If checking for finalizable block, then: 8 | 1. The current block number must be at least the block number `proof.blockHeader.blockNumber`. 9 | 1. If checking for not-finalizable block, then: 10 | 1. The current block number must be less than the block number `proof.blockHeader.blockNumber`. 11 | 12 | Additional checks must pass if the [root header](./../1.%20Data%20Structures/Roots.md) component of a transaction proof is also being validated at the same time. 13 | 14 | 1. The root index `proof.rootIndex` must be less than the number of roots `proof.blockHeader.roots.length`. 15 | 1. The hash of the root header `proof.rootHeader` must match the root header at index `proof.rootIndex`. 16 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/2. Verifiers/Data.md: -------------------------------------------------------------------------------- 1 | Verifier: Data 2 | === 3 | 4 | Validates the [data](./../1.%20Data%20Structures/Transactions.md) component of a [transaction proof](./Transaction%20Proof.md) is properly formatted. 5 | 6 | The data field in an [unsigned transaction](./../1.%20Data%20Structures/Transactions.md) is a list of the unique state elements that are being consumed by the inputs. Since the key for these state elements (a hash) commits to sufficient information to verify their values, we simply need to provide the preimage to each hash. 7 | 8 | For each provided state element `stateElement` and each data `data` in the list of proof data `proof.data`: 9 | 1. The hash of `stateElement` must match `data`. 10 | 11 | Note that `stateElement` can come in [different types](./Inputs.md), depending on the type of the input (i.e. what is being spent). 12 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/2. Verifiers/Inputs.md: -------------------------------------------------------------------------------- 1 | Verifier: Inputs 2 | === 3 | 4 | Validates the [inputs](../2.%20Verifiers/Inputs.md) component of a [transaction proof](./Transaction%20Proof.md) is properly formatted. 5 | 6 | One additional proof per input in the primary transaction proof `proof` must be provided, the list `inputProofs`. 7 | 8 | For each input in `proof.transaction.inputs` and `inputProof` in `inputProofs`, indexed by `index`: 9 | 1. If input's [type](../1.%20Data%20Structures/Inputs.md) is `Transfer` or `HTLC`: 10 | 1. The transaction proof `inputProof` must be [validated](./Transaction%20Proof.md). 11 | 1. The output metadata of `inputProof` must match the metadata of input (i.e. they must be pointing to the same entry in the ledger). 12 | 1. The UTXO ID being produced by the output of `inputProof` must match `proof.data[index]`. 13 | 1. If input's [type](../1.%20Data%20Structures/Inputs.md) is `Deposit`: 14 | 1. The deposit object `inputProof` must be validated: 15 | 1. The [deposit ID](./../1.%20Data%20Structures/Deposits.md) of `inputProof` must match `proof.data[index]`. 16 | 1. If input's [type](../1.%20Data%20Structures/Inputs.md) is `Root`: 17 | 1. The transaction proof `inputProof` must be [validated](./Transaction%20Proof.md). 18 | 1. The UTXO ID being produced by the output of `inputProof` must match `proof.data[index]`. 19 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/2. Verifiers/Merkle Proof.md: -------------------------------------------------------------------------------- 1 | Verifier: Merkle Proofs 2 | === 3 | 4 | [Verifies the Merkle proof](https://crypto.stackexchange.com/questions/31871/what-is-the-canonical-way-of-creating-merkle-tree-branches) component of a [transaction proof](./Transaction%20Proof.md). 5 | 6 | 1. The tree height `proof.merkleProof.length` must be less than `MERKLE_TREE_HEIGHT_MAX` (`256`). 7 | 1. Hash transaction leaf `proof.transaction` to get current hash as the leaf hash. 8 | 1. For height `i` between `0` and ``proof.merkleProof.length - 1`: 9 | 1. Hash the current hash with its sibling from the Merkle proof. If the `i`th bit of `proof.transactionIndex` is `0`, the sibling is on the right. If it's `1`, the sibling is on the left. 10 | 1. The resultant Merkle root must match `proof.rootHeader.merkleTreeRoot`. 11 | 12 | Note: when constructing the tree, the number of nodes at a given level may not be even. In such case, the default value `EMPTY_LEAF_HASH` (`0x0000000000000000000000000000000000000000000000000000000000000000`) is used as the sibling hash value. 13 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/2. Verifiers/Transaction Proof.md: -------------------------------------------------------------------------------- 1 | Verifier: Transaction Proofs 2 | === 3 | 4 | Validates a transaction proof is properly formatted. 5 | 6 | 1. The header of the transaction proof [must be valid](./Block%20Header.md). 7 | 1. The Merkle proof of the transaction proof [must be valid](./Merkle%20Proof.md). 8 | 1. The length of the transaction leaf `transaction.length` must be greater than `0`. 9 | 10 | TransactionProof 11 | --- 12 | 13 | | name | type | size | description | 14 | | -------------------- | -------------------------------------------------------------- | -------- | ------------------------------------------------------------------------ | 15 | | `blockHeader` | [BlockHeader](../1.%20Data%20Structures/Blocks.md) | variable | Block header substructure. | 16 | | `rootHeader` | [RootHeader](../1.%20Data%20Structures/Roots.md) | variable | Root header substructure. | 17 | | `rootIndex` | `uint16` | 2 | Root index. | 18 | | `merkleProof.length` | `uint16` | 2 | Number of nodes in Merkle proof. | 19 | | `merkleProof` | `bytes32[]` | 32* | [Merkle inclusion proof](./Merkle%20Proof.md). | 20 | | `inputIndex` | `uint8` | 1 | Input index. | 21 | | `outputIndex` | `uint8` | 1 | Output index. | 22 | | `transactionIndex` | `uint16` | 2 | Transaction index. | 23 | | `transaction` | [TransactionLeaf](./../1.%20Data%20Structures/Transactions.md) | variable | Transaction leaf substructure. | 24 | | `data.length` | `uint8` | 1 | Next field number of elements. | 25 | | `data` | `bytes32[]` | 32* | List of state elements being spent. | 26 | | `signatureFeeToken` | `uint256` | 32 | Implicit [fee token ID](../1.%20Data%20Structures/Roots.md). | 27 | | `signatureFee` | `uint256` | 32 | Implicit [fee rate](./../1.%20Data%20Structures/Roots.md). | 28 | | `token` | `address` | 20 | Token address, used for [invalid sum](../3.%20Provers/Invalid%20Sum.md). | 29 | | `returnOwner` | `address` | 20 | For HTLC outputs only, the return owner. | 30 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/2. Verifiers/Witness.md: -------------------------------------------------------------------------------- 1 | Verifier: Witnesses 2 | === 3 | 4 | Validates the [witness](../1.%20Data%20Structures/Witness.md) component of a [transaction proof](./Transaction%20Proof.md) is properly formatted. 5 | 6 | This is needed to ensure that the preimage to the transaction ID provided in the transaction proof `proof` (i.e. the [unsigned transaction](./../1.%20Data%20Structures/Transactions.md)) is actually valid. [Data](./../1.%20Data%20Structures/Transactions.md) is elided when being posting transactions to Ethereum, so the integrity of the data provided in the proof must be checked. 7 | 8 | For the provided state element `stateElement`, `witness = proof.transaction.witnesses[0]`, and `input = proof.transaction.inputs[0]`: 9 | 1. If `witness`'s type is `Signature`: 10 | 1. Recover the address with signature `witness` and the transaction ID of computed from `proof.transaction` and `proof.data[0]` as message. 11 | 1. If `input`'s [type](../1.%20Data%20Structures/Inputs.md) is `Transfer` or `HTLC`: 12 | 1. The recovered address must match `stateElement.owner`. 13 | 1. If `input`'s [type](../1.%20Data%20Structures/Inputs.md) is `Deposit`: 14 | 1. The recovered address must match `stateElement.owner`. 15 | 1. If `input`'s [type](../1.%20Data%20Structures/Inputs.md) is `Root`: 16 | 1. The recovered address must match `proof.blockProducer`. 17 | 1. If `witness`'s type is `Caller`: 18 | 1. The [witness registered](../1.%20Data%20Structures/Witness.md) indexed by `stateElement.owner` and `stateElement.blockNumber` must match the transaction ID of computed from `proof.transaction` and `proof.data[0]` 19 | 1. If `witness`'s type is `Producer`: 20 | 1. The `stateElement.hash` must match the transaction ID of computed from `proof.transaction` and `proof.data[0]`. 21 | 22 | Note that `stateElement` can come in [different types](./Inputs.md), depending on the type of the input (i.e. what is being spent). 23 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/3. Provers/Double Spend.md: -------------------------------------------------------------------------------- 1 | Prover: Double Spends 2 | === 3 | 4 | Proves that a double spend occurred. 5 | 6 | Two valid [transaction proofs](../2.%20Verifiers/Transaction%20Proof.md) must be provided. 7 | 1. The input metadata for each transaction proof must be different. 8 | 1. The referenced input metadata (i.e. the spent state element) for each transaction proof must match. 9 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/3. Provers/Invalid Input.md: -------------------------------------------------------------------------------- 1 | Prover: Invalid Inputs 2 | === 3 | 4 | Proves that an [input](./../1.%20Data%20Structures/Inputs.md) was invalid, i.e. a non-existent state element was spent. 5 | 6 | A valid [transaction proof](../2.%20Verifiers/Transaction%20Proof.md), `proof`, must be provided. In addition, a valid [transaction proof block header](././../2.%20Verifiers/Block%20Header.md) for the output being spent, `inputProof` must be provided. Since this output might not exist, the transaction proof does not need to be valid, only the block header. 7 | 1. Get input `input` as `proof.transaction.inputs(proof.inputIndex)`. 8 | 1. If the input's [type](../1.%20Data%20Structures/Inputs.md) is `Deposit`: 9 | 1. The deposit with that [deposit ID](./../1.%20Data%20Structures/Deposits.md) must have amount of `0` (i.e. a non-deposit is being spent). 10 | 1. Get metadata `metadata` as `proof.transaction.metadata[proof.inputIndex]`. 11 | 1. The metadata's root index `metadata.rootIndex` must be at least `inputProof.rootHeader.rootLength` (i.e. metadata root index out of bounds). 12 | 1. If the input's [type](../1.%20Data%20Structures/Inputs.md) is `Transfer` or `HTLC`: 13 | 1. If the input proof is for the rightmost leaf in the root's transaction tree, then the metadata's transaction index `metadata.transactionIndex` must be greater than `inputProof.transactionIndex`. It's impossible to provide an inclusion proof for an out-of-bounds transaction, so this check serves as a check for this condition. 14 | 1. The transaction leaf must be non-empty, i.e. `inputProof.transaction.length` must be greater than `0`. 15 | 1. The metadata's output index `metadata.outputIndex` must be at least `inputProof.transaction.outputs.length()` (i.e. metadata output index out of bounds). 16 | 1. The output's [type](./../1.%20Data%20Structures/Outputs.md) must be `Withdraw` or `Return` (i.e. spending a [non-spendable output](../1.%20Data%20Structures/Outputs.md)). 17 | 1. If the input's [type](../1.%20Data%20Structures/Inputs.md) is `Transfer`: 18 | 1. The output's type must not be `Transfer` (i.e. type mismatch). 19 | 1. If the input's [type](../1.%20Data%20Structures/Inputs.md) is `HTLC`: 20 | 1. The output's type must not be `HTLC` (i.e. type mismatch). 21 | 1. If `proof.blockHeader.blockNumber` is less than `inputProof.transaction.outputs(inputProof.outputIndex).expiry` (i.e. the timelock has not expired): 22 | 1. The hashlock digest `inputProof.transaction.outputs(inputProof.outputIndex).digest` must not match the hash of the preimage `input.preImage` (i.e. invalid preimage). 23 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/3. Provers/Invalid Sum.md: -------------------------------------------------------------------------------- 1 | Prover: Invalid Sums 2 | === 3 | 4 | Proves that a transaction spent more than allowed (i.e. sum of outputs > sum of inputs + fees). 5 | 6 | A valid [transaction proof](../2.%20Verifiers/Transaction%20Proof.md), must be provided. The proof's [witness must also be valid](./../2.%20Verifiers/Witness.md). The proof's [data must also be valid](../2.%20Verifiers/Data.md). 7 | 1. For the provided token ID, the sum of the inputs must be greater than the sum of the outputs plus fees. 8 | 1. Fees for a transaction are calculated as the feerate `proof.fee` times the transaction leaf length `proof.transaction.length`. 9 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/3. Provers/Invalid Transaction.md: -------------------------------------------------------------------------------- 1 | Prover: Invalid Transactions 2 | === 3 | 4 | Proves that a transaction was malformed. This involves attempting to parse the transaction leaf. 5 | 6 | A valid [transaction proof](../2.%20Verifiers/Transaction%20Proof.md), `proof`, must be provided. 7 | 1. Get the transaction leaf component of the proof, `leaf = proof.transaction`. 8 | 1. Metadata count `leaf.metadata.length` must be less than `0` or more than [`INPUTS_MAX`](../1.%20Data%20Structures/Transactions.md). 9 | 1. As a sanity check, witnesses length in bytes `leaf.witnesses.length` must be less than `0` or more than `TRANSACTION_SIZE_MAX`. Same for inputs length `leaf.inputs.length` and outputs length `leaf.outputs.length`. 10 | 1. The leaf length `leaf.length` must be at less than [`TRANSACTION_SIZE_MIN`](../1.%20Data%20Structures/Transactions.md) or more than [`TRANSACTION_SIZE_MAX`](../1.%20Data%20Structures/Transactions.md). 11 | 1. The leaf total length `leaf.length+2` (since the `leaf.length` field itself [is `2` bytes](../1.%20Data%20Structures/Transactions.md)) must not match that size of the leaf component of the proof. 12 | 13 | The witnesses are parsed: 14 | 1. For each witness, shift by the length of the witness: 15 | 1. If the witness type is `Caller`: 16 | 1. The transaction ID from the [witness registry](../1.%20Data%20Structures/Witness.md) at the witness ID must be `0` (i.e. the witness has not bee registered). 17 | 1. The block number of the witness must be at least the block number in `proof` (i.e. the witness was not registered _strictly before_ the block was committed). 18 | 1. The number of parsed witnesses must be greater than [`INPUTS_MAX`](../1.%20Data%20Structures/Transactions.md). 19 | 1. The parsed length of witnesses must not match `leaf.witnesses.length`. 20 | 21 | The inputs are parsed: 22 | 1. For each input, shift by the length of the input: 23 | 1. The input type must be out of [bounds](../1.%20Data%20Structures/Inputs.md). 24 | 1. The witness reference index `input.witnessIndex` must be out of bounds (i.e. at least the number of witnesses). 25 | 1. The number of parsed inputs must be greater than [`INPUTS_MAX`](../1.%20Data%20Structures/Transactions.md). 26 | 1. The parsed length of inputs must not match `leaf.inputs.length`. 27 | 28 | The outputs are parsed: 29 | 1. For each output, shift by the length of the output: 30 | 1. The output type must be out of [bounds](../1.%20Data%20Structures/Outputs.md). 31 | 1. If the output type is `Transfer`, `Withdraw`, or `HTLC`: 32 | 1. The output [token and amount fields](../1.%20Data%20Structures/Outputs.md) must be out of bounds. 33 | 1. The output [owner field](../1.%20Data%20Structures/Outputs.md) must be out of bounds. 34 | 1. If the output type is `HTLC`: 35 | 1. the output [return owner field](../1.%20Data%20Structures/Outputs.md) must be out of bounds. 36 | 1. If the output type is `Return`: 37 | 1. The data length must be out of [bounds](../1.%20Data%20Structures/Outputs.md). 38 | 1. The number of parsed outputs must be greater than [`OUTPUTS_MAX`](../1.%20Data%20Structures/Transactions.md). 39 | 1. The parsed length of outputs must not match `leaf.outputs.length`. 40 | 41 | The sizes are parsed: 42 | 1. The number of metadata elements must not match the number of inputs. 43 | 44 | The metadata are parsed: 45 | 1. For each metadata, shift by [the length of the metadata](../1.%20Data%20Structures/Metadata.md): 46 | 1. The metadata [fields](../1.%20Data%20Structures/Metadata.md) must be out of bounds. 47 | 1. The parsed length of metadata must not match `leaf.metadata.length`. 48 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/3. Provers/Invalid Witness.md: -------------------------------------------------------------------------------- 1 | Prover: Invalid Witnesses 2 | === 3 | 4 | Proves that a witness was invalid, and that a spend wasn't authorized. 5 | 6 | A [transaction proof](./../1.%20Data%20Structures/Transactions.md) with [valid inputs](./../2.%20Verifiers/Inputs.md) must be provided. In addition, a list of state elements (one for each input of the transaction) must be provided. 7 | 1. For each input: 8 | 1. The owner of the input must not match the owner of the corresponding state element. 9 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/3. Provers/Malformed Block.md: -------------------------------------------------------------------------------- 1 | Prover: Malformed Blocks 2 | === 3 | 4 | Proves that a [block](./../1.%20Data%20Structures/Blocks.md) was malformed. Given initial checks when [committing a new block](./../1.%20Data%20Structures/Blocks.md), the only case is when the Merkle root claimed in a [root header](./../1.%20Data%20Structures/Roots.md) is incorrectly computed. 5 | 6 | 1. A valid [block header](./../2.%20Verifiers/Block%20Header.md) and [root header](../1.%20Data%20Structures/Roots.md) must be provided, along with the original list of [transaction leaves](../1.%20Data%20Structures/Roots.md) committed to in the root header. 7 | 1. [Merkleizing](../2.%20Verifiers/Merkle%20Proof.md) the transaction leaves must not match the `merkleTreeRoot` field in the root header. 8 | -------------------------------------------------------------------------------- /src/v1.0.0/3. Concepts/4. Additional Modules/Funnels.md: -------------------------------------------------------------------------------- 1 | Token Funnels 2 | === 3 | 4 | The usual flow for using an [ERC-20 token](https://github.com/ethereum/EIPs/issues/20) with a contract is to first `approve` an amount of tokens to transfer, then use `transferFrom` to actually transfer the tokens. In addition to poor UX, this has a number of issues: 5 | 1. Approving with a non-zero approved balance [allows an adversary to front-run the approval](https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729) and essential double-transfer tokens. 6 | 1. Users transferring tokens directly to a contract with `transfer` lose them, as the contract has no way of processing the transfer. This has resulted in [millions of dollars being burned](https://github.com/ethereum/eips/issues/223) through user error. 7 | 8 | We provide a _token funnel_, a contract that can accept direct transfers magically. Intuitively, the funnel contract's deterministic [`CREATE2`](https://eips.ethereum.org/EIPS/eip-1014) address itself is a commitment to a deposit to Fuel (generally, the hash of: the sender address, the token type, and the token amount). After transferring tokens to this address, the funnel contract can be deployed at any time to transfer to deposit properly to Fuel, then immediately self-destruct. 9 | 10 | Readers familiar with Bitcoin might notice this bears many similarities to [Pay-to-Script-Hash](https://en.bitcoin.it/wiki/Pay_to_script_hash). 11 | 12 | Specific implementation details can be found [here](https://github.com/FuelLabs/fuel/blob/master/src/Funnel.yulp). 13 | -------------------------------------------------------------------------------- /src/v1.0.0/4. Tools and Applications/0. Fast Withdrawals.md: -------------------------------------------------------------------------------- 1 | Fast Withdrawals 2 | === 3 | 4 | Withdrawals must normally wait [`finalizationDelay`](../3.%20Concepts/0.%20Fundamentals/7.%20Deployment%20Parameters.md) Ethereum blocks until the rollup block they are included in is finalized, at which point the funds can be withdrawn. As the finalization delay is supposed to be set quite long to be robust against censorship attacks and short-term chain congestion, this leads to poor UX. We can do better! 5 | 6 | Fungible assets (ETH, ERC-20 tokens) can be withdrawn immediately with an [atomic swap](https://arxiv.org/abs/1801.09515) powered by [HTLCs](https://en.bitcoin.it/wiki/Hash_Time_Locked_Contracts), which is [one of the transaction output types](../3.%20Concepts/1.%20Data%20Structures/Outputs.md) Fuel supports. 7 | 8 | Liquidity providers can offer up liquidity to users wanting to withdraw quickly, in exchange for a fee. Unlike lending protocols that are popular in DeFi, liquidity providers for fast withdrawals have zero systemic risk if they fully validate Fuel blocks before accepting a swap, as [valid blocks are guaranteed to finalize and they can always catch invalid blocks](./../3.%20Concepts/0.%20Fundamentals/2.%20Security%20Analysis.md). 9 | -------------------------------------------------------------------------------- /src/v1.0.0/4. Tools and Applications/1. Token Minting.md: -------------------------------------------------------------------------------- 1 | Mass Token Minting 2 | === 3 | 4 | Minting and distributing tokens to a large number of users is a fairly common pattern, especially for community-driven applications and rewards or reputation points. Generally, tokens of this form are distributed in a permissioned manner by a central party, as un-gameable global reputation is non-trivial. However, once the tokens have been distributed they cannot be reclaimed by the issuer. 5 | 6 | While it is certainly possible to do this relatively inexpensively by using one-to-many transactions (as Fuel supports [up to eight inputs and eight outputs](../3.%20Concepts/0.%20Fundamentals/4.%20Transaction%20Architecture.md) per transactions), we can do even better! 7 | 8 | First, let us consider how one would make distributing such tokens cheaper on Ethereum today. There are two easy, concrete methods: 9 | 1. The issuer pre-signs an authorization to mint a certain number of tokens for a particular user. She then sends the user the pre-signed authorization, which the user can redeem to the token contract for tokens. In this case, the issuer does not pay anything to distribute the token, as gas costs are covered by the user. 10 | 1. The issuer posts a _commitment_ (e.g. a Merkle root) of new coin balances to the token contract, which is an `O(1)`-cost operation. Users can then withdraw their tokens with a Merkle inclusion proof. In this case, the issuer pays a constant cost to distribute tokens, regardless of the number of tokens or users. 11 | 12 | These schemes do not work on [Fuel v1](../5.%20Future%20Roadmap/1.%20Planned%20Features.md), as generic smart contracts are not supported. But what if we combined some of the aspects of the two approaches? 13 | 14 | | ![Token minting](/assets/images/fig_token_minting.png) | 15 | | :----------------------------------------------------: | 16 | | Pre-signed transaction tree. | 17 | 18 | The scheme is actually quite simple: 19 | 1. The issuer mints all the tokens at once on Ethereum, as a batch. 20 | 1. The tokens are deposited to Fuel. 21 | 1. The issuer now has a single UTXO (or rather, a deposit) with exactly the number of tokens they want to distribute. 22 | 1. The issuer recursively pre-signs transactions that split this UTXO into eight outputs _that are returned to the same address_. This forms a tree of pre-signed transactions, as shown in the diagram above. 23 | 1. Once the leaves are reached, each output is sent to the appropriate user's address. Users are then given the Merkle branch of pre-signed transactions to the transaction that would send them tokens. 24 | 1. A user that wishes to redeem their tokens broadcasts the branch of pre-signed transactions to Fuel (or, more specifically, the transactions that haven't yet been included on Fuel from potential previous users that do the same), then spends the appropriate output with a new (potentially fee-paying) transaction. 25 | 26 | > **Note:** The issuer does _not_ send the pre-signed transactions to Fuel. Indeed, the pre-signed transactions do not pay any fees and so would not be included barring out-of-bounds negotiation. Rather, the user pays fees for an entire branch of pre-signed transactions using [Child-Pays-For-Parent (CPFP)](https://en.bitcoin.it/wiki/Transaction_fees#Feerates_for_dependent_transactions_.28child-pays-for-parent.29). 27 | 28 | Readers familiar with Bitcoin's [CTV (BIP-119)](https://github.com/bitcoin/bips/blob/master/bip-0119.mediawiki) proposal should find this scheme very similar. However, rather than being enforced with on-chain rules, the commitment to a tree of transactions is simply an off-chain promise. 29 | 30 | > **Note:** The threat model for distributing _tokens_ in this manner is not necessarily weaker than that of using a contract on Ethereum to enforce some rules. In this mass token minting scheme, the issuer could double-spend their pre-signed transactions. Notice however that the issuer in any case could simply just _not issue_ the tokens in the first place, as distribution is permissioned, to the same effect. 31 | 32 | > **Note:** Equivalent functionality to [CTV (BIP-119)](https://github.com/bitcoin/bips/blob/master/bip-0119.mediawiki) is on the roadmap [as a future addition with covenants](../5.%20Future%20Roadmap/1.%20Planned%20Features.md). 33 | -------------------------------------------------------------------------------- /src/v1.0.0/4. Tools and Applications/2. Subscriptions.md: -------------------------------------------------------------------------------- 1 | Subscriptions 2 | === 3 | 4 | Recurring cancellable subscriptions can be accomplished through pre-signed transactions with [HTLCs](./../3.%20Concepts/1.%20Data%20Structures/Outputs.md). 5 | 6 | For a two-time recurring subscription, Alice can construct transactions as follows: 7 | 8 | | ![Subscription](/assets/images/fig_subscription.png) | 9 | | :--------------------------------------------------: | 10 | | Subscription pre-signed transactions. | 11 | 12 | Each pre-signed transaction spends the HTLC UTXO of its parent after the timelock expires (which is set to the subscription period, e.g. 1 month for a monthly subscription). The transaction burns a portion of this UTXO (or otherwise pays for the subscription), and outputs the remainder to a new HTLC whose timelock is offset by another period. At any time, Alice can cancel the recurring payments by spending the HTLC UTXO with the hashlock condition, which is set to return the funds to an address she controls. Her wallet stores the preimage, or it can even be deterministically generated from her private key, e.g. by signing over the subscription identifier. 13 | 14 | An additional output can be added to pay fees to the block producer, but that is an implementation detail. 15 | -------------------------------------------------------------------------------- /src/v1.0.0/4. Tools and Applications/3. Non-Custodial Exchanges.md: -------------------------------------------------------------------------------- 1 | Non-Custodial Exchanges 2 | === 3 | 4 | | ![Swap](/assets/images/fig_swaps.png) | 5 | | :-----------------------------------: | 6 | | Exchange settlement on Fuel. | 7 | 8 | Non-custodial exchanges can be built by anyone on top of Fuel today. The order book is kept, and matching is done, off-chain, with settlement of each order happening on Fuel as a multi-user transaction. 9 | 10 | In this example, Alice and Bob each consume one of their UTXOs in a transaction, which swaps the owner of each asset to produce two new UTXOs. (Fees and change are an implementation detail.) Note that since users sign over _an entire transaction_, there is no possibility of theft. Alice and Bob can each sign the transaction individually, and any time before the transaction is confirmed, can spend their UTXO in a different transaction to cancel the order. 11 | -------------------------------------------------------------------------------- /src/v1.0.0/5. Future Roadmap/1. Planned Features.md: -------------------------------------------------------------------------------- 1 | Roadmap 2 | === 3 | 4 | Fuel v0 5 | --- 6 | 7 | Released as testnet at the beginning of 2020 ([announcement](https://medium.com/@fuellabs/announcing-the-fuel-v0-open-beta-565a2d340fc3)). 8 | 9 | [Source code](https://github.com/FuelLabs/fuel-core). 10 | 11 | Features: 12 | - UTXO-based optimistic rollup 13 | - Support simple transfers, deposits, and withdrawals 14 | - [Burner wallet integration](https://medium.com/@fuellabs/burner-wallet-fuel-7b8ce8e54aff) 15 | - [Reddit community points transfer and swap demo](https://reddit.com/r/CryptoCurrency/comments/gonjm3/tldr_moons_and_bricks_go_brrr/) 16 | 17 | Fuel v1 18 | --- 19 | 20 | Current release, as testnet. 21 | 22 | [Source code](https://github.com/FuelLabs/fuel). 23 | 24 | Features in addition to [v0](#fuel-v0): 25 | - Optimize transaction format, reducing transaction sizes by ~50% 26 | - Contract refactoring in [Yul+](https://github.com/FuelLabs/yulp) for additional gas cost savings 27 | - Support HTLC and Return outputs 28 | - Extra module: Token funnel 29 | - Additional client-side applications: 30 | - mass token minting 31 | - liquidity provider for fast withdrawals 32 | - non-custodial exchange 33 | 34 | Fuel v1.5 35 | --- 36 | 37 | Future release, expected EOY 2020. 38 | 39 | Features in addition to [v1](#fuel-v1): 40 | - BLS signature aggregation (bringing TPS to 1,500-2,000) 41 | - Native NFT support 42 | - Optimistic mass migration 43 | 44 | Fuel v2 45 | --- 46 | 47 | Future released, expected 2021. 48 | 49 | Features in addition to [v1.5](#fuel-v15): 50 | - Predicate scripting 51 | - Covenants 52 | - Configurable state introspection (for Ethereum-style smart contracts) 53 | --------------------------------------------------------------------------------