Bing-Yang
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Introducing the FuelVM and Sway :::warning This note is mostly copied from the following references 1. [Exploring the FuelVM](https://medium.com/blockchain-capital-blog/exploring-the-fuelvm-86cf9ccdc159) 2. [Predicates in Sway](https://fuellabs.github.io/fuels-rs/v0.25.1/getting-started/predicates.html#predicates) 3. [What is Account Abstraction](https://www.argent.xyz/blog/wtf-is-account-abstraction/) 4. [The Fuel Rust SDK](https://fuellabs.github.io/fuels-rs/v0.31.0/) 5. [Solidity Bytecode and Opcode Basics](https://medium.com/@blockchain101/solidity-bytecode-and-opcode-basics-672e9b1a88c2) 6. [Geth, which implements DevP2P specifications in Go.](https://geth.ethereum.org/docs/interface/devp2p) 7. [Merkle Patricia Trie](https://medium.com/@chiqing/merkle-patricia-trie-explained-ae3ac6a7e123) 8. [The Fuel Book](https://fuellabs.github.io/fuel-docs/master/index.html) 9. [The Sway Programming Language](https://fuellabs.github.io/sway/v0.31.1/) 10. [FuelVM Bootcamp](https://www.youtube.com/watch?v=GKNuaFcPaXc) 11. [The Rust Programming Language](https://doc.rust-lang.org/book/) 12. [Fuel Website](https://www.fuel.network/) ::: <p float="left"> <img src="https://assets.website-files.com/62e273f312d561347ce33306/630500bd9e32db63fbd441ef_Fuel_MonolithicLayer_Labels_B_Compressed_Cropped-p-800.png" width="350" /> <img src="https://assets.website-files.com/62e273f312d561347ce33306/630500bed675d01bf02a75b5_Fuel_ModularLayer_Labels_Final_Compressed_cropped-p-800.png" width="350" /> </p> - Build by [Fuel Lab](https://www.fuel.network/) - Fuel Virtual Machine (FuelVM) - A fully purpose-built, custom virtual machine for executing smart contracts - Designed to be modular - It can plug in as the execution engine for any blockchain - [Fuel VM Specification](https://fuellabs.github.io/fuel-specs/master/vm/index.html) - Sway - A domain-specific language (DSL) for the (FuelVM) - Based on Rust, and includes syntax to leverage a blockchain VM without needlessly verbose boilerplate - [The Sway Programming Language](https://fuellabs.github.io/sway/v0.31.1/) # FuelVM ## What is the FuelVM? - Designed from the start to be easily fraud-provable - Can be used as the transaction execution layer for an optimistic rollup - Optimized to **better utilize hardware** to **increase the throughput** of transaction execution - UTXO based - Every transaction requires to explicitly define the UTXOs that it will touch - Execution engine can identify exactly what state every transaction touches - Able to find the transactions that are not contentious and parallelize them ## Why does the VM matter? - The VM is the operating system for the smart contract blockchain - All widely used smart contract chains today are using the same VM as Ethereum: the EVM - For the EVM, the bandwidth is cheap, the next bottleneck will be computational throughput ([reasons](https://medium.com/blockchain-capital-blog/exploring-the-fuelvm-86cf9ccdc159)) - Goal of FuelVM: execute transactions fast while keeping the underlying hardware requirements low enough for sufficient decentralization ## FuelVM’s Differentiators ### Execution + Validation Parallelization - The secret behind the FuelVM’s parallelizable virtual machine is its strict access lists - Require users (clients or wallets) to indicate which contract(s) their transaction will touch - [Transaction Layout](https://fuellabs.github.io/fuel-specs/master/protocol/tx_format/transaction.html) - Just list a few fields below | Field | Description | | --------------- | -------------------------------------------------------------------------------------------------------- | | **Inputs** | List of all contract UTXOs that the transaction will touch + data to unlock the UTXO or predicate script | | Outputs | Define the UTXOs that will be created | | Gas Information | gas price + gas limits | | Witnesses | metadata + digital signature for authorization | - The **inputs** lists all the UTXOs that will be consumed - Before executing any code, the VM is able to tell which contracts a transaction will touch - It can safely execute all other non-contentious state-accessing transactions in parallel <p float="left"> <img src="https://miro.medium.com/max/1100/1*1avkHndlTD9RhwMMYBaL7w.png" width="350" /> <img src="https://miro.medium.com/max/1100/1*nIXbEQkuMQ2p2g5GF-R9IQ.png" width="350" /> </p> - Transaction outputs are explicitly included for validation - In the process of asserting that a block that another node proposed was correct, there is no need to execute the overlapping transactions sequentially - Validation can happen fully in parallel regardless of state contention - When nodes are syncing the network, they can achieve even greater parallelization and can catch up faster ### Native Asset System - In the EVM, there is one native asset: ETH - All other assets are implemented via a smart contract that handles accounting for balances ([ERC20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/)) - In Fuel, developers are **free to implement assets** in smart contracts - FuelVM is allowed the to handle the assets natively - Advantages - Native asset manipulation is cheaper (in terms of gas) than manipulating state in a smart contract - This can be attributed to its running at lower-level primitives (UTXO system is used instead of manipulating storage) - Native assets have better UX - E.g., Sending ETH directly is much simpler than sending ERC20s (no need for setting approvals) - From [ERC777](https://eips.ethereum.org/EIPS/eip-777) > "The tokensReceived hook allows to send tokens to a contract and notify it in a single transaction, unlike ERC-20 which requires a double call (approve/transferFrom) to achieve this." - From [Native Support for Multiple Asset Types](https://fuellabs.github.io/sway/v0.31.1/blockchain-development/native_assets.html) in [The Sway Programming Language](https://fuellabs.github.io/sway/v0.31.1/) > "The FuelVM has built-in support for working with multiple assets. > > What does this mean in practice? > > As in the EVM, sending ETH to an address or contract is an operation built into the FuelVM, meaning it doesn't rely on the existence of some token smart contract to update balances to track ownership. > > However, unlike the EVM, the process for sending any native asset is the same. This means that while you would still need a smart contract to handle the minting and burning of fungible tokens, the sending and receiving of these tokens can be done independently of the token contract." ### Native Account Abstraction + Predicates - Account abstraction has been a hot topic of research and several attempts have been made at EIPs ([EIP-86](https://eips.ethereum.org/EIPS/eip-86), [EIP-2938](https://eips.ethereum.org/EIPS/eip-2938), [EIP-3074](https://eips.ethereum.org/EIPS/eip-3074), [EIP-4337](https://eips.ethereum.org/EIPS/eip-4337), [EIP-5003](https://eips.ethereum.org/EIPS/eip-5003)) - It is difficult to implement and upgrade Ethereum to support account abstraction - Due to the associated complexity - No engineering bandwidth - A long list of higher priority items - Many rollups have the opportunity to implement account abstraction from the start on their novel execution environments - FuelVM for example - Native account abstraction - [Predicates](https://fuellabs.github.io/fuels-rs/v0.25.1/getting-started/predicates.html#predicates) - A **predicate** is a pure (does not access state) contract script that simply returns a boolean (true or false) - UTXOs can be locked behind a predicate so they can only be spent whenever the conditions defined in the predicate are met - Users can set a transaction to execute only under certain conditions - Once the predicate is met, their transaction can automatically execute - Predicates can be pruned when they are destroyed, so they do not contribute to state bloat ### Multi-dimensional Resource Pricing - Resource pricing allows the system to charge users for consuming **work** from the nodes in the network - In the EVM, one of the most common reasons for the introduction of [EIPs](https://eips.ethereum.org/) has been for opcode re-pricing - Opcodes have hardcoded gas prices - The underlying price of resources do not scale proportionally to each other (historically, CPUs improve more rapidly than SSDs) - The FuelVM - Implements dynamic multi-resource pricing that can incentivize node runners to optimize their underlying hardware better while still optimizing for the maximum *utility per block* <p float="left"> <img src="https://miro.medium.com/max/1400/1*bLvTVR8HlGdSYIgoZvd8AQ.png" width="600" /> </p> - In this figure, one smart contract has significantly higher demand than others - With localized resource pricing, other contracts are not impacted to the same extent - A smart contract with a specific resource profile will be priced differently than another contract - For the NFT drop example, the hot contract might have a resource profile that is very storage intensive but very computationally cheap - Smart contracts that have high compute requirements relative to storage would not be as impacted by the noisy NFT drop - Example: An **extremely high storage load** on the system because of an event where many different NFTs are being minted simultaneously - **The fees are very low** because not all this traffic is happening on a single account - The per-account fee model does solve the hot partition problem for accounts but leaves scenarios where the system is not correctly pricing underlying resources, so **it can still lead to failures** - It is simply cleaner and more accurate to price the system based on the underlying hardware resources - Instead of trying to add a network-specific abstraction layer like accounts to base the multi-market resource pricing on ### State-bloat Considerations - Historically, SSDs do not improve as quickly as the state size is growing, so this cost will continue to impact the decentralization of the network. - From [A Theory of Ethereum State Size Management](https://hackmd.io/@vbuterin/state_size_management) >State refers to information that a node must hold in order to be able to process new incoming blocks and transactions. It is typically contrasted with history, information about past events which can be held for later rebroadcasting and archiving purposes, but is not strictly needed to continue to process the chain. - FuelVM - By a combination of appropriate resource pricing and a more clear data model for state pruning with the UTXO system, it will be able to keep the state under control, reducing the cost of running a node, which is equivalent to increasing the decentralization of the network ### Decentralization of the “sequencer” - The **sequencer** is a privileged node that is responsible for - Ordering transactions - Executing state transitions - Submitting the state root update along with compressed transaction information to L1 - A single **super-computer** responsible for sequencing can **execute more transactions per epoch than** a multitude of **smaller computers** redundantly executing the same sequence of transactions - Several key problems with this centralized sequence - Controlling the ordering of transactions is very profitable - MEV is one of the main sources of income for those who order blocks - A single party controlling ordering and MEV capture eventually leads to worse execution for users - A centralized sequencer can be a single point of failure both from an availability and regulatory perspective - If a single or a small number of organizations are running sequencers they can go down or be taken down. - A liveness risk to the network - A centralized sequencer may censor transactions on the L2 - The sequencer gets to choose whatever transactions and place them in any order during the construction of a block - This leads to the ability to censor - Sequencers can make inconsistent promises about the state of the chain to users of the rollup - The sequencer can make a misleading promise about some state of the L2 - Fast finality on the rollup is a trusted step - A sequencer can abuse this trust that leads users to do things they do not intend - How does Fuel solve these problems? - Fuel is not just a rollup or an L1 blockchain - It is a system that **simply applies state transitions** that can be posted to an L1 if configured as a rollup or operate in a network to achieve consensus as an L1. - The Fuel execution engine **does not care about consensus or transaction ordering** - Fuel is only responsible for applying the transactions as quickly as possible - Layer 2 tokenomics with decentralization is on-going - [A Token Model for Layer-2 Block Production](https://fuel-labs.ghost.io/token-model-layer-2-block-production/) >Rollups need new token models, and currently-deployed models have shortcomings. In this blog post we propose a new model for layer-2 block production. - It lays out a design for a token that helps decentralize block production by allowing rollups to tokenize block space scarcity through the right to collect fees as a block producer - Fee collection is only one portion of the income for block producers - MEV is another large portion of the income - **Similarly to block space scarcity, MEV income will also be tokenized via the right to produce blocks** ## The State Model: UTXO vs Account Based - The account model is more similar to a bank ledger - Naturally lead to hot pieces of state because every transaction is trying to access the same account - UTXOs can be likened to cash bills (IOTA DAG) - It is less contentious if designed correctly - Enables better parallelization and also can prevent state bloat by simplifying the process of state pruning - An example follows - UXTO: 2 cash transactions can happen at the same time and they don’t need to have any knowledge of each other - Acount-based: 2 account updates on a ledger, both transactions would have to update the same shared ledger <p float="left"> <img src="https://miro.medium.com/max/1100/1*sjfvqbqpQT_MLCe_HsPhNg.png" width="350" /> <img src="https://miro.medium.com/max/640/1*daR6MsOjX5wPl5BRyypIpA.png" width="350" /> </p> ## Summary of FuelVM - Unlike other L2s, Fuel has plans to decentralize the sequencer role from the start by designing the VM - Expensive hardware is not required to increase scale - FuelVM is flexible - It can be deployed in many environments, but the priority is to be Ethereum aligned as an Optimistic Rollup - Fuel’s UX will be much better than the EVM’s because of native and novel ways of interacting with the chain - Such as account abstraction, scripts, and predicates - The UTXO data model is naturally less contentious than the account data model and will lead to more parallelism AND less state bloat # Sway - Sway is a domain-specific language (DSL) for the Fuel Virtual Machine (FuelVM), a blockchain-optimized VM designed for the Fuel blockchain - Sway is based on [Rust](https://www.rust-lang.org/), and includes syntax to leverage a blockchain VM without needlessly verbose boilerplate ## Programing Type A Sway program itself has a **type**: it is either a **contract**, a **predicate**, a **script**, or a **library**. The first three of these things are all deployable to the blockchain. A library is simply a project designed for code reuse and is never directly deployed to the chain. ### Contracts - The program starts with a declaration of what program type it is. A contract must also either define or import an Application Binary Interface (ABI) declaration and implement it - It is considered good practice to define your ABI in a separate library and import it into your contract - This allows callers of your contract to simply import the ABI directly and use it in their scripts to call your contract - A contract example: ```rust library wallet_abi; abi Wallet { #[storage(read, write)] fn receive_funds(); #[storage(read, write)] fn send_funds(amount_to_send: u64, recipient_address: Address); } ``` ### Libraries - Libraries are defined using the library keyword at the beginning of a file, followed by a name so that they can be imported - The most prominent example of this is the [Sway Standard Library](https://fuellabs.github.io/sway/v0.31.1/introduction/standard_library.html) - A library example: ```rust library my_library; // library code ``` ### Scripts - A script is runnable bytecode on the chain which executes once to perform some task - It does not represent ownership of any resources and it cannot be called by a contract - A script can return a single value of any type. - Scripts are **state-aware** in that while they have no persistent storage (because they only exist during the transaction) they can call contracts and act based upon the returned values and results - A script example: ```rust script; use std::constants::ZERO_B256; use wallet_abi::Wallet; fn main() { let contract_address = 0x9299da6c73e6dc03eeabcce242bb347de3f5f56cd1c70926d76526d7ed199b8b; let caller = abi(Wallet, contract_address); let amount_to_send = 200; let recipient_address = Address::from(0x9299da6c73e6dc03eeabcce242bb347de3f5f56cd1c70926d76526d7ed199b8b); caller.send_funds { gas: 10000, coins: 0, asset_id: ZERO_B256, }(amount_to_send, recipient_address); } ``` ### Predicates - From the perspective of Sway, predicates are programs that return a Boolean value and which represent ownership of some resource upon execution to true - They have no access to contract storage - Here is a trivial predicate, which always evaluates to true: ```rust predicate; // All predicates require a main function which returns a Boolean value. fn main() -> bool { true } ``` - Debugging Predicates - Because they don't have any side effects (they are pure), predicates cannot create receipts. - They cannot have logging or create a stack backtrace - **There is no native way to debug them aside from using a single-stepping debugger** - The [fuel-debugger PR](https://github.com/FuelLabs/fuel-debugger/pull/1) is now merged - [Not released yet](https://docs.rs/forc-debugger/latest/forc_debugger/) - As a workaround, the predicate can be written, tested, and debugged first as a script, and then changed back into a predicate ## Blockchain Development with Sway - Hashing and Cryptography - The Sway standard library provides easy access to a selection of cryptographic hash functions (sha256 and EVM-compatible keccak256), and EVM-compatible secp256k1-based signature recovery operations - Contract Storage - **Persistent storage**, often just called storage in this context, is a place where you can store values that are persisted inside the contract itself - This is **in contrast to a regular value in memory**, which disappears after the contract exits - Contract storage is like saving data to a hard drive - That data is saved even after the program which saved it exits - Function Purity - A function is pure if it does not access any persistent storage - Conversely, the function is impure if it does access any storage - Naturally, as storage is only available in smart contracts, **impure functions cannot be used in predicates, scripts, or libraries** - A pure function cannot call an impure function - **In Sway, functions are pure by default** but can be opted into impurity via the storage function attribute - The storage attribute may take read and/or write arguments indicating which type of access the function requires - Identifiers - Addresses in Sway are similar to EVM addresses. The two major differences are: - Sway addresses are 32 bytes long (instead of 20) - Sway addresses are computed with the SHA-256 hash of the public key instead of the keccak-256 hash - Contracts, on the other hand, are uniquely identified with a contract ID rather than an address - A contract's ID is also 32 bytes long and is calculated [here](https://fuellabs.github.io/fuel-specs/master/protocol/id/contract) - Native Assets - As in the EVM, sending ETH to an address or contract is an operation built into the FuelVM, meaning it doesn't rely on the existence of some token smart contract to update balances to track ownership - Access Control - Smart contracts require the ability to restrict access to and identify certain users or contracts - Unlike account-based blockchains, **transactions in UTXO-based blockchains (i.e. Fuel) do not necessarily have a unique transaction sender** - Additional logic is needed to handle this difference, and is provided by the standard library - Calling Contracts - Smart contracts can be **called** by other contracts or scripts. In the FuelVM, this is done primarily with the call instruction - Sway provides a nice way to manage callable interfaces with its **abi** system. The Fuel ABI specification can be found [here](https://fuellabs.github.io/fuel-specs/master/protocol/abi) ## Examples and Quick DEMO - [Counter](https://fuellabs.github.io/sway/v0.31.1/examples/counter.html#counter) - [Subcurrency](https://fuellabs.github.io/sway/v0.31.1/examples/subcurrency.html) - [FizzBuzz](https://fuellabs.github.io/sway/v0.31.1/examples/fizzbuzz.html) - [Wallet Smart Contract](https://fuellabs.github.io/sway/v0.31.1/examples/wallet_smart_contract.html) - [Liquidity Pool](https://fuellabs.github.io/sway/v0.31.1/blockchain-development/native_assets.html#liquidity-pool-example) - [Native Token](https://fuellabs.github.io/sway/v0.31.1/blockchain-development/native_assets.html#native-token-example)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Google Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully