diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..272712417 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "gitsubmodule" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" diff --git a/.github/workflows/check-undocumented-issues.yml b/.github/workflows/check-undocumented-issues.yml new file mode 100644 index 000000000..ece52e116 --- /dev/null +++ b/.github/workflows/check-undocumented-issues.yml @@ -0,0 +1,57 @@ +name: Check Undocumented Issues + +on: + issues: + types: [opened] + +jobs: + check-issue-content: + runs-on: ubuntu-latest + permissions: + issues: write + + steps: + - name: Check issue content + uses: actions/github-script@v7 + with: + script: | + const issue = context.payload.issue; + + // Get the issue body and title + const body = issue.body || ''; + const title = issue.title || ''; + + // Check if this is a docs update request + const isDocsRequest = title.startsWith('Docs update request:'); + + if (!isDocsRequest) { + return; + } + + // Split body into lines and remove empty ones + const bodyLines = body.split('\n').filter(line => line.trim()); + + // Check if only contains the template content + const hasOnlyTemplate = + bodyLines.length <= 3 && // Updated to match 3 lines + bodyLines[0]?.startsWith('Source:') && + bodyLines[1]?.startsWith('Request: (how can we help?)') && + bodyLines[2]?.includes('Psst, this issue will be closed'); // Added check for the warning message + + if (hasOnlyTemplate) { + // Close the issue with a comment + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + body: 'This issue is being closed automatically as it appears to be an empty documentation update request. Please provide specific details about what needs to be updated or improved in the documentation. You can create a new issue with more details if needed.\n\nSome helpful details to include:\n- What specific part of the documentation needs updating?\n- What is unclear or missing?\n- What would make the documentation more helpful?\n\nThank you for helping us improve our documentation!' + }); + + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + state: 'closed', + state_reason: 'not_planned' + }); + } diff --git a/.gitignore b/.gitignore index 11dc0888e..83be1e7d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .vscode arbitrum-docs/sdk -arbitrum-docs/stylus-by-example \ No newline at end of file +arbitrum-docs/stylus-by-example +.vercel +.DS_Store diff --git a/arbitrum-docs/arbitrum-bridge/01-quickstart.md b/arbitrum-docs/arbitrum-bridge/01-quickstart.mdx similarity index 88% rename from arbitrum-docs/arbitrum-bridge/01-quickstart.md rename to arbitrum-docs/arbitrum-bridge/01-quickstart.mdx index 2fb7f1426..f2610aec7 100644 --- a/arbitrum-docs/arbitrum-bridge/01-quickstart.md +++ b/arbitrum-docs/arbitrum-bridge/01-quickstart.mdx @@ -10,7 +10,7 @@ This quickstart is for users who want to "deposit" ETH or any ERC-20 tokens from We will go through the whole process step by step with as much detail as possible. If you feel stuck in any of the steps, don't hesitate to contact us through our [Discord](https://discord.gg/arbitrum) and we will be happy to help you complete the process. -The only prerequisite for this quickstart is to have a web3 wallet installed, e.g. Metamask. If you don't have one, visit Arbitrum's [portal page](https://portal.arbitrum.io/?categories=wallet) to download one. +The only prerequisite for this quickstart is to have a web3 wallet installed, e.g., Metamask/OKX Wallet. If you don't have one, visit Arbitrum's [portal page](https://portal.arbitrum.io/?categories=wallet) to download one. ## Deposit ETH or ERC-20 tokens (from parent chain to child chain) @@ -26,11 +26,11 @@ There are several ways to obtain the native currency: ### Step 2: Add the preferred network to your wallet -You'll also need to add the desired chain's RPC endpoint to your wallet. Here we provide an example for doing this using MetaMask, although the process should be similar for other wallets. You need to first click on the MetaMask extension on your browser, click the network selector dropdown on the top-left corner, and then click the `Add Network` button at the bottom. Click "Add a network manually" and then provide the information corresponding to the chain you want to send your assets to. +You'll also need to add the desired chain's RPC endpoint to your wallet. Here we provide an example for doing this using MetaMask/OKX Wallet, although the process should be similar for other wallets. You need to first click on the MetaMask/OKX Wallet extension on your browser, click the network selector dropdown on the top-left corner, and then click the `Add Network` button at the bottom. Click "Add a network manually" and then provide the information corresponding to the chain you want to send your assets to. -![Add the desired destination network to your MetaMask wallet](images/getting_started_users_1.png) +![Add the desired destination network to your MetaMask/OKX wallet](images/getting_started_users_1.png) -Here we display the information of the most common Arbitrum chains, but you can find a more exhaustive list in our [RPC endpoints and providers](/build-decentralized-apps/reference/01-node-providers.md) page. +Here we display the information of the most common Arbitrum chains, but you can find a more exhaustive list in our [RPC endpoints and providers](/build-decentralized-apps/reference/01-node-providers.mdx) page. | Parameter | Arbitrum One | Arbitrum Nova | Arbitrum Sepolia (testnet) | | ------------------ | ---------------------------- | ---------------------------- | -------------------------------------- | @@ -74,7 +74,7 @@ Also make sure your wallet is set to the destination chain so you can see your f :::info There's at least a 7 day withdrawal period for Arbitrum One and Nova networks Once you withdraw your funds from Arbitrum One or Nova through the Arbitrum bridge, you will have to wait for at least 7 days to receive them on Ethereum mainnet. -For more details, see [Arbitrum Bridge: Troubleshooting](/arbitrum-bridge/03-troubleshooting.md#how-long-does-it-take-before-i-receive-my-funds-when-i-initiate-withdrawal-from-arbitrum-chains-one-and-nova). +For more details, see [Arbitrum Bridge: Troubleshooting](https://docs.arbitrum.io/arbitrum-bridge/troubleshooting#how-long-does-it-take-before-i-receive-my-funds-when-i-initiate-a-withdrawal-from-arbitrum-chains-one-and-nova). ::: diff --git a/arbitrum-docs/arbitrum-bridge/02-usdc-arbitrum-one.md b/arbitrum-docs/arbitrum-bridge/02-usdc-arbitrum-one.mdx similarity index 67% rename from arbitrum-docs/arbitrum-bridge/02-usdc-arbitrum-one.md rename to arbitrum-docs/arbitrum-bridge/02-usdc-arbitrum-one.mdx index b943f5fe4..30de9d499 100644 --- a/arbitrum-docs/arbitrum-bridge/02-usdc-arbitrum-one.md +++ b/arbitrum-docs/arbitrum-bridge/02-usdc-arbitrum-one.mdx @@ -9,7 +9,7 @@ sidebar_position: 4 Arbitrum One supports two different types of USDC: -1. **Arbitrum-native USDC (USDC)**: USDC tokens native to the Arbitrum One chain. +1. **USDC (USDC)**: USDC tokens native to the Arbitrum One chain. 2. **Bridged USDC (USDC.e)**: Ethereum-native USDC tokens that have been bridged to Arbitrum One. ### Differences between USDC and USDC.e @@ -17,12 +17,12 @@ Arbitrum One supports two different types of USDC: - + - + @@ -54,4 +54,6 @@ The Arbitrum Bridge will continue to facilitate transfers of all USDC tokens. Wh ### Historical context -Arbitrum One has supported Bridged USDC since conception, which previously had over a billion Bridged USDC in circulation. On June 8th 2023, Circle added support for the Cross-Chain Transfer Protocol and launched Arbitrum-native USDC, which enabled direct minting and burning of Arbitrum-Native USDC on Arbitrum One. Due to this, the Bridged USDC token symbol was renamed from USDC to USDC.e to accommodate Arbitrum-native USDC. The expectation is that over time the conversion of Bridged USDC to Arbitrum-native USDC will continue. +The Arbitrum Bridge will continue to facilitate transfers of all USDC tokens. When depositing USDC from Ethereum, the option exists to receive USDC using Circle’s Cross-Chain Transfer Protocol or receive Bridged USDC using Arbitrum’s lock-and-mint bridge. +Historical context +In 2023, Circle launched USDC natively on Arbitrum One and added support for Cross-Chain Transfer Protocol, which enabled direct minting and burning of USDC between Ethereum and Arbitrum One. Due to this, the token symbol for Bridged USDC was renamed to USDC.e to accommodate an ecosystem-wide liquidity migration to native USDC. The expectation is that over time the liquidity migration of USDC.e to USDC will continue. diff --git a/arbitrum-docs/arbitrum-bridge/03-troubleshooting.md b/arbitrum-docs/arbitrum-bridge/03-troubleshooting.mdx similarity index 100% rename from arbitrum-docs/arbitrum-bridge/03-troubleshooting.md rename to arbitrum-docs/arbitrum-bridge/03-troubleshooting.mdx diff --git a/arbitrum-docs/assets/batching.png b/arbitrum-docs/assets/batching.png new file mode 100644 index 000000000..6e311e261 Binary files /dev/null and b/arbitrum-docs/assets/batching.png differ diff --git a/arbitrum-docs/assets/bypassing-the-sequencer.png b/arbitrum-docs/assets/bypassing-the-sequencer.png new file mode 100644 index 000000000..289d0d599 Binary files /dev/null and b/arbitrum-docs/assets/bypassing-the-sequencer.png differ diff --git a/arbitrum-docs/assets/compression.png b/arbitrum-docs/assets/compression.png new file mode 100644 index 000000000..2a8ec38f1 Binary files /dev/null and b/arbitrum-docs/assets/compression.png differ diff --git a/arbitrum-docs/assets/sequencer-feed.png b/arbitrum-docs/assets/sequencer-feed.png new file mode 100644 index 000000000..b5b580fb7 Binary files /dev/null and b/arbitrum-docs/assets/sequencer-feed.png differ diff --git a/arbitrum-docs/assets/sequencer-operations.png b/arbitrum-docs/assets/sequencer-operations.png new file mode 100644 index 000000000..50053133f Binary files /dev/null and b/arbitrum-docs/assets/sequencer-operations.png differ diff --git a/arbitrum-docs/assets/submit-to-sequencer-inbox.png b/arbitrum-docs/assets/submit-to-sequencer-inbox.png new file mode 100644 index 000000000..08653bb3d Binary files /dev/null and b/arbitrum-docs/assets/submit-to-sequencer-inbox.png differ diff --git a/arbitrum-docs/assets/submit-tx-to-sequencer.png b/arbitrum-docs/assets/submit-tx-to-sequencer.png new file mode 100644 index 000000000..b67b0df65 Binary files /dev/null and b/arbitrum-docs/assets/submit-tx-to-sequencer.png differ diff --git a/arbitrum-docs/audit-reports.mdx b/arbitrum-docs/audit-reports.mdx index 2bfc60f01..a3e954a9d 100644 --- a/arbitrum-docs/audit-reports.mdx +++ b/arbitrum-docs/audit-reports.mdx @@ -1,21 +1,27 @@ # Security Audit Reports -| Auditor | Audit date | Audited code | View report | -| ----------------------- | ---------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| **ConsenSys Diligence** | 11/05/2021 | Core Contracts, Token Bridge | [view](hosted-audit-reports/2021_11_05_consensys_diligence_security_audit_core_contracts_token_bridge.pdf) | -| **ConsenSys Diligence** | 06/24/2022 | Nitro Node & Core Contracts | [view](hosted-audit-reports/2024_06_24_consensys_diligence_security_audit_nitro_contracts.pdf) | -| **Trail of Bits** | 03/14/2022 | Nitro Node & Core Contracts, 1 of 2 | [view](hosted-audit-reports/2022_03_14_trail_of_bits_security_audit_nitro_1_of_2.pdf) | -| **Trail of Bits** | 10/10/2022 | Nitro Node & Core Contracts, 2 of 2 | [view](hosted-audit-reports/2022_10_22_trail_of_bits_security_audit_nitro_2_of_2.pdf) | -| **Trail of Bits** | 01/06/2023 | Governance & Token Bridge | [view](hosted-audit-reports/2023_06_23_trail_of_bits_security_audit_governance_report_governance_token_bridge.pdf) | -| **Chainsecurity** | 03/20/2024 | Nova Fee Router Updates (ArbOS 31) | [view](hosted-audit-reports/2024_08_20_chainsecurity_security_audit_nova_fee_router_update_arbos_31.pdf) | -| **Trail of Bits** | 05/02/2024 | Arbitrum BoLD & Delay Buffer | [view](hosted-audit-reports/2024_05_02_trail_of_bits_security_audit_bold_delay_buffer.pdf) | -| **Code4rena** | 06/17/2024 | Arbitrum BoLD: Public Audit Competition Report | [view](hosted-audit-reports/2024_06_17_code4arena_security_audit_arbos30_nitro_upgrade.pdf) | -| **Trail of Bits** | 06/10/2024 | Arbitrum Stylus | [view](hosted-audit-reports/2024_06_10_trail_of_bits_security_audit_stylus.pdf) | -| **Trail of Bits** | 07/26/2024 | ArbOS 30 Atlas: Nitro Upgrade | [view](hosted-audit-reports/2024_07_26_trail_of_bits_security_audit_arbos30_nitro_upgrade.pdf) | -| **Trail of Bits** | 07/26/2024 | ArbOS 31 Bianca: Nitro Upgrade | [view](hosted-audit-reports/2024_07_26_trail_of_bits_security_audit_arbos_31.pdf) | -| **Trail of Bits** | 03/18/2024 | l1-l3-teleporter | [view](hosted-audit-reports/2024_03_18_trail_of_bits_security_audit_l1_l3_teleporter.pdf) | -| **Trail of Bits** | 08/01/2024 | Custom fee token | [view](hosted-audit-reports/2024_08_01_trail_of_bits_security_audit_custom_fee_token.pdf) | -| **Trail of Bits** | 08/29/2024 | USDC Custom Gateway & ArbOS Timestamp Upgrade Action contract | [view](hosted-audit-reports/2024_08_29_trail_of_bits_security_audit_usdc_custom_gateway_and_arbos_upgrade_at_timestamp_action.pdf) | -| **Trail of Bits** | 08/29/2024 | Orbit & Governance Upgrade Actions Contracts v2.1 | [view](hosted-audit-reports/2024_08_29_trail_of_bits_security_audit_orbit_and_governance_upgrade_actions_v2.1.pdf) | -| **Open Zeppelin** | 09/05/2024 | Stylus Rust SDK | [view](hosted-audit-reports/2024_09_05_open_zeppelin_security_audit_stylus_rust_sdk.pdf) | -| **Trail of Bits** | 09/25/2024 | Timeboost Auction Contracts | [view](hosted-audit-reports/2024_09_25_trail_of_bits_security_audit_timeboost_auction_contracts.pdf) | +| Auditor | Audit date (MM/DD/YYY) | Audited code | View report | +| ----------------------- | ---------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| **Trail of Bits** | 12/26/2024 | BoLD Proposal Payload & Upgrade Actions + Misc Changes for Nitro Contracts v3.0.0 | [view](hosted-audit-reports/2024_12_26_trail_of_bits_boldfixes_securityreview.pdf) | +| **Trail of Bits** | 10/30/2024 | Changes to BoLD Solidity contracts to support EIP7702 & Fast Withdrawals | [view](hosted-audit-reports/2024_10_30_trail_of_bits_security_audit_Nitro_Contracts_with_BoLD.pdf) | +| **Trail of Bits** | 10/23/2024 | ArbOS 32 Bianca: Emergency Stylus Fixes | [view](hosted-audit-reports/2024_10_23_trail_of_bits_security_audit_arbos32_emergency_fixes.pdf) | +| **Trail of Bits** | 10/07/2024 | Optimizations to BoLD history commitments | [view](hosted-audit-reports/2024_10_07_trail_of_bits_security_audit_bold_optimized_history_commitments.pdf) | +| **Trail of Bits** | 09/25/2024 | Timeboost Auction Contracts | [view](hosted-audit-reports/2024_09_25_trail_of_bits_security_audit_timeboost_auction_contracts.pdf) | +| **Open Zeppelin** | 09/05/2024 | Initial Stylus Rust SDK audit | [view](hosted-audit-reports/2024_09_05_open_zeppelin_security_audit_stylus_rust_sdk.pdf) | +| **Trail of Bits** | 08/29/2024 | Orbit & Governance Upgrade Actions Contracts v2.1 | [view](hosted-audit-reports/2024_08_29_trail_of_bits_security_audit_orbit_and_governance_upgrade_actions_v2.1.pdf) | +| **Trail of Bits** | 08/29/2024 | USDC Custom Gateway & ArbOS Timestamp Upgrade Action contract | [view](hosted-audit-reports/2024_08_29_trail_of_bits_security_audit_usdc_custom_gateway_and_arbos_upgrade_at_timestamp_action.pdf) | +| **Trail of Bits** | 08/05/2024 | BoLD contract fixes from the May 2024 audit & DAC reward updates | [view](hosted-audit-reports/2024_08_05_trail_of_bits_security_audit_bold_and_dac_rewards_updates.pdf) | +| **Trail of Bits** | 08/01/2024 | Custom fee token | [view](hosted-audit-reports/2024_08_01_trail_of_bits_security_audit_custom_fee_token.pdf) | +| **Trail of Bits** | 07/26/2024 | ArbOS 31 Bianca: Nitro Upgrade | [view](hosted-audit-reports/2024_07_26_trail_of_bits_security_audit_arbos_31.pdf) | +| **Trail of Bits** | 07/26/2024 | ArbOS 30 Atlas: Nitro Upgrade | [view](hosted-audit-reports/2024_07_26_trail_of_bits_security_audit_arbos30_nitro_upgrade.pdf) | +| **Code4rena** | 06/17/2024 | Arbitrum BoLD: Public Audit Competition Report | [view](hosted-audit-reports/2024_06_17_code4arena_security_audit_arbos30_nitro_upgrade.pdf) | +| **Trail of Bits** | 06/10/2024 | Arbitrum Stylus | [view](hosted-audit-reports/2024_06_10_trail_of_bits_security_audit_stylus.pdf) | +| **Trail of Bits** | 05/02/2024 | BoLD contract fixes from the Aug 2023 audit & Delay Buffer changes to the sequencer inbox | [view](hosted-audit-reports/2024_05_02_trail_of_bits_security_audit_bold_delay_buffer.pdf) | +| **Chainsecurity** | 03/20/2024 | Nova Fee Router Updates (ArbOS 31) | [view](hosted-audit-reports/2024_08_20_chainsecurity_security_audit_nova_fee_router_update_arbos_31.pdf) | +| **Trail of Bits** | 03/18/2024 | l1-l3-teleporter | [view](hosted-audit-reports/2024_03_18_trail_of_bits_security_audit_l1_l3_teleporter.pdf) | +| **Trail of Bits** | 08/02/2023 | Arbitrum BoLD - initial audit (then called challenge protocol v2) | [view](hosted-audit-reports/2023_08_02_trail_of_bits_security_audit_challenge_protocol_v2.pdf) | +| **Trail of Bits** | 01/06/2023 | Governance & Token Bridge | [view](hosted-audit-reports/2023_06_23_trail_of_bits_security_audit_governance_report_governance_token_bridge.pdf) | +| **Trail of Bits** | 10/10/2022 | Nitro Node & Core Contracts, 2 of 2 | [view](hosted-audit-reports/2022_10_22_trail_of_bits_security_audit_nitro_2_of_2.pdf) | +| **ConsenSys Diligence** | 06/24/2022 | Nitro Node & Core Contracts | [view](hosted-audit-reports/2024_06_24_consensys_diligence_security_audit_nitro_contracts.pdf) | +| **Trail of Bits** | 03/14/2022 | Nitro Node & Core Contracts, 1 of 2 | [view](hosted-audit-reports/2022_03_14_trail_of_bits_security_audit_nitro_1_of_2.pdf) | +| **ConsenSys Diligence** | 11/05/2021 | Core Contracts, Token Bridge | [view](hosted-audit-reports/2021_11_05_consensys_diligence_security_audit_core_contracts_token_bridge.pdf) | diff --git a/arbitrum-docs/bold/concepts/bold-technical-deep-dive.md b/arbitrum-docs/bold/concepts/bold-technical-deep-dive.mdx similarity index 98% rename from arbitrum-docs/bold/concepts/bold-technical-deep-dive.md rename to arbitrum-docs/bold/concepts/bold-technical-deep-dive.mdx index 63f9495da..a27a7684c 100644 --- a/arbitrum-docs/bold/concepts/bold-technical-deep-dive.md +++ b/arbitrum-docs/bold/concepts/bold-technical-deep-dive.mdx @@ -10,10 +10,6 @@ sme: leeederek sidebar_position: 1 --- -import PublicPreviewBannerPartial from '../../how-arbitrum-works/bold/partials/_bold-public-preview-banner-partial.md'; - - - ## Overview Arbitrum's current dispute protocol involves defending against challengers individually in a 1-vs-1 tournament setting. In contrast, BoLD enables an all-vs-all battle royale between Good and Evil, with a single winner always determined. @@ -44,7 +40,7 @@ The current implementation of BoLD involves both on-chain and off-chain componen - **Honest validator:** An entity that knows the correct state of the Arbitrum L2 chain and who may want to participate in creating assertions, confirming assertions, and/or challenging invalid assertions if they exist. More specifically, this entity must run an Arbitrum full node in `MakeNodes`, `Defensive`, `StakeLatest`, or `ResolveNodes` mode as described in the [How to run a validator](https://docs.arbitrum.io/run-arbitrum-node/more-types/run-validator-node). Note that there must always be an active proposer to advance the chain and who will need to run a validator in `MakeNodes` mode. - **Challenge period:** Window of time ([~6.4 days on Arbitrum One](https://docs.arbitrum.io/build-decentralized-apps/reference/chain-params)) over which an assertion can be challenged, after which the assertion can be confirmed. This is configurable by the DAO. - **Edge:** Edges are a portion of a claim made by a validator about the history of the chain from some end state all the way back to some initial state. Edges are the fundamental unit in a challenge. -- **Timers:** Each unrivaled edge (that is, an edge without another competing edge) will have a timer that _ticks up_. Time in the protocol is measured using L1 blocks and block numbers are used. An edge's timer stops ticking when a rival edge is created on-chain. Most importantly, timers are used to confirm assertions when an unrivaled edge's timer, and associated assertion, reaches the specified challenge period. See the section on [Timers](./bold-technical-deep-dive.md#timers) for more details. +- **Timers:** Each unrivaled edge (that is, an edge without another competing edge) will have a timer that _ticks up_. Time in the protocol is measured using L1 blocks and block numbers are used. An edge's timer stops ticking when a rival edge is created on-chain. Most importantly, timers are used to confirm assertions when an unrivaled edge's timer, and associated assertion, reaches the specified challenge period. See the section on [Timers](./bold-technical-deep-dive.mdx#timers) for more details. - **Delay attacks:** In a delay attack, a malicious party (or group of parties) acts within the rollup protocol, forcing the honest party to play 1-vs-1 games against them to delay the confirmation of results back to the L1 chain. BoLD has a proven, constant upper bound on confirmation times for assertions in Arbitrum, addressing the biggest flaw of the current challenge mechanism. BoLD validators don’t need to play 1-vs-1 challenges and instead can defend a single challenge against many malicious claims. With delay attacks solved, Arbitrum will be able to allow permissionless validation. - **Permissionless validation:** The ability for anyone to interact with the Arbitrum rollup contracts on Ethereum to both post assertions and challenge others' assertions without needing permission. With the release of BoLD, the rollup contracts on Arbitrum will no longer have a permissioned list of validators. - **Validator software:** Software that has knowledge of the correct Arbitrum L2 state at any point. It tracks the on-chain rollup contracts for assertions posted and will automatically initiate challenges on malicious assertions if configured to do so by the user. It will participate in new and existing challenges and make moves as required by the protocol to win against any number of malicious entities. Its goal is to ensure only honest assertions about Arbitrum's state are confirmed on Ethereum. All Arbitrum full nodes are watchtower validators by default. This means they do not post claims or assertions unless configured to do so but will warn in case invalid assertions are detected on-chain. @@ -168,7 +164,7 @@ Bob commits to 33 hashes with start = A, end = B’ Either of them can perform a “bisection” move on their edge. For instance, if Alice “bisects” her edge E, the bisection transaction will produce two children, E_1 and E_2. E_1 commits to 17 hashes from height A to B/2, and E_2 commits to 17 hashes from height B/2 to B. -A validator can make a move on an edge as long as that edge is “rivaled”. That is, the children just created due to Alice’s bisection will have increasing timers until Bob also bisects and possibly creates rivals for Alice’s edges (see [timers](./bold-technical-deep-dive.md#timers) for more details). +A validator can make a move on an edge as long as that edge is “rivaled”. That is, the children just created due to Alice’s bisection will have increasing timers until Bob also bisects and possibly creates rivals for Alice’s edges (see [timers](./bold-technical-deep-dive.mdx#timers) for more details). #### Subchallenges @@ -202,17 +198,17 @@ To create a challenge, there must be a fork in the Arbitrum assertion chain smar Challenge bonds are named as such because they are bonds required for opening challenges. The mechanism of how challenge bond economics are decided is contained in the -[Economics of Disputes](../../how-arbitrum-works/bold/bold-economics-of-disputes.md), which also explains +[Economics of Disputes](../../how-arbitrum-works/bold/bold-economics-of-disputes.mdx), which also explains the cost profile and spam prevention in BoLD. In short, the actual cost of a bond encompasses many costs associated with participating in the dispute game. More information on the bond sizes and how they were -calculated can be found in the [Economics of Disputes](../../how-arbitrum-works/bold/bold-economics-of-disputes.md) +calculated can be found in the [Economics of Disputes](../../how-arbitrum-works/bold/bold-economics-of-disputes.mdx) document mentioned above. Each subchallenge that is created requires depositing a challenge bond. For Arbitrum One, the first unrivaled edge’s bond is kept in the challenge manager contract on Ethereum, while any subsequent rival bonds are kept in an excess bond receiver address. Once a challenge is complete, all bonds for an honest party are automatically refunded in-protocol while all confiscated bonds are sent to the ArbitrumDAO treasury. It is important to not offer the majority of the bonds confiscated from dishonest parties to honest parties to avoid perverse incentives, such as grieving attacks in self-challenges or to discourage needless competition between honest parties. ### Reimbursements of bonds -The reimbursement of assertion bonds and challenge bonds for honest parties will be handled “in-band” by the protocol. Please see [Economics of Disputes](../../how-arbitrum-works/bold/bold-economics-of-disputes.md) for more information about this topic. +The reimbursement of assertion bonds and challenge bonds for honest parties will be handled “in-band” by the protocol. Please see [Economics of Disputes](../../how-arbitrum-works/bold/bold-economics-of-disputes.mdx) for more information about this topic. ### Upgrade mechanism diff --git a/arbitrum-docs/build-decentralized-apps/01-quickstart-solidity-hardhat.md b/arbitrum-docs/build-decentralized-apps/01-quickstart-solidity-hardhat.mdx similarity index 97% rename from arbitrum-docs/build-decentralized-apps/01-quickstart-solidity-hardhat.md rename to arbitrum-docs/build-decentralized-apps/01-quickstart-solidity-hardhat.mdx index 969be520a..d1befd410 100644 --- a/arbitrum-docs/build-decentralized-apps/01-quickstart-solidity-hardhat.md +++ b/arbitrum-docs/build-decentralized-apps/01-quickstart-solidity-hardhat.mdx @@ -8,7 +8,7 @@ content_type: quickstart :::info Want to use Rust instead? -Head over to [the Stylus quickstart](/stylus/stylus-quickstart) if you'd like to use Rust instead of Solidity. +Head over to [the Stylus quickstart](/stylus/quickstart) if you'd like to use Rust instead of Solidity. ::: @@ -42,7 +42,7 @@ Let's implement the "web3" version of the above vending machine using Arbitrum. ### Prerequisites - **VS Code**: The IDE we'll use to build our vending machine. See [code.visualstudio.com](https://code.visualstudio.com/) to install. -- **Metamask**: The wallet we'll use to interact with our vending machine. See [metamask.io](https://metamask.io/) to install. +- **Web3 wallet**: The wallet we'll use to interact with our vending machine. See [metamask.io](https://metamask.io/) and click View MetaMask Web or [OKX Wallet](https://www.okx.com/web3) and click Connect Wallet to install. - **Yarn**: The package manager we'll use to install our dependencies. See [yarnpkg.com](https://yarnpkg.com/) to install. We'll address remaining dependencies as we go. @@ -456,7 +456,7 @@ Select `Arbitrum Sepolia` from Metamask's dropdown, paste your contract address Now that we've verified that our smart contract works on Arbitrum's Sepolia testnet, we're ready to deploy it to Arbitrum One Mainnet. This is the same process as deploying to Arbitrum's Sepolia testnet, except that we'll need to pay a transaction fee in real $ETH instead of $ASPL. -Expect to see inconsistent $ETH gas fees in this step - the [Gas and fees section](/how-arbitrum-works/gas-fees.md) contains more information about how gas fees are determined for Arbitrum transactions. +Expect to see inconsistent $ETH gas fees in this step - the [Gas and fees section](/how-arbitrum-works/09-gas-fees.mdx) contains more information about how gas fees are determined for Arbitrum transactions. @@ -512,15 +512,15 @@ If you have any questions or feedback, reach out to us on [Discord](https://disc -- Visit [How to estimate gas](/build-decentralized-apps/02-how-to-estimate-gas.md) to learn how to estimate the gas cost of your smart contract transactions. -- Visit [RPC endpoints and providers](/build-decentralized-apps/reference/01-node-providers.md#rpc-endpoints) for a list of public chains that you can deploy your smart contracts to. +- Visit [How to estimate gas](/build-decentralized-apps/02-how-to-estimate-gas.mdx) to learn how to estimate the gas cost of your smart contract transactions. +- Visit [RPC endpoints and providers](/build-decentralized-apps/reference/01-node-providers.mdx) for a list of public chains that you can deploy your smart contracts to. [^1]: The vending machine example was inspired by [Ethereum.org's "Introduction to Smart Contracts"](https://ethereum.org/en/developers/docs/smart-contracts/), which was inspired by [Nick Szabo's "From vending machines to smart contracts"](http://unenumerated.blogspot.com/2006/12/from-vending-machines-to-smart.html). [^2]: Although application front-ends are usually hosted by centralized services, smart contracts allow the underlying logic and data to be partially or fully decentralized. These smart contracts are hosted and executed by Ethereum's public, decentralized network of nodes. Arbitrum has its own network of nodes that use advanced cryptography techniques to "batch process" Ethereum transactions and then submit them to Ethereum L1, which significantly reduces the cost of using Ethereum. All without requiring developers to compromise on security or decentralization. [^3]: There are multiple types of Ethereum nodes. The ones that earn ETH for processing and validating transactions are called _validators_. See [Nodes and Networks](https://docs.prylabs.network/docs/concepts/nodes-networks) for a beginner-friendly introduction to Ethereum's node types. [^4]: When our `VendingMachine` contract is deployed to Ethereum, it'll be hosted by Ethereum's decentralized network of nodes. Generally speaking, we won't be able to modify the contract's code after it's deployed. [^5]: To learn more about how Ethereum wallets work, see [Ethereum.org's introduction to Ethereum wallets](https://ethereum.org/en/wallets/). -[^6]: Visit the [Gentle Introduction to Arbitrum](../intro/intro.md) for a beginner-friendly introduction to Arbitrum's rollup protocol. +[^6]: Visit the [Gentle Introduction to Arbitrum](../intro/intro.mdx) for a beginner-friendly introduction to Arbitrum's rollup protocol. -import PublicPreviewBannerPartial from '../../partials/_public-preview-banner-partial.mdx'; - - - The Arbitrum Nitro software includes a special `NodeInterface` contract available at address `0xc8` that is only accessible via RPCs (it's not actually deployed on-chain, and thus can't be called by smart contracts). The way it works is that the node uses Geth's [`InterceptRPCMessage`](https://github.com/OffchainLabs/go-ethereum/blob/@goEthereumCommit@/internal/ethapi/api.go#L1034) hook to detect messages sent to the address `0xc8`, and swaps out the message it's handling before deriving a transaction from it. The [reference page](/build-decentralized-apps/nodeinterface/02-reference.mdx) contains information about all methods available in the NodeInterface. diff --git a/arbitrum-docs/build-decentralized-apps/nodeinterface/02-reference.mdx b/arbitrum-docs/build-decentralized-apps/nodeinterface/02-reference.mdx index e23cfb768..0c9a2e2d1 100644 --- a/arbitrum-docs/build-decentralized-apps/nodeinterface/02-reference.mdx +++ b/arbitrum-docs/build-decentralized-apps/nodeinterface/02-reference.mdx @@ -9,6 +9,6 @@ The Arbitrum Nitro software includes a special `NodeInterface` contract availabl ## NodeInterface methods -import NodeInterfaceRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_NodeInterface.md'; +import NodeInterfaceRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_NodeInterface.mdx'; diff --git a/arbitrum-docs/build-decentralized-apps/oracles/01-overview.mdx b/arbitrum-docs/build-decentralized-apps/oracles/01-overview.mdx index 94f6d04d2..3178bdf66 100644 --- a/arbitrum-docs/build-decentralized-apps/oracles/01-overview.mdx +++ b/arbitrum-docs/build-decentralized-apps/oracles/01-overview.mdx @@ -1,25 +1,33 @@ --- -title: 'Oracles overview' +id: 'overview-oracles' +title: 'Oracles' description: A high level description of what oracles are user_story: As a developer, I want to understand what oracles are and how they work. content_type: concept +sidebar_label: Oracles --- -Oracles are services that let smart contracts interact with the world outside of the blockchain’s world state. In this conceptual overview, we’ll explore what oracles are, how they work, and some general use cases for them. This guide will provide a foundational understanding of oracles, setting expectations for developers who want to integrate them into their applications. +:::note + +This is a conceptual overview of oracles. For more detailed information on how to use oracles in your applications, check out our [third-party oracles documentation](/for-devs/oracles/oracles-content-map). + +::: + +In this conceptual overview, we'll explore oracles, how they work, and some general applications. This overview will provide a foundational understanding and set expectations for developers who want to integrate oracles into their applications. ### What are oracles? -Oracles are third-party services that provide smart contracts with external information. They act as a bridge between blockchains and the outside world, enabling smart contracts to access off-chain data. Oracles are essential in expanding the functionality of smart contracts by enabling them to interact with data sources beyond their native networks. +Oracles are third-party services that provide smart contracts with external information. They act as a bridge between blockchains and the outside world, which expands their functionality by enabling smart contracts to access data beyond their native networks. ### Types of oracles -Oracles can be classified based on their source, direction of information, trust, and the way they provide information to smart contracts. Some common types of oracles include: +Oracles can be classified based on their source, direction of information, trust, and how they provide information to smart contracts. Some common types of oracles include: -- Inbound and Outbound oracles: Inbound oracles transmit information from external sources to smart contracts, while outbound oracles send information from smart contracts to the external world. -- Centralized and Decentralized oracles: A centralized oracle is controlled by a single entity and is the sole provider of information for a smart contract. Decentralized oracles, on the other hand, increase reliability by relying on multiple sources of truth and distributing trust among various participants. -- Push and Pull oracles: Push oracles proactively provide data to smart contracts without being explicitly requested. They push data to the smart contract when a specified event or condition occurs. Pull oracles, on the other hand, require smart contracts to request data explicitly. They pull data from external sources in response to a query from the smart contract. -- Software oracles: These oracles interact with online sources of information, such as databases, servers, or websites, and transmit the data to the blockchain. They often provide real-time information like exchange rates or digital asset prices. -- Hardware oracles: These oracles obtain information from the physical world using electronic sensors, barcode scanners, or other reading devices. They "translate" real-world events into digital values that can be understood by smart contracts. +- **Inbound and Outbound oracles**: Inbound oracles share information from external sources to smart contracts, while outbound oracles send information from smart contracts to the external world. +- **Centralized and Decentralized oracles**: A centralized oracle is a single entity and sole data provider for a smart contract. Decentralized oracles increase reliability by relying on multiple sources of truth and distributing trust among participants. +- **Push and Pull oracles**: Push oracles proactively provide data to smart contracts without being explicitly requested. They push data to the smart contract when a specified event or condition occurs. On the other hand, pull oracles require smart contracts to request data explicitly. They pull data from external sources in response to a query from the smart contract. +- **Software oracles**: These oracles interact with online sources of information, such as databases, servers, or websites, and transmit the data to the blockchain. They often provide real-time information like exchange rates or digital asset prices. +- **Hardware oracles**: These oracles obtain information from the physical world using electronic sensors, barcode scanners, or other reading devices. They "translate" real-world events into digital values that smart contracts can understand. ### How do push oracles work? @@ -42,7 +50,7 @@ sequenceDiagram ### How do pull oracles work? -Pull oracles, in contrast to push oracles, require smart contracts to request data explicitly. A smart contract will send a query to the oracle, which will then retrieve the requested information and relay it back to the contract. For example, a smart contract might request the current price of a specific digital asset from a pull oracle. +Pull oracles require smart contracts to request data explicitly. A smart contract sends a query to the oracle, retrieving and relaying the requested information to the contract. For example, a smart contract might request the current price of a specific digital asset from a pull oracle. ```mermaid sequenceDiagram @@ -60,11 +68,15 @@ sequenceDiagram ### Use cases for oracles -Oracles are used in various applications across different industries. Some general use cases include: +Oracles serve a purpose in various applications across industries. Some general use cases include: + +- **Prediction markets**: Oracles provide real-world data to prediction market platforms, allowing users to bet on future events or outcomes. +- **Supply chain management**: Hardware oracles can track the location and status of goods throughout the supply chain, enabling smart contracts to automate various processes and improve efficiency. +- **Insurance**: Oracles can supply data about events such as natural disasters, accidents, or price fluctuations, allowing smart contracts to automate claims processing and payouts. +- **Decentralized finance (DeFi)**: Oracles provide critical price and market data to DeFi applications, enabling them to operate efficiently and securely. + +In summary, oracles are a crucial component of the blockchain ecosystem, bridging the gap between on-chain and off-chain data sources. They enhance the functionality of smart contracts and enable a wide range of applications across various industries. As blockchain technology continues to evolve, developing secure and reliable oracles will remain essential in unlocking the full potential of smart contracts and decentralized applications. -- Prediction markets: Oracles provide real-world data to prediction market platforms, allowing users to bet on future events or outcomes. -- Supply chain management: Hardware oracles can track the location and status of goods throughout the supply chain, enabling smart contracts to automate various processes and improve efficiency. -- Insurance: Oracles can supply data on events like natural disasters, accidents, or price fluctuations, allowing smart contracts to automate claims processing and payouts. -- Decentralized finance (DeFi): Oracles provide critical price and market data to DeFi applications, enabling them to operate efficiently and securely. +### Resources -In summary, oracles are a crucial component of the blockchain ecosystem, bridging the gap between on-chain and off-chain data sources. They enhance the functionality of smart contracts and enable a wide range of applications across various industries. As blockchain technology continues to evolve, the development of secure and reliable oracles will remain essential in unlocking the full potential of smart contracts and decentralized applications. +You can learn more about oracles in our [third-party oracles documentation](/for-devs/oracles/oracles-content-map). diff --git a/arbitrum-docs/build-decentralized-apps/oracles/02-how-to-use-oracles.mdx b/arbitrum-docs/build-decentralized-apps/oracles/02-how-to-use-oracles.mdx deleted file mode 100644 index f9d660acd..000000000 --- a/arbitrum-docs/build-decentralized-apps/oracles/02-how-to-use-oracles.mdx +++ /dev/null @@ -1,363 +0,0 @@ ---- -title: 'How to use oracles in Arbitrum app' -description: Learn how to integrate oracles into your Arbitrum dapp -user_story: As a developer, I want to understand how to use oracles in Arbitrum to get off-chain data on-chain. -content_type: how-to ---- - -Oracles are web services that provide a connection between smart contracts and the outside world. They let decentralized apps (dApps) interact with off-chain data and services. - -Familiarity with [oracles](/build-decentralized-apps/oracles/01-overview.mdx), smart contracts, and blockchain development is expected. If you’re new to blockchain development, consider reviewing our [Quickstart: Build a dApp with Arbitrum (Solidity, Hardhat)](/build-decentralized-apps/01-quickstart-solidity-hardhat.md) before proceeding. - -## Chainlink - -[Chainlink](https://chain.link/) is a widely-recognized Web3 services platform that specializes in decentralized oracle networks. It lets you build Ethereum and Arbitrum dApps that connect to a variety of off-chain data feeds and APIs, including those that provide asset prices, weather data, random number generation, and more. - -### Querying the price of $ARB through Chainlink - -Here’s an example on how to use a price feed from Chainlink to query the current price of $ARB on-chain. We’ll use an interface provided by Chainlink that can be configured with the address of the proxy that holds the information we want to request, and wrap the operation in a contract. - -Chainlink provides an npm package with the contracts needed to access their feeds. We first install that package in our project: - -```tsx -yarn add @chainlink/contracts -``` - -To use a data feed, we retrieve the information through the `AggregatorV3Interface` and the proxy address of the feed we want to query. - -```solidity -import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; -``` - -In this case, we want to obtain the current price of $ARB in $USD in Arbitrum One, so we need to know the address of the proxy that will provide that information. Chainlink maintains a list of price feed address [here](https://docs.chain.link/data-feeds/price-feeds/addresses?network=arbitrum). For $ARB/$USD, we’ll use the address `0xb2A824043730FE05F3DA2efaFa1CBbe83fa548D6`. - -We can now build the function to get the latest price of $ARB. We’ll use this example contract: - -```solidity -contract ARBPriceConsumer { - AggregatorV3Interface internal priceFeed; - - /** - * Network: Arbitrum One - * Aggregator: ARB/USD - * Address: 0xb2A824043730FE05F3DA2efaFa1CBbe83fa548D6 - */ - address constant PROXY = 0xb2A824043730FE05F3DA2efaFa1CBbe83fa548D6; - - constructor() { - priceFeed = AggregatorV3Interface(PROXY); - } - - /** - * Returns the latest price. - */ - function getLatestPrice() public view returns (int) { - ( - /* uint80 roundID */, - int price, - /*uint startedAt*/, - /*uint timeStamp*/, - /*uint80 answeredInRound*/ - ) = priceFeed.latestRoundData(); - return price; - } -} -``` - -You can adapt this contract to your needs. Just remember to use the address of the asset you want to request the price for in the appropriate network, and to **deploy your contract to the same network**. Remember we have a [Quickstart](/build-decentralized-apps/01-quickstart-solidity-hardhat.md) available that goes through the process of compiling and deploying a contract. - -### More examples - -Refer to [Chainlink’s documentation](https://docs.chain.link/) for more examples of querying price feeds plus other data feeds available. - -## Chronicle - -[Chronicle Protocol](https://chroniclelabs.org/) is a novel Oracle solution that overcomes the current limitations of transferring data on-chain by developing scalable, cost-efficient, decentralized, and verifiable Oracles, rewriting the rulebook on data transparency and accessibility. - -### Querying the price of $ARB using Chronicle - -Chronicle contracts are read-protected by a whitelist, meaning you won't be able to read them on-chain without your address being added to the whitelist. On the Testnet, users can add themselves to the whitelist through the SelfKisser contract; a process playfully referred to as "kissing" themselves. To access production Oracles on the Mainnet, please open a support ticket in [Discord](https://discord.com/invite/CjgvJ9EspJ) in the 🆘 | support channel. - -For the deployment addresses, please check out the [Dashboard](https://chroniclelabs.org/dashboard/oracles). - -```solidity -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.16; - -/** - * @title OracleReader - * @notice A simple contract to read from Chronicle oracles - * @dev To see the full repository, visit https://github.com/chronicleprotocol/OracleReader-Example. - * @dev Addresses in this contract are hardcoded for the Arbitrum Sepolia testnet. - * For other supported networks, check the https://chroniclelabs.org/dashboard/oracles. - */ -contract OracleReader { - /** - * @notice The Chronicle oracle to read from. - * Chronicle_ARB_USD_1 - 0xdD7c06561689c73f0A67F2179e273cCF45EFc964 - * Network: Arbitrum Sepolia - */ - - IChronicle public chronicle = IChronicle(address(0xdD7c06561689c73f0A67F2179e273cCF45EFc964)); - - /** - * @notice The SelfKisser granting access to Chronicle oracles. - * SelfKisser_1:0xc0fe3a070Bc98b4a45d735A52a1AFDd134E0283f - * Network: Arbitrum Sepolia - */ - ISelfKisser public selfKisser = ISelfKisser(address(0xc0fe3a070Bc98b4a45d735A52a1AFDd134E0283f)); - - constructor() { - // Note to add address(this) to chronicle oracle's whitelist. - // This allows the contract to read from the chronicle oracle. - selfKisser.selfKiss(address(chronicle)); - } - - /** - * @notice Function to read the latest data from the Chronicle oracle. - * @return val The current value returned by the oracle. - * @return age The timestamp of the last update from the oracle. - */ - function read() external view returns (uint256 val, uint256 age) { - (val, age) = chronicle.readWithAge(); - } -} - -// Copied from [chronicle-std](https://github.com/chronicleprotocol/chronicle-std/blob/main/src/IChronicle.sol). -interface IChronicle { - /** - * @notice Returns the oracle's current value. - * @dev Reverts if no value set. - * @return value The oracle's current value. - */ - function read() external view returns (uint256 value); - - /** - * @notice Returns the oracle's current value and its age. - * @dev Reverts if no value set. - * @return value The oracle's current value using 18 decimals places. - * @return age The value's age as a Unix Timestamp . - * */ - function readWithAge() external view returns (uint256 value, uint256 age); -} - -// Copied from [self-kisser](https://github.com/chronicleprotocol/self-kisser/blob/main/src/ISelfKisser.sol). -interface ISelfKisser { - /// @notice Kisses caller on oracle `oracle`. - function selfKiss(address oracle) external; -} -``` - -### More examples - -For more examples of integrating Chronicle Oracles, please check the [documentation portal](https://docs.chroniclelabs.org/). - -## API3 - -[API3](https://api3.org/) is a collaborative project to deliver traditional API services to smart contract platforms in a decentralized and trust-minimized way. API3 provides the technology for [Airnodes](https://docs.api3.org/reference/airnode/latest/understand/) to push off-chain data to on-chain contracts. This data can then be queried directly through the Airnode (initiating a “pull-type” request) or through [dAPIs](https://docs.api3.org/guides/dapis/) (data-feeds sourced directly from multiple first-party oracles owned and operated by API providers). - -### Querying the price of $ARB through API3 - -Here’s an example of how to use an API3 data feed to query the current price of $ARB on-chain. The [API3 market](https://market.api3.org/arbitrum) provides a list of all the dAPIs available across multiple chains including testnets. You can go forward and activate the dAPI you want to use. - -API3 provides an npm package with the contracts needed to access their feeds. We first install that package in our project: - -```bash -yarn add @api3/contracts -``` - -To use a data feed, we retrieve the information through the specific proxy address for that feed. We’ll use the IProxy interface to do so. - -```solidity -import "@api3/contracts/api3-server-v1/proxies/interfaces/IProxy.sol"; -``` - -In this case, we want to obtain the current price of $ARB in $USD in Arbitrum One, so we need to know the proxy address that will provide that information. We will search the feed on the API3 Market and connect our wallet. We would then want to see if the feed is active, and if it is, we can check its configuration parameters, deploy the proxy contract and click on `Integrate.` You can find the proxy address of ARB/USD [here](https://market.api3.org/arbitrum?search=ARB%2FUSD). - -:::info -If a dAPI is already active, you can use the proxy address directly. If it is not active, you can activate it by clicking on `Activate` and following the instructions to deploy a proxy contract. -::: - -We can now build the function to get the latest price of $ARB. We’ll use this example contract: - -```solidity -contract ARBPriceConsumer { - /** - * Network: Arbitrum One - * Aggregator: ARB/USD - * Proxy: 0x0cB281EC7DFB8497d07196Dc0f86D2eFD21066A5 - */ - address constant PROXY = 0x0cB281EC7DFB8497d07196Dc0f86D2eFD21066A5; - - /** - * Returns the latest price. - */ - function getLatestPrice() - external - view - returns (int224 value, uint256 timestamp) - { - (value, timestamp) = IProxy(PROXY).read(); - // If you have any assumptions about `value` and `timestamp`, make sure - // to validate them right after reading from the proxy. - } -} -``` - -You can adapt this contract to your needs. Just remember to use the address of the asset you want to request the price for in the appropriate network and to **deploy your contract to the same network**. Remember we have a [Quickstart](/build-decentralized-apps/01-quickstart-solidity-hardhat.md) available that goes through the process of compiling and deploying a contract. - -### Querying a random number through API3 - -[API3 QRNG](https://docs.api3.org/explore/qrng/) is a public utility provided with the courtesy of [Australian National University (ANU)](https://www.anu.edu.au/). It is served as a public good, it is free of charge (apart from the gas costs), and it provides quantum randomness when requiring RNG on-chain. - -To request randomness on-chain, the requester submits a request for a random number to `AirnodeRrpV0`. The ANU Airnode gathers the request from the `AirnodeRrpV0` protocol contract, retrieves the random number off-chain, and sends it back to `AirnodeRrpV0`. Once received, it performs a callback to the requester with the random number. - -Here’s an example of a basic `QrngRequester` that requests a random number. - -API3 provides an npm package with the contracts needed to access the ANU QRNG airnode. We first install that package in our project: - -```bash -yarn add @api3/airnode-protocol -``` - -We’ll need several pieces of data to request a random number: - -- `address airnodeRrp`: Address of the protocol contract. See the [Chains](https://docs.api3.org/reference/qrng/chains.html) page for a list of addresses on different chains. For Arbitrum, we’ll use `0xb015ACeEdD478fc497A798Ab45fcED8BdEd08924`. -- `address airnode`: The address that belongs to the Airnode that will be called to get the QRNG data via its endpoints. See the [Providers](https://docs.api3.org/reference/qrng/providers.html) page for a list of addresses on different chains. For Arbitrum we’ll use `0x9d3C147cA16DB954873A498e0af5852AB39139f2`. -- `bytes32 endpointId`: Endpoint ID known by the Airnode that will map to an API provider call (allowed to be `bytes32(0)`). You can also find that information in the [Providers](https://docs.api3.org/reference/qrng/providers.html) page. For Arbitrum we’ll use `0xfb6d017bb87991b7495f563db3c8cf59ff87b09781947bb1e417006ad7f55a78`. -- `address sponsorWallet`: The address of the wallet that will pay for the gas costs for the callback request to get the random number on-chain. You need to fund this wallet with enough ETH to cover the gas costs. - -To derive your sponsorWallet address, you can use the following command: - -```bash -yarn @api3/airnode-admin derive-sponsor-wallet-address \ - --airnode-address 0x9d3C147cA16DB954873A498e0af5852AB39139f2 \ - --airnode-xpub xpub6DXSDTZBd4aPVXnv6Q3SmnGUweFv6j24SK77W4qrSFuhGgi666awUiXakjXruUSCDQhhctVG7AQt67gMdaRAsDnDXv23bBRKsMWvRzo6kbf \ - --sponsor-address - - # The command outputs. - Sponsor wallet address: 0x6394...5906757 - # Use this address as the value for _sponsorWallet. -``` - -We can now build the function to get a random number. We’ll use this example contract: - -```solidity -import "@api3/airnode-protocol/contracts/rrp/requesters/RrpRequesterV0.sol"; - -contract QrngRequester is RrpRequesterV0 { - event RequestedUint256(bytes32 indexed requestId); - event ReceivedUint256(bytes32 indexed requestId, uint256 response); - - /** - * Network: Arbitrum One - * AirnodeRrpV0 Address: 0xb015ACeEdD478fc497A798Ab45fcED8BdEd08924 - * Airnode: 0x9d3C147cA16DB954873A498e0af5852AB39139f2 - * Endpoint ID: 0xfb6d017bb87991b7495f563db3c8cf59ff87b09781947bb1e417006ad7f55a78 - */ - address constant _airnodeRrp = 0xb015ACeEdD478fc497A798Ab45fcED8BdEd08924; - address constant airnode = 0x9d3C147cA16DB954873A498e0af5852AB39139f2; - bytes32 constant endpointIdUint256 = 0xfb6d017bb87991b7495f563db3c8cf59ff87b09781947bb1e417006ad7f55a78; - mapping(bytes32 => bool) public waitingFulfillment; - address sponsorWallet; - - constructor() RrpRequesterV0(_airnodeRrp) {} - - // Set the sponsor wallet address that you just derived. - function setSponsorWallet(address _sponsorWallet) external { - sponsorWallet = _sponsorWallet; - } - - function makeRequestUint256() external { - bytes32 requestId = airnodeRrp.makeFullRequest( - airnode, - endpointIdUint256, - address(this), - sponsorWallet, - address(this), - this.fulfillUint256.selector, - "" - ); - waitingFulfillment[requestId] = true; - emit RequestedUint256(requestId); - } - - function fulfillUint256(bytes32 requestId, bytes calldata data) - external - onlyAirnodeRrp - { - require( - waitingFulfillment[requestId], - "Request ID not known" - ); - waitingFulfillment[requestId] = false; - uint256 qrngUint256 = abi.decode(data, (uint256)); - - // Use `qrngUint256` here... - - emit ReceivedUint256(requestId, qrngUint256); - } -} -``` - -You can adapt this contract to your needs. Just remember to set the `sponsorWallet` address before making the request to use the appropriate network's addresses, and to **deploy your contract to the same network**. Remember, we have a [Quickstart](/build-decentralized-apps/01-quickstart-solidity-hardhat.md) available that goes through the process of compiling and deploying a contract. - -### More examples - -Refer to [API3’s documentation](https://docs.api3.org/) for more examples of querying other data feeds and Airnodes. - -You can also check out some other detailed guides: - -- [Subscribing to dAPIs](https://docs.api3.org/guides/dapis/subscribing-to-dapis/) -- [Reading a dAPI Proxy](https://docs.api3.org/guides/dapis/read-a-dapi/) -- [Using QRNG with Remix](https://docs.api3.org/guides/qrng/qrng-remix/) - -## Tellor - -[Tellor](https://tellor.io/) is a decentralized oracle network that incentivizes an open, permissionless network of data reporting and validation, ensuring that any verifiable data can be brought on-chain. It supports basic spot prices, sophisticated pricing specs (TWAP/VWAP), Snapshot Vote Results, and custom data needs. - -### Querying the price of $ETH through Tellor - -Here’s an example of how to use a Tellor data feed to query the current price of $ETH on-chain. The way it works is that a query is crafted asking for the price of one currency against another and sent to the oracle contract. If the information for that query is available, it will be returned. Oracle contracts can be found on the [Contracts Reference](https://docs.tellor.io/tellor/the-basics/contracts-reference) page. - -Tellor provides an npm package with the contracts needed to query the contract. We first install that package in our project: - -```bash -npm install usingtellor -``` - -Our function will just wrap the call to the Oracle contract with the query we are interested in. In this case, we want to obtain the “SpotPrice” of “eth” against “usd”. We will request this information to the Arbitrum oracle contract `0xD9157453E2668B2fc45b7A803D3FEF3642430cC0`. We’ll use this example contract: - -```solidity -contract ARBPriceConsumer is UsingTellor { - /** - * Network: Arbitrum One - * Aggregator: ARB/USD - * Address: 0xD9157453E2668B2fc45b7A803D3FEF3642430cC0 - */ - constructor(address payable _tellorAddress) UsingTellor(_tellorAddress) - {} - - /** - * Returns the latest price. - */ - function getLatestPrice() public view returns (uint256) { - bytes memory _queryData = abi.encode("SpotPrice", abi.encode("eth", "usd")); - bytes32 _queryId = keccak256(_queryData); - - (bytes memory _value, uint256 _timestampRetrieved) = - getDataBefore(_queryId, block.timestamp - 20 minutes); - if (_timestampRetrieved == 0) return 0; - require(block.timestamp - _timestampRetrieved < 24 hours); - return abi.decode(_value, (uint256)); - } -} -``` - -You can adapt this contract to your needs. Just remember to use the ticker of the assets you want to request the price for and to **deploy your contract to the appropriate network, with the address of the Oracle contract in that network**. Remember, we have a [Quickstart](/build-decentralized-apps/01-quickstart-solidity-hardhat.md) available that goes through the process of compiling and deploying a contract. - -### See also - -- [Tellor’s documentation](https://docs.tellor.io/) demonstrates how to query price feeds and other data feeds. -- [How to use Supra's price feed oracle](/for-devs/third-party-docs/Supra/use-supras-price-feed-oracle) -- [How to use Supra's VRF](/for-devs/third-party-docs/Supra/use-supras-vrf) diff --git a/arbitrum-docs/build-decentralized-apps/oracles/03-reference.mdx b/arbitrum-docs/build-decentralized-apps/oracles/03-reference.mdx deleted file mode 100644 index 977dc7a1f..000000000 --- a/arbitrum-docs/build-decentralized-apps/oracles/03-reference.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: 'Oracles reference' -description: An overview of popular oracles that exist in the Arbitrum ecosystem -user_story: As a developer, I want to understand what oracles are available in the Arbitrum ecosystem. -content_type: overview ---- - -import KnowMoreToolsBox from '../../for-devs/partials/_know-more-tools-box-partial.md'; - - - -The following [oracles](/build-decentralized-apps/oracles/01-overview.mdx) will help you integrate off-chain data into your decentralized apps (dApps): - -| Name | Description | Example/Documentation | -| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -| Chainlink | Chainlink is a widely-recognized Web3 services platform specializing in decentralized oracle networks. It enables building Ethereum and Arbitrum dApps that connect to a variety of off-chain data feeds and APIs, including asset prices, weather data, random number generation, and more. | [How to use Chainlink](/build-decentralized-apps/oracles/02-how-to-use-oracles.mdx#chainlink) | -| API3 | API3 is a collaborative project delivering traditional API services to smart contract platforms in a decentralized and trust-minimized way. It offers technology for Airnodes to push off-chain data to on-chain contracts, and the data can be queried directly through Airnodes or dAPIs. | [How to use API3](/build-decentralized-apps/oracles/02-how-to-use-oracles.mdx#api3) | -| Tellor | Tellor is a decentralized oracle network that incentivizes data reporting and validation. It supports a range of data types, including basic spot prices, sophisticated pricing specs (TWAP/VWAP), Snapshot Vote Results, and custom data needs. | [How to use Tellor](/build-decentralized-apps/oracles/02-how-to-use-oracles.mdx#tellor) | -| Supra | Supra is an Oracle & IntraLayer offering a toolkit of cross-chain solutions such as data oracles, asset bridges, and automation networks. It aims to interlink all blockchains, whether public (L1s and L2s) or private (enterprises). | [Supra Overview](https://supraoracles.com/docs/overview/) | diff --git a/arbitrum-docs/build-decentralized-apps/precompiles/01-overview.md b/arbitrum-docs/build-decentralized-apps/precompiles/01-overview.mdx similarity index 95% rename from arbitrum-docs/build-decentralized-apps/precompiles/01-overview.md rename to arbitrum-docs/build-decentralized-apps/precompiles/01-overview.mdx index ba8fe7daf..b4dddd6c9 100644 --- a/arbitrum-docs/build-decentralized-apps/precompiles/01-overview.md +++ b/arbitrum-docs/build-decentralized-apps/precompiles/01-overview.mdx @@ -7,4 +7,4 @@ content_type: concept Precompiles are predefined smart contracts that have special addresses and provide specific functionality which is executed not at the EVM bytecode level, but natively by the Arbitrum client itself. Precompiles are primarily used to introduce specific functions that would be computationally expensive if executed in EVM bytecode, and functions that facilitate the interaction between the Layer 1 (L1) and the Layer 2 (L2). By having them natively in the Arbitrum client, they can be optimized for performance. -Besides supporting all precompiles available in Ethereum, Arbitrum provides L2-specific precompiles with methods smart contracts can call the same way they can solidity functions. For more details on the addresses these precompiles live, and the specific methods available, please refer to the [methods documentation](/build-decentralized-apps/precompiles/02-reference.md). +Besides supporting all precompiles available in Ethereum, Arbitrum provides L2-specific precompiles with methods smart contracts can call the same way they can solidity functions. For more details on the addresses these precompiles live, and the specific methods available, please refer to the [methods documentation](/build-decentralized-apps/precompiles/02-reference.mdx). diff --git a/arbitrum-docs/build-decentralized-apps/precompiles/02-reference.md b/arbitrum-docs/build-decentralized-apps/precompiles/02-reference.mdx similarity index 95% rename from arbitrum-docs/build-decentralized-apps/precompiles/02-reference.md rename to arbitrum-docs/build-decentralized-apps/precompiles/02-reference.mdx index c63ffd763..321ec6202 100644 --- a/arbitrum-docs/build-decentralized-apps/precompiles/02-reference.md +++ b/arbitrum-docs/build-decentralized-apps/precompiles/02-reference.mdx @@ -5,7 +5,7 @@ user_story: As a developer, I want to understand the most useful precompiles ava content_type: reference --- -ArbOS provides L2-specific precompiles with methods smart contracts can call the same way they can solidity functions. This reference page exhaustively documents the specific calls ArbOS makes available through precompiles. For a more conceptual description of what precompiles are and how they work, please refer to the [precompiles conceptual page](/build-decentralized-apps/precompiles/01-overview.md). +ArbOS provides L2-specific precompiles with methods smart contracts can call the same way they can solidity functions. This reference page exhaustively documents the specific calls ArbOS makes available through precompiles. For a more conceptual description of what precompiles are and how they work, please refer to the [precompiles conceptual page](/build-decentralized-apps/precompiles/01-overview.mdx). This reference page is divided into two sections. The first one lists all precompiles in a summary table with links to the reference of the specific precompile, along with the address where they live, their purpose and links to the go implementation and solidity interface. The second one details the methods available in each precompile with links to the specific implementation. @@ -77,7 +77,7 @@ ArbAddressTable ([Interface][arbaddresstable_link_interface] | [Implementation][ Precompile address: `0x0000000000000000000000000000000000000066` -import ArbAddressTableRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAddressTable.md'; +import ArbAddressTableRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAddressTable.mdx'; @@ -89,7 +89,7 @@ Compression ratios are measured in basis points. Methods that are checkmarked ar Precompile address: `0x000000000000000000000000000000000000006D` -import ArbAggregatorRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAggregator.md'; +import ArbAggregatorRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAggregator.mdx'; @@ -107,7 +107,7 @@ ArbDebug ([Interface][arbdebug_link_interface] | [Implementation][arbdebug_link_ Precompile address: `0x00000000000000000000000000000000000000ff` -import ArbDebugRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbDebug.md'; +import ArbDebugRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbDebug.mdx'; @@ -117,7 +117,7 @@ ArbFunctionTable ([Interface][arbfunctiontable_link_interface] | [Implementation Precompile address: `0x0000000000000000000000000000000000000068` -import ArbFunctionTableRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbFunctionTable.md'; +import ArbFunctionTableRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbFunctionTable.mdx'; @@ -127,7 +127,7 @@ ArbGasInfo ([Interface][arbgasinfo_link_interface] | [Implementation][arbgasinfo Precompile address: `0x000000000000000000000000000000000000006C` -import ArbGasInfoRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbGasInfo.md'; +import ArbGasInfoRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbGasInfo.mdx'; @@ -137,7 +137,7 @@ ArbInfo ([Interface][arbinfo_link_interface] | [Implementation][arbinfo_link_imp Precompile address: `0x0000000000000000000000000000000000000065` -import ArbInfoRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbInfo.md'; +import ArbInfoRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbInfo.mdx'; @@ -147,7 +147,7 @@ ArbosTest ([Interface][arbostest_link_interface] | [Implementation][arbostest_li Precompile address: `0x0000000000000000000000000000000000000069` -import ArbosTestRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbosTest.md'; +import ArbosTestRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbosTest.mdx'; @@ -163,7 +163,7 @@ Most of Arbitrum Classic's owner methods have been removed since they no longer Precompile address: `0x0000000000000000000000000000000000000070` -import ArbOwnerRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwner.md'; +import ArbOwnerRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwner.mdx'; @@ -173,17 +173,17 @@ ArbOwnerPublic ([Interface][arbownerpublic_link_interface] | [Implementation][ar Precompile address: `0x000000000000000000000000000000000000006b` -import ArbOwnerPublicRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwnerPublic.md'; +import ArbOwnerPublicRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwnerPublic.mdx'; ### ArbRetryableTx -ArbRetryableTx ([Interface][arbretryabletx_link_interface] | [Implementation][arbretryabletx_link_implementation]) provides methods for managing retryables. The model has been adjusted for Nitro, most notably in terms of how retry transactions are scheduled. For more information on retryables, please see [the retryable documentation](/how-arbitrum-works/arbos/introduction.md#Retryables). +ArbRetryableTx ([Interface][arbretryabletx_link_interface] | [Implementation][arbretryabletx_link_implementation]) provides methods for managing retryables. The model has been adjusted for Nitro, most notably in terms of how retry transactions are scheduled. For more information on retryables, please see [the retryable documentation](/how-arbitrum-works/10-l1-to-l2-messaging.mdx#retryable-tickets). Precompile address: `0x000000000000000000000000000000000000006E` -import ArbRetryableTxRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbRetryableTx.md'; +import ArbRetryableTxRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbRetryableTx.mdx'; @@ -193,7 +193,7 @@ ArbStatistics ([Interface][arbstatistics_link_interface] | [Implementation][arbs Precompile address: `0x000000000000000000000000000000000000006F` -import ArbStatisticsRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbStatistics.md'; +import ArbStatisticsRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbStatistics.mdx'; @@ -203,7 +203,7 @@ ArbSys ([Interface][arbsys_link_interface] | [Implementation][arbsys_link_implem Precompile address: `0x0000000000000000000000000000000000000064` -import ArbSysRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbSys.md'; +import ArbSysRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbSys.mdx'; @@ -213,7 +213,7 @@ ArbWasm ([Interface][arbwasm_link_interface] | [Implementation][arbwasm_link_imp Precompile address: `0x0000000000000000000000000000000000000071` -import ArbWasmRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasm.md'; +import ArbWasmRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasm.mdx'; @@ -223,6 +223,6 @@ ArbWasmCache ([Interface][arbwasmcache_link_interface] | [Implementation][arbwas Precompile address: `0x0000000000000000000000000000000000000072` -import ArbWasmCacheRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasmCache.md'; +import ArbWasmCacheRef from '../../for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasmCache.mdx'; diff --git a/arbitrum-docs/build-decentralized-apps/reference/01-node-providers.md b/arbitrum-docs/build-decentralized-apps/reference/01-node-providers.mdx similarity index 100% rename from arbitrum-docs/build-decentralized-apps/reference/01-node-providers.md rename to arbitrum-docs/build-decentralized-apps/reference/01-node-providers.mdx diff --git a/arbitrum-docs/build-decentralized-apps/reference/04-development-frameworks.md b/arbitrum-docs/build-decentralized-apps/reference/04-development-frameworks.mdx similarity index 99% rename from arbitrum-docs/build-decentralized-apps/reference/04-development-frameworks.md rename to arbitrum-docs/build-decentralized-apps/reference/04-development-frameworks.mdx index de7485e54..71111f19e 100644 --- a/arbitrum-docs/build-decentralized-apps/reference/04-development-frameworks.md +++ b/arbitrum-docs/build-decentralized-apps/reference/04-development-frameworks.mdx @@ -5,7 +5,7 @@ user_story: As a developer, I want to understand the popular development framewo content_type: overview --- -import KnowMoreToolsBox from '../../for-devs/partials/_know-more-tools-box-partial.md'; +import KnowMoreToolsBox from '../../for-devs/partials/_know-more-tools-box-partial.mdx'; diff --git a/arbitrum-docs/build-decentralized-apps/reference/05-web3-libraries-tools.md b/arbitrum-docs/build-decentralized-apps/reference/05-web3-libraries-tools.mdx similarity index 99% rename from arbitrum-docs/build-decentralized-apps/reference/05-web3-libraries-tools.md rename to arbitrum-docs/build-decentralized-apps/reference/05-web3-libraries-tools.mdx index a900081ff..60c9a7e9a 100644 --- a/arbitrum-docs/build-decentralized-apps/reference/05-web3-libraries-tools.md +++ b/arbitrum-docs/build-decentralized-apps/reference/05-web3-libraries-tools.mdx @@ -5,7 +5,7 @@ user_story: As a developer, I want to understand what web3 libraries and tools a content_type: overview --- -import KnowMoreToolsBox from '../../for-devs/partials/_know-more-tools-box-partial.md'; +import KnowMoreToolsBox from '../../for-devs/partials/_know-more-tools-box-partial.mdx'; diff --git a/arbitrum-docs/build-decentralized-apps/reference/06-monitoring-tools-block-explorers.md b/arbitrum-docs/build-decentralized-apps/reference/06-monitoring-tools-block-explorers.mdx similarity index 77% rename from arbitrum-docs/build-decentralized-apps/reference/06-monitoring-tools-block-explorers.md rename to arbitrum-docs/build-decentralized-apps/reference/06-monitoring-tools-block-explorers.mdx index 15fa7cb13..965f2af47 100644 --- a/arbitrum-docs/build-decentralized-apps/reference/06-monitoring-tools-block-explorers.md +++ b/arbitrum-docs/build-decentralized-apps/reference/06-monitoring-tools-block-explorers.mdx @@ -5,17 +5,17 @@ user_story: As a developer, I want to understand what monitoring tools and block content_type: overview --- -import KnowMoreToolsBox from '../../for-devs/partials/_know-more-tools-box-partial.md'; +import KnowMoreToolsBox from '../../for-devs/partials/_know-more-tools-box-partial.mdx'; Here, we offer a compilation of tools and blockchain explorers that enable you to examine and oversee transactions, smart contracts, and overall blockchain activity related to decentralized applications (dApps) on different Arbitrum chains. -| Tool | Use-cases | Relevant links | -| ---------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Arbiscan | Track/trace transactions and examine addresses on Arbitrum networks |
  • Arbitrum One: [https://arbiscan.io/](https://arbiscan.io/)
  • Arbitrum Nova: [https://nova.arbiscan.io/](https://nova.arbiscan.io/)
  • Arbitrum Sepolia: [https://sepolia.arbiscan.io](https://sepolia.arbiscan.io)
| -| Blockscout | Track/trace transactions and examine addresses on Arbitrum networks |
  • Stylus Testnet: [https://stylus-testnet-explorer.arbitrum.io](https://stylus-testnet-explorer.arbitrum.io)
| -| Chainbase | Index, transform, and use on-chain data at scale | [Chainbase](https://chainbase.com/) | -| DexGuru | Track/trace transactions and examine addresses on Arbitrum networks |
  • Arbitrum One: [https://arbitrum.dex.guru/](https://arbitrum.dex.guru/)
  • Arbitrum Nova: [https://nova.dex.guru/](https://nova.dex.guru/)
| -| Dune | Visualize and analyze Arbitrum network data |
  • [Dune](https://dune.com/)
  • [Arbitrum community-created Duune dashboard](https://dune.com/browse/dashboards?q=arbitrum)
| -| OKLINK | Track/trace transactions and examine addresses on Arbitrum One network |
  • Arbitrum One: [https://www.oklink.com/arbitrum](https://www.oklink.com/arbitrum)
| +| Tool | Use-cases | Relevant links | +| ---------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Arbiscan | Track/trace transactions and examine addresses on Arbitrum networks |
  • Arbitrum One: [https://arbiscan.io/](https://arbiscan.io/)
  • Arbitrum Nova: [https://nova.arbiscan.io/](https://nova.arbiscan.io/)
  • Arbitrum Sepolia: [https://sepolia.arbiscan.io](https://sepolia.arbiscan.io)
| +| Blockscout | Track/trace transactions and examine addresses on Arbitrum networks |
  • Arbitrum One: [https://arbitrum.blockscout.com/](https://arbitrum.blockscout.com/)
  • Arbitrum Nova: [https://arbitrum-nova.blockscout.com/](https://arbitrum-nova.blockscout.com/)
  • Arbitrum Sepolia: [https://arbitrum-sepolia.blockscout.com/](https://arbitrum-sepolia.blockscout.com/)
| +| Chainbase | Index, transform, and use on-chain data at scale | [Chainbase](https://chainbase.com/) | +| DexGuru | Track/trace transactions and examine addresses on Arbitrum networks |
  • Arbitrum One: [https://arbitrum.dex.guru/](https://arbitrum.dex.guru/)
  • Arbitrum Nova: [https://nova.dex.guru/](https://nova.dex.guru/)
| +| Dune | Visualize and analyze Arbitrum network data |
  • [Dune](https://dune.com/)
  • [Arbitrum community-created Duune dashboard](https://dune.com/browse/dashboards?q=arbitrum)
| +| OKLINK | Track/trace transactions and examine addresses on Arbitrum One network |
  • Arbitrum One: [https://www.oklink.com/arbitrum](https://www.oklink.com/arbitrum)
| diff --git a/arbitrum-docs/build-decentralized-apps/reference/07-debugging-tools.md b/arbitrum-docs/build-decentralized-apps/reference/07-debugging-tools.mdx similarity index 98% rename from arbitrum-docs/build-decentralized-apps/reference/07-debugging-tools.md rename to arbitrum-docs/build-decentralized-apps/reference/07-debugging-tools.mdx index 91f56cba6..4d89d780b 100644 --- a/arbitrum-docs/build-decentralized-apps/reference/07-debugging-tools.md +++ b/arbitrum-docs/build-decentralized-apps/reference/07-debugging-tools.mdx @@ -5,7 +5,7 @@ user_story: As a developer, I want to understand what debugging tools are availa content_type: overview --- -import KnowMoreToolsBox from '../../for-devs/partials/_know-more-tools-box-partial.md'; +import KnowMoreToolsBox from '../../for-devs/partials/_know-more-tools-box-partial.mdx'; diff --git a/arbitrum-docs/build-decentralized-apps/reference/08-mainnet-risks.md b/arbitrum-docs/build-decentralized-apps/reference/08-mainnet-risks.mdx similarity index 91% rename from arbitrum-docs/build-decentralized-apps/reference/08-mainnet-risks.md rename to arbitrum-docs/build-decentralized-apps/reference/08-mainnet-risks.mdx index 1e094cb41..69463cd14 100644 --- a/arbitrum-docs/build-decentralized-apps/reference/08-mainnet-risks.md +++ b/arbitrum-docs/build-decentralized-apps/reference/08-mainnet-risks.mdx @@ -6,7 +6,7 @@ author: dzgoldman # Arbitrum: Understanding the risks -Arbitrum One — the first permissionless Ethereum layer 2 rollup with full Ethereum smart contract functionality — is [live on mainnet](https://offchain.medium.com/mainnet-for-everyone-27ce0f67c85e) — as is [Nova](https://medium.com/offchainlabs/its-time-for-a-new-dawn-nova-is-open-to-the-public-a081df1e4ad2), our first [AnyTrust chain](/how-arbitrum-works/inside-anytrust.md); We're sure you're (almost) as excited as we are! +Arbitrum One — the first permissionless Ethereum layer 2 rollup with full Ethereum smart contract functionality — is [live on mainnet](https://offchain.medium.com/mainnet-for-everyone-27ce0f67c85e) — as is [Nova](https://medium.com/offchainlabs/its-time-for-a-new-dawn-nova-is-open-to-the-public-a081df1e4ad2), our first [AnyTrust chain](/how-arbitrum-works/08-anytrust-protocol.mdx); We're sure you're (almost) as excited as we are! Here are some risks you should know about before using the system: ### State Of progressive decentralization @@ -16,7 +16,7 @@ The Arbitrum DAO system is the owner of both the Arbitrum One and Arbitrum AnyTr ### General words of caution: Software bugs Offchain Labs’ [implementation](https://github.com/OffchainLabs/nitro) of the Arbitrum protocol has been carefully constructed, is perpetually being audited by several independent firms, and is continuously reviewed and tested following best engineering practices. -That said, there remains a non-zero chance that our codebase contains some undiscovered vulnerabilities that put user funds at risk. Users should carefully factor this risk into their decision to use Arbitrum One and/or Arbitrum Nova, and in deciding how much of their value to entrust into the system. Note that Offchain Labs also sponsors a [multi-million dollar bug bounty program](https://immunefi.com/bounty/arbitrum/) to incentivize any party who funds such a critical bug to disclose it responsibly. +That said, there remains a non-zero chance that our codebase contains some undiscovered vulnerabilities that put user funds at risk. Users should carefully factor this risk into their decision to use Arbitrum One and/or Arbitrum Nova, and in deciding how much of their value to entrust into the system. Note that Offchain Labs also sponsors a [multi-million dollar bug bounty program](https://immunefi.com/bounty/arbitrum/) to incentivize any party who finds such a critical bug to disclose it responsibly. ### General words of caution: Scams diff --git a/arbitrum-docs/build-decentralized-apps/token-bridging/01-overview.md b/arbitrum-docs/build-decentralized-apps/token-bridging/01-overview.mdx similarity index 68% rename from arbitrum-docs/build-decentralized-apps/token-bridging/01-overview.md rename to arbitrum-docs/build-decentralized-apps/token-bridging/01-overview.mdx index e624f8c9d..46f4fe575 100644 --- a/arbitrum-docs/build-decentralized-apps/token-bridging/01-overview.md +++ b/arbitrum-docs/build-decentralized-apps/token-bridging/01-overview.mdx @@ -7,12 +7,12 @@ content_type: overview sidebar_position: 1 --- -Token bridging is a fundamental aspect of any Layer 2 (L2) protocol. Arbitrum uses its ability to pass messages between L1 and L2 (see [Cross-chain messaging](/build-decentralized-apps/04-cross-chain-messaging.md)) to allow projects to trustlessly move assets from Ethereum to an Arbitrum chain and back. Any asset and asset type can in principle be bridged, including Ether, ERC-20 tokens and ERC-721 tokens among others. +Token bridging is a fundamental aspect of any Layer 2 (L2) protocol. Arbitrum uses its ability to pass messages between L1 and L2 (see [Cross-chain messaging](/build-decentralized-apps/04-cross-chain-messaging.mdx)) to allow projects to trustlessly move assets from Ethereum to an Arbitrum chain and back. Any asset and asset type can in principle be bridged, including Ether, ERC-20 tokens and ERC-721 tokens among others. This section offers a series of conceptual documents explaining how asset bridging works and what options exist to bridge ether (ETH) and other types of asset between layers, as well as a series of how-tos showcasing the different methods available for making your token bridgeable. This section is divided in 3 parts: -- [ETH bridging](/build-decentralized-apps/token-bridging/02-token-bridge-ether.md): explains how Arbitrum handles bridging ETH, the native token of Ethereum and the Arbitrum chains, between L1 and L2. -- [ERC-20 token bridging](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md): explains the architecture of the token bridge for this type of asset, describing the different options available to make a token bridgeable. +- [ETH bridging](/build-decentralized-apps/token-bridging/02-token-bridge-ether.mdx): explains how Arbitrum handles bridging ETH, the native token of Ethereum and the Arbitrum chains, between L1 and L2. +- [ERC-20 token bridging](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx): explains the architecture of the token bridge for this type of asset, describing the different options available to make a token bridgeable. - [Bridge tokens programmatically](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/01-get-started.mdx): goes over the process of making an ERC-20 token bridgeable using the different types of gateway available in the token bridge. diff --git a/arbitrum-docs/build-decentralized-apps/token-bridging/02-token-bridge-ether.md b/arbitrum-docs/build-decentralized-apps/token-bridging/02-token-bridge-ether.mdx similarity index 73% rename from arbitrum-docs/build-decentralized-apps/token-bridging/02-token-bridge-ether.md rename to arbitrum-docs/build-decentralized-apps/token-bridging/02-token-bridge-ether.mdx index 13b64a79c..c6b97d1c6 100644 --- a/arbitrum-docs/build-decentralized-apps/token-bridging/02-token-bridge-ether.md +++ b/arbitrum-docs/build-decentralized-apps/token-bridging/02-token-bridge-ether.mdx @@ -28,7 +28,7 @@ As far as the L1 knows, all deposited funds are held by Arbitrum's Bridge contra ## Withdrawing ether -Withdrawing ether can be done using the [ArbSys precompile](/build-decentralized-apps/precompiles/02-reference.md#arbsys)'s `withdrawEth` method: +Withdrawing ether can be done using the [ArbSys precompile](/build-decentralized-apps/precompiles/02-reference.mdx#arbsys)'s `withdrawEth` method: ```sol ArbSys(100).withdrawEth{ value: 2300000 }(destAddress) @@ -36,7 +36,7 @@ ArbSys(100).withdrawEth{ value: 2300000 }(destAddress) Upon withdrawing, the Ether balance is burnt on the Arbitrum side, and will later be made available on the Ethereum side. -`ArbSys.withdrawEth` is actually a convenience function which is equivalent to calling `ArbSys.sendTxToL1` with empty calldataForL1. Like any other `sendTxToL1` call, it will require an additional call to `Outbox.executeTransaction` on L1 after the dispute period elapses for the user to finalize claiming their funds on L1 (see ["L2 to L1 Messages"](/how-arbitrum-works/arbos/l2-l1-messaging.md)). Once the withdrawal is executed from the Outbox, the user's Ether balance will be credited on L1. +`ArbSys.withdrawEth` is a convenience function equivalent to calling `ArbSys.sendTxToL1` with empty `calldataForL1`. Like any other `sendTxToL1` call, it will require an additional call to `Outbox.executeTransaction` on L1 after the dispute period elapses for the user to finalize claiming their funds on L1 (see ["L2 to L1 Messages"](/how-arbitrum-works/11-l2-to-l1-messaging.mdx)). Once the withdrawal is executed from the Outbox, the user's Ether balance will be credited on L1. The following diagram depicts the process that funds follow during a withdraw operation. diff --git a/arbitrum-docs/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md b/arbitrum-docs/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx similarity index 96% rename from arbitrum-docs/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md rename to arbitrum-docs/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx index 365d5559b..78dbccc62 100644 --- a/arbitrum-docs/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md +++ b/arbitrum-docs/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx @@ -7,7 +7,7 @@ content_type: concept sidebar_position: 3 --- -The Arbitrum protocol itself technically has no native notion of any token standards, and gives no built-in advantage or special recognition to any particular token bridge. In this page we describe the "canonical bridge", which was implemented by Offchain Labs, and should be the primary bridge most users and applications use; it is (effectively) a decentralized app (dApp) with contracts on both Ethereum (the Layer 1, or L1) and Arbitrum (the Layer 2, or L2) that leverages Arbitrum's [cross-chain message passing system](/build-decentralized-apps/04-cross-chain-messaging.md) to achieve basic desired token-bridging functionality. We recommend that you use it! +The Arbitrum protocol itself technically has no native notion of any token standards, and gives no built-in advantage or special recognition to any particular token bridge. In this page we describe the "canonical bridge", which was implemented by Offchain Labs, and should be the primary bridge most users and applications use; it is (effectively) a decentralized app (dApp) with contracts on both Ethereum (the Layer 1, or L1) and Arbitrum (the Layer 2, or L2) that leverages Arbitrum's [cross-chain message passing system](/build-decentralized-apps/04-cross-chain-messaging.mdx) to achieve basic desired token-bridging functionality. We recommend that you use it! ## Design rationale @@ -44,11 +44,11 @@ Our architecture consists of three types of contracts: ![img](./assets/gatewayUML.svg) -All Ethereum to Arbitrum token transfers are initiated via the router contract on L1, the `L1GatewayRouter` contract. `L1GatewayRouter` forwards the token's deposit call to the appropriate gateway contract on L1, the `L1ArbitrumGateway` contract. `L1GatewayRouter` is responsible for mapping L1 token addresses to L1Gateway contracts, thus acting as an L1/L2 address oracle, and ensuring that each token corresponds to only one gateway. The `L1ArbitrumGateway` then communicates to its counterpart gateway contract on L2, the `L2ArbitrumGateway` contract (typically/expectedly via [retryable tickets](/how-arbitrum-works/arbos/l1-l2-messaging.md)). +All Ethereum to Arbitrum token transfers are initiated via the router contract on L1, the `L1GatewayRouter` contract. `L1GatewayRouter` forwards the token's deposit call to the appropriate gateway contract on L1, the `L1ArbitrumGateway` contract. `L1GatewayRouter` is responsible for mapping L1 token addresses to L1Gateway contracts, thus acting as an L1/L2 address oracle and ensuring each token corresponds to only one gateway. The `L1ArbitrumGateway` then communicates to its counterpart gateway contract on L2, the `L2ArbitrumGateway` contract (typically/expectedly via [retryable tickets](/how-arbitrum-works/10-l1-to-l2-messaging.mdx)). ![img](./assets/bridge_deposits.png) -Similarly, Arbitrum to Ethereum transfers are initiated via the router contract on L2, the `L2GatewayRouter` contract, which calls the token's gateway contract on L2, the `L2ArbitrumGateway` contract, which in turn communicates to its corresponding gateway contract on L1, the `L1ArbitrumGateway` contract (typically/expectedly via [sending L2-to-L1 messages to the outbox](/how-arbitrum-works/arbos/l2-l1-messaging.md)). +Similarly, Arbitrum to Ethereum transfers are initiated via the router contract on L2, the `L2GatewayRouter` contract, which calls the token's gateway contract on L2, the `L2ArbitrumGateway` contract, which in turn communicates to its corresponding gateway contract on L1, the `L1ArbitrumGateway` contract (typically/expectedly via [sending L2-to-L1 messages to the outbox](/how-arbitrum-works/11-l2-to-l1-messaging.mdx)). ![img](./assets/bridge_withdrawals.png) @@ -106,7 +106,7 @@ Your token on L1 should conform to the [ICustomToken](https://github.com/Offchai Your token should conform to the minimum [IArbToken](https://github.com/OffchainLabs/token-bridge-contracts/blob/main/contracts/tokenbridge/arbitrum/IArbToken.sol) interface; i.e., it should have `bridgeMint` and `bridgeBurn` methods only callable by the L2CustomGateway contract, and the address of its corresponding Ethereum token accessible via `l1Address`. For an example implementation, see [L2GatewayToken](https://github.com/OffchainLabs/token-bridge-contracts/blob/main/contracts/tokenbridge/libraries/L2GatewayToken.sol). -import TokenCompatibilityPartial from './partials/_token-compatibility.md'; +import TokenCompatibilityPartial from './partials/_token-compatibility.mdx'; diff --git a/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/01-get-started.mdx b/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/01-get-started.mdx index 57d1ffb15..84fc66acb 100644 --- a/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/01-get-started.mdx +++ b/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/01-get-started.mdx @@ -5,19 +5,15 @@ user_story: As a developer, I want to understand how to bridge tokens between Et content_type: overview --- -import PublicPreviewBannerPartial from '../../../partials/_public-preview-banner-partial.mdx'; - - - Token bridging is a fundamental aspect of any Layer 2 (L2) protocol. It allows projects to quickly integrate with the Arbitrum ecosystem by leveraging their existing Layer 1 (L1) tokens. This section offers a series of how-tos showcasing the different methods available for making your token bridgeable. You have three options to consider when deciding on how to bridge your token: -1. [Standard gateway](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/02-how-to-bridge-tokens-standard.mdx): opt for this method if you want to have an standard ERC-20 token automatically deployed on Arbitrum, which will act as the L2 counterpart to your L1 token. For additional information, please refer to [this section on the standard ERC-20 gateway in the conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md#default-standard-bridging). -2. [Generic-custom gateway](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/03-how-to-bridge-tokens-generic-custom.mdx): choose this method if you require custom functionality for your ERC20 token on Arbitrum. You will deploy your counterpart token on Arbitrum equipped with the unique features you wish to implement. For additional information, please refer to [this section on the Arbitrum generic custom gateway in the conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md#the-arbitrum-generic-custom-gateway). -3. [Custom gateway](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/04-how-to-bridge-tokens-custom-gateway.mdx): this method is intended for edge cases where a custom ERC20 token is insufficient and you need an additional layer of flexibility with the gateway (for example, your token has the capacity to increase its supply on L2, and you want those L2-minted tokens to be withdrawable back to L1 and recognized by the L1 contract). For additional information, please refer to [this section on other types of gateways in the conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md#other-flavors-of-gateways). +1. [Standard gateway](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/02-how-to-bridge-tokens-standard.mdx): opt for this method if you want to have an standard ERC-20 token automatically deployed on Arbitrum, which will act as the L2 counterpart to your L1 token. For additional information, please refer to [this section on the standard ERC-20 gateway in the conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx#default-standard-bridging). +2. [Generic-custom gateway](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/03-how-to-bridge-tokens-generic-custom.mdx): choose this method if you require custom functionality for your ERC20 token on Arbitrum. You will deploy your counterpart token on Arbitrum equipped with the unique features you wish to implement. For additional information, please refer to [this section on the Arbitrum generic custom gateway in the conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx#the-arbitrum-generic-custom-gateway). +3. [Custom gateway](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/04-how-to-bridge-tokens-custom-gateway.mdx): this method is intended for edge cases where a custom ERC20 token is insufficient and you need an additional layer of flexibility with the gateway (for example, your token has the capacity to increase its supply on L2, and you want those L2-minted tokens to be withdrawable back to L1 and recognized by the L1 contract). For additional information, please refer to [this section on other types of gateways in the conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx#other-flavors-of-gateways). ## What if I just want to bridge a token programmatically? diff --git a/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/02-how-to-bridge-tokens-standard.mdx b/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/02-how-to-bridge-tokens-standard.mdx index 7317336a3..1d584001c 100644 --- a/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/02-how-to-bridge-tokens-standard.mdx +++ b/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/02-how-to-bridge-tokens-standard.mdx @@ -5,13 +5,9 @@ user_story: As a developer, I want to understand how to bridge tokens between Et content_type: how-to --- -import PublicPreviewBannerPartial from '../../../partials/_public-preview-banner-partial.mdx'; +In this how-to you’ll learn how to bridge your own token between Ethereum (Layer 1 or L1) and Arbitrum (Layer 2 or L2), using [Arbitrum’s standard ERC20 gateway](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx#default-standard-bridging). For alternative ways of bridging tokens, don’t forget to check out this [overview](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/01-get-started.mdx). - - -In this how-to you’ll learn how to bridge your own token between Ethereum (Layer 1 or L1) and Arbitrum (Layer 2 or L2), using [Arbitrum’s standard ERC20 gateway](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md#default-standard-bridging). For alternative ways of bridging tokens, don’t forget to check out this [overview](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/01-get-started.mdx). - -Familiarity with [Arbitrum’s token bridge system](/build-decentralized-apps/token-bridging/01-overview.md), smart contracts, and blockchain development is expected. If you’re new to blockchain development, consider reviewing our [Quickstart: Build a dApp with Arbitrum (Solidity, Hardhat)](/build-decentralized-apps/01-quickstart-solidity-hardhat.md) before proceeding. We will use [Arbitrum’s SDK](https://github.com/OffchainLabs/arbitrum-sdk) throughout this how-to, although no prior knowledge is required. +Familiarity with [Arbitrum’s token bridge system](/build-decentralized-apps/token-bridging/01-overview.mdx), smart contracts, and blockchain development is expected. If you’re new to blockchain development, consider reviewing our [Quickstart: Build a dApp with Arbitrum (Solidity, Hardhat)](/build-decentralized-apps/01-quickstart-solidity-hardhat.mdx) before proceeding. We will use [Arbitrum’s SDK](https://github.com/OffchainLabs/arbitrum-sdk) throughout this how-to, although no prior knowledge is required. We will go through all steps involved in the process. However, if you want to jump straight to the code, we have created [this script in our tutorials repository](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/token-deposit) that encapsulates the entire process. @@ -78,7 +74,7 @@ main() ## Step 2: Identify the bridge contracts to call (concepts summary) -As stated in the [token bridge conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md#default-standard-bridging), when using Arbitrum’s standard ERC20 gateway, you don’t need to do any pre-configuration process. Your token will be “bridgeable” out of the box. +As stated in the [token bridge conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx#default-standard-bridging), when using Arbitrum’s standard ERC20 gateway, you don’t need to do any pre-configuration process. Your token will be “bridgeable” out of the box. As explained in the conceptual page, there are 2 contracts that we need to be aware of when bridging tokens: @@ -87,7 +83,7 @@ As explained in the conceptual page, there are 2 contracts that we need to be aw For simplicity, in this how-to we’ll focus on the first case: bridging from Ethereum (L1) to Arbitrum (L2). -We’ll explain below what specific contracts and methods need to be called to bridge your token, but you can abstract this whole process of finding the right addresses by using Arbitrum’s SDK. You can use the [deposit](../../../sdk/reference/assetBridger/erc20Bridger.md#deposit) function of the [Erc20Bridger](../../../sdk/reference/assetBridger/erc20Bridger.md) class to bridge your tokens, which will use the appropriate router contract based on the network you’re connected to, and will relay the request to the appropriate gateway contract. You can also use the function [getParentGatewayAddress](../../../sdk/reference/assetBridger/erc20Bridger.md#getParentGatewayAddress) to get the address of the gateway contract that’s going to be used. But don’t worry about any of this yet, we’ll use those functions in the next steps. +We’ll explain below what specific contracts and methods need to be called to bridge your token, but you can abstract this whole process of finding the right addresses by using Arbitrum’s SDK. You can use the [deposit](../../../sdk/reference/assetBridger/erc20Bridger.md#deposit) function of the [Erc20Bridger](../../../sdk/reference/assetBridger/erc20Bridger.md) class to bridge your tokens, which will use the appropriate router contract based on the network you’re connected to, and will relay the request to the appropriate gateway contract. You can also use the function [getParentGatewayAddress](https://docs.arbitrum.io/sdk/reference/assetBridger/erc20Bridger#getparentgatewayaddress) to get the address of the gateway contract that’s going to be used. But don’t worry about any of this yet, we’ll use those functions in the next steps. Now, here’s an explanation of the contracts and methods that need to be called to manually bridge your token: @@ -176,7 +172,7 @@ As mentioned before, you can also call the method `outboundTransferCustomRefund` ## Step 5: Wait for execution on L2 -After calling the deposit method (or the `outboundTransferCustomRefund`, if you’re choosing the manual way), you’ll have to wait a bit until the message is executed on L2. We will verify the status of the underlying retryable ticket created to bridge the tokens. Check this page, to know more about [L1-to-L2 messages, also known as retryables](/how-arbitrum-works/arbos/l1-l2-messaging.md). +After calling the deposit method (or the `outboundTransferCustomRefund` if you’re choosing the manual way), you’ll have to wait a bit until the message is executed on L2. We will verify the status of the underlying retryable ticket created to bridge the tokens. Check this page to learn more about [L1-to-L2 messages, also known as retryables](/how-arbitrum-works/10-l1-to-l2-messaging.mdx). You can programmatically wait for the execution of the transaction on L2 using Arbitrum’s SDK. You should first wait for the execution of the submission transaction (the one sent to the router contract) and then the execution of the L2 transaction. @@ -201,7 +197,7 @@ If you’re going the manual way, you can verify if the message has been execute Finally, let’s find the token contract that has been created on L2. -Using Arbitrum’s SDK, you can call method [getChildErc20Address](../../../sdk/reference/assetBridger/erc20Bridger.md#getChildErc20Address) of the [Erc20Bridger](../../../sdk/reference/assetBridger/erc20Bridger.md) class, which will return the address of the token contract in L2 that corresponds to the L1 token contract sent as parameter. +Using Arbitrum’s SDK, you can call method [getChildErc20Address](https://docs.arbitrum.io/sdk/reference/assetBridger/erc20Bridger#getchildgatewayaddress) of the [Erc20Bridger](../../../sdk/reference/assetBridger/erc20Bridger.md) class, which will return the address of the token contract in L2 that corresponds to the L1 token contract sent as parameter. ```tsx /** @@ -214,7 +210,7 @@ const l2Token = erc20Bridger.getChildTokenContract(l2Provider, l2TokenAddress); To do this operation manually, you can call method `calculateL2TokenAddress` of the router contract. -If you visit that address in [Arbiscan](https://arbiscan.io/), you’ll notice that it is a copy of the contract [StandardArbERC20](https://github.com/OffchainLabs/token-bridge-contracts/blob/main/contracts/tokenbridge/arbitrum/StandardArbERC20.sol). This is the standard contract that is automatically created the first time a token that doesn’t exist in Arbitrum is bridged. [The token bridge conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md#default-standard-bridging) has more information about this contract. +If you visit that address in [Arbiscan](https://arbiscan.io/), you’ll notice that it is a copy of the contract [StandardArbERC20](https://github.com/OffchainLabs/token-bridge-contracts/blob/main/contracts/tokenbridge/arbitrum/StandardArbERC20.sol). This is the standard contract that is automatically created the first time a token that doesn’t exist in Arbitrum is bridged. [The token bridge conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx#default-standard-bridging) has more information about this contract. ## Conclusion @@ -222,6 +218,6 @@ After finishing this process, you’ll now have a counterpart token contract aut ## Resources -1. [Concept page: Token Bridge](/build-decentralized-apps/token-bridging/01-overview.md) +1. [Concept page: Token Bridge](/build-decentralized-apps/token-bridging/01-overview.mdx) 2. [Arbitrum SDK](https://github.com/OffchainLabs/arbitrum-sdk) 3. [Token bridge contract addresses](/build-decentralized-apps/reference/02-contract-addresses.mdx) diff --git a/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/03-how-to-bridge-tokens-generic-custom.mdx b/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/03-how-to-bridge-tokens-generic-custom.mdx index 988d474ad..88a79ed10 100644 --- a/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/03-how-to-bridge-tokens-generic-custom.mdx +++ b/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/03-how-to-bridge-tokens-generic-custom.mdx @@ -5,19 +5,15 @@ user_story: As a developer, I want to understand how to bridge tokens between Et content_type: how-to --- -import PublicPreviewBannerPartial from '../../../partials/_public-preview-banner-partial.mdx'; +In this how-to you’ll learn how to bridge your own token between Ethereum (Layer 1 or L1) and Arbitrum (Layer 2 or L2), using [Arbitrum’s generic-custom gateway](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx#the-arbitrum-generic-custom-gateway). For alternative ways of bridging tokens, don’t forget to check out this [overview](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/01-get-started.mdx). - - -In this how-to you’ll learn how to bridge your own token between Ethereum (Layer 1 or L1) and Arbitrum (Layer 2 or L2), using [Arbitrum’s generic-custom gateway](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md#the-arbitrum-generic-custom-gateway). For alternative ways of bridging tokens, don’t forget to check out this [overview](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/01-get-started.mdx). - -Familiarity with [Arbitrum’s token bridge system](/build-decentralized-apps/token-bridging/01-overview.md), smart contracts, and blockchain development is expected. If you’re new to blockchain development, consider reviewing our [Quickstart: Build a dApp with Arbitrum (Solidity, Hardhat)](/build-decentralized-apps/01-quickstart-solidity-hardhat.md) before proceeding. We will use [Arbitrum’s SDK](https://github.com/OffchainLabs/arbitrum-sdk) throughout this how-to, although no prior knowledge is required. +Familiarity with [Arbitrum’s token bridge system](/build-decentralized-apps/token-bridging/01-overview.mdx), smart contracts, and blockchain development is expected. If you’re new to blockchain development, consider reviewing our [Quickstart: Build a dApp with Arbitrum (Solidity, Hardhat)](/build-decentralized-apps/01-quickstart-solidity-hardhat.mdx) before proceeding. We will use [Arbitrum’s SDK](https://github.com/OffchainLabs/arbitrum-sdk) throughout this how-to, although no prior knowledge is required. We will go through all steps involved in the process. However, if you want to jump straight to the code, we have created [this script in our tutorials repository](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/custom-token-bridging) that encapsulates the entire process. ## Step 0: Review the prerequisites -As stated in the [token bridge conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md#the-arbitrum-generic-custom-gateway), there are a few prerequisites to keep in mind while using this method to make a token bridgeable. +As stated in the [token bridge conceptual page](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx#the-arbitrum-generic-custom-gateway), there are a few prerequisites to keep in mind while using this method to make a token bridgeable. First of all, the **L1 counterpart of the token**, must conform to the [ICustomToken](https://github.com/OffchainLabs/token-bridge-contracts/blob/main/contracts/tokenbridge/ethereum/ICustomToken.sol) interface. This means that: @@ -36,7 +32,7 @@ Also, the **L2 counterpart of the token**, must conform to the [IArbToken](https - It must have`bridgeMint` and `bridgeBurn` methods only callable by the L2CustomGateway contract - It must have an `l1Address` view method that returns the address of the token in L1 -import TokenCompatibilityPartial from '../partials/_token-compatibility.md'; +import TokenCompatibilityPartial from '../partials/_token-compatibility.mdx'; @@ -379,7 +375,7 @@ Yes, if your token has a standard ERC20 counterpart on L2, you can go through th ## Resources -1. [Concept page: Token Bridge](/build-decentralized-apps/token-bridging/01-overview.md) +1. [Concept page: Token Bridge](/build-decentralized-apps/token-bridging/01-overview.mdx) 2. [Arbitrum SDK](https://github.com/OffchainLabs/arbitrum-sdk) 3. [Token bridge contract addresses](/build-decentralized-apps/reference/02-contract-addresses.mdx) ) diff --git a/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/04-how-to-bridge-tokens-custom-gateway.mdx b/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/04-how-to-bridge-tokens-custom-gateway.mdx index 651d9b882..5c45239ff 100644 --- a/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/04-how-to-bridge-tokens-custom-gateway.mdx +++ b/arbitrum-docs/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/04-how-to-bridge-tokens-custom-gateway.mdx @@ -5,10 +5,6 @@ reader_audience: developers who want to build on Ethereum/Arbitrum and bridge to content_type: how-to --- -import PublicPreviewBannerPartial from '../../../partials/_public-preview-banner-partial.mdx'; - - - :::caution Do you really need a custom gateway? Before starting to implement and deploy a custom gateway, it is strongly encouraged to analyze the current solutions that Arbitrum’s token bridge provides: the [standard gateway](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/02-how-to-bridge-tokens-standard.mdx) and the [generic-custom gateway](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/03-how-to-bridge-tokens-generic-custom.mdx). These solutions provide enough functionality to solve the majority of bridging needs from projects. And if you are in doubt about your current approach, you can always ask for assistance on our [Discord server](https://discord.gg/arbitrum). @@ -17,7 +13,7 @@ Before starting to implement and deploy a custom gateway, it is strongly encoura In this how-to you’ll learn how to bridge your own token between Ethereum (Layer 1 or L1) and Arbitrum (Layer 2 or L2), using a custom gateway. For alternative ways of bridging tokens, don’t forget to check out this [overview](/build-decentralized-apps/token-bridging/bridge-tokens-programmatically/01-get-started.mdx). -Familiarity with [Arbitrum’s token bridge system](/build-decentralized-apps/token-bridging/01-overview.md), smart contracts, and blockchain development is expected. If you’re new to blockchain development, consider reviewing our [Quickstart: Build a dApp with Arbitrum (Solidity, Hardhat)](/build-decentralized-apps/01-quickstart-solidity-hardhat.md) before proceeding. We will use [Arbitrum’s SDK](https://github.com/OffchainLabs/arbitrum-sdk) throughout this how-to, although no prior knowledge is required. +Familiarity with [Arbitrum’s token bridge system](/build-decentralized-apps/token-bridging/01-overview.mdx), smart contracts, and blockchain development is expected. If you’re new to blockchain development, consider reviewing our [Quickstart: Build a dApp with Arbitrum (Solidity, Hardhat)](/build-decentralized-apps/01-quickstart-solidity-hardhat.mdx) before proceeding. We will use [Arbitrum’s SDK](https://github.com/OffchainLabs/arbitrum-sdk) throughout this how-to, although no prior knowledge is required. We will go through all steps involved in the process. However, if you want to jump straight to the code, we have created [this script in our tutorials repository](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/custom-gateway-bridging) that encapsulates the entire process. @@ -42,7 +38,7 @@ On the other hand, the **L2 counterpart of the gateway**, must conform to the [I - A method `outboundTransfer`, to handle external calls, and forwarded calls from `L2GatewayRouter.outboundTransfer`. - A method `finalizeInboundTransfer`, to handle messages coming ONLY from L1’s gateway. - Two methods `calculateL2TokenAddress` and `getOutboundCalldata` to handle other bridging operations. -- Methods to send cross-chain messages through the [ArbSys precompile](/build-decentralized-apps/precompiles/02-reference.md#arbsys). An example implementation can be found in `sendTxToL1` on [L2ArbitrumMessenger](https://github.com/OffchainLabs/token-bridge-contracts/blob/main/contracts/tokenbridge/arbitrum/L2ArbitrumMessenger.sol). +- Methods to send cross-chain messages through the [ArbSys precompile](/build-decentralized-apps/precompiles/02-reference.mdx#arbsys). An example implementation can be found in `sendTxToL1` on [L2ArbitrumMessenger](https://github.com/OffchainLabs/token-bridge-contracts/blob/main/contracts/tokenbridge/arbitrum/L2ArbitrumMessenger.sol). ### What about my custom tokens? @@ -843,6 +839,6 @@ The full code of this how-to and a more extensive deployment and testing script ## Resources -1. [Concept page: Token Bridge](/build-decentralized-apps/token-bridging/01-overview.md) +1. [Concept page: Token Bridge](/build-decentralized-apps/token-bridging/01-overview.mdx) 2. [Arbitrum SDK](https://github.com/OffchainLabs/arbitrum-sdk) 3. [Token bridge contract addresses](/build-decentralized-apps/reference/02-contract-addresses.mdx) diff --git a/arbitrum-docs/build-decentralized-apps/token-bridging/partials/_token-compatibility.md b/arbitrum-docs/build-decentralized-apps/token-bridging/partials/_token-compatibility.mdx similarity index 100% rename from arbitrum-docs/build-decentralized-apps/token-bridging/partials/_token-compatibility.md rename to arbitrum-docs/build-decentralized-apps/token-bridging/partials/_token-compatibility.mdx diff --git a/arbitrum-docs/for-devs/contribute.md b/arbitrum-docs/for-devs/contribute.md deleted file mode 100644 index 7795a031b..000000000 --- a/arbitrum-docs/for-devs/contribute.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: 'Contribute docs' -description: "Learn how to contribute to Arbitrum's documentation" -author: symbolpunk ---- - -import ContributeDocsPartial from '../partials/_contribute-docs-partial.mdx'; - - diff --git a/arbitrum-docs/for-devs/contribute.mdx b/arbitrum-docs/for-devs/contribute.mdx new file mode 100644 index 000000000..8e13ea78b --- /dev/null +++ b/arbitrum-docs/for-devs/contribute.mdx @@ -0,0 +1,9 @@ +--- +title: 'Contribute docs' +description: "Learn how to contribute to Arbitrum's open-source documentation. Enhance developer resources and play a key role in scaling Ethereum's leading Layer 2 ecosystem." +author: symbolpunk +--- + +import ContributeDocsPartial from '../partials/_contribute-docs-partial.mdx'; + + diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/chain-info.mdx b/arbitrum-docs/for-devs/dev-tools-and-resources/chain-info.mdx index f53517b15..b26147c18 100644 --- a/arbitrum-docs/for-devs/dev-tools-and-resources/chain-info.mdx +++ b/arbitrum-docs/for-devs/dev-tools-and-resources/chain-info.mdx @@ -26,8 +26,4 @@ import ArbitrumContractAddresses from '../../partials/_reference-arbitrum-contra import StylusFaucets from '../../stylus/reference/partials/_stylus-faucets.mdx'; -import PublicPreviewBannerPartial from '../../stylus/partials/_stylus-public-preview-banner-partial.md'; - - - diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAddressTable.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAddressTable.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAddressTable.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAddressTable.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAggregator.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAggregator.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAggregator.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbAggregator.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbDebug.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbDebug.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbDebug.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbDebug.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbFunctionTable.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbFunctionTable.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbFunctionTable.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbFunctionTable.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbGasInfo.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbGasInfo.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbGasInfo.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbGasInfo.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbInfo.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbInfo.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbInfo.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbInfo.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwner.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwner.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwner.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwner.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwnerPublic.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwnerPublic.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwnerPublic.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbOwnerPublic.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbRetryableTx.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbRetryableTx.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbRetryableTx.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbRetryableTx.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbStatistics.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbStatistics.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbStatistics.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbStatistics.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbSys.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbSys.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbSys.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbSys.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasm.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasm.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasm.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasm.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasmCache.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasmCache.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasmCache.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbWasmCache.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbosTest.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbosTest.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbosTest.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_ArbosTest.mdx diff --git a/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_NodeInterface.md b/arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_NodeInterface.mdx similarity index 100% rename from arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_NodeInterface.md rename to arbitrum-docs/for-devs/dev-tools-and-resources/partials/precompile-tables/_NodeInterface.mdx diff --git a/arbitrum-docs/for-devs/oracles/api3/api3.mdx b/arbitrum-docs/for-devs/oracles/api3/api3.mdx new file mode 100644 index 000000000..ae1125b7c --- /dev/null +++ b/arbitrum-docs/for-devs/oracles/api3/api3.mdx @@ -0,0 +1,168 @@ +--- +id: 'api3' +title: 'API3' +sidebar_label: 'API3' +description: 'Learn how to query $ARB random numbers and more.' +author: GreatSoshiant +sme: GreatSoshiant +user_story: As an Arbitrum developer, I want to learn how to use oracles in my dApp. +content_type: get-started +--- + +[API3](https://api3.org/) is a collaborative project to deliver traditional API services to smart contract platforms in a decentralized and trust-minimized way. API3 provides the technology for [Airnodes](https://docs.api3.org/reference/airnode/latest/understand/) to push off-chain data to on-chain contracts. This data can then be queried directly through the Airnode (initiating a “pull-type” request) or through [dAPIs](https://docs.api3.org/guides/dapis/) (data-feeds sourced directly from multiple first-party oracles owned and operated by API providers). + +### Querying the price of $ARB through API3 + +Here’s an example of how to use an API3 data feed to query the current price of $ARB on-chain. The [API3 market](https://market.api3.org/arbitrum) provides a list of all the dAPIs available across multiple chains including testnets. You can go forward and activate the dAPI you want to use. + +API3 provides an npm package with the contracts needed to access their feeds. We first install that package in our project: + +```bash +yarn add @api3/contracts +``` + +To use a data feed, we retrieve the information through the specific proxy address for that feed. We’ll use the IProxy interface to do so. + +```solidity +import "@api3/contracts/api3-server-v1/proxies/interfaces/IProxy.sol"; +``` + +In this case, we want to obtain the current price of $ARB in $USD in Arbitrum One, so we need to know the proxy address that will provide that information. We will search the feed on the API3 Market and connect our wallet. We would then want to see if the feed is active, and if it is, we can check its configuration parameters, deploy the proxy contract and click on `Integrate.` You can find the proxy address of ARB/USD [here](https://market.api3.org/arbitrum?search=ARB%2FUSD). + +:::info +If a dAPI is already active, you can use the proxy address directly. If it is not active, you can activate it by clicking on `Activate` and following the instructions to deploy a proxy contract. +::: + +We can now build the function to get the latest price of $ARB. We’ll use this example contract: + +```solidity +contract ARBPriceConsumer { + /** + * Network: Arbitrum One + * Aggregator: ARB/USD + * Proxy: 0x0cB281EC7DFB8497d07196Dc0f86D2eFD21066A5 + */ + address constant PROXY = 0x0cB281EC7DFB8497d07196Dc0f86D2eFD21066A5; + + /** + * Returns the latest price. + */ + function getLatestPrice() + external + view + returns (int224 value, uint256 timestamp) + { + (value, timestamp) = IProxy(PROXY).read(); + // If you have any assumptions about `value` and `timestamp`, make sure + // to validate them right after reading from the proxy. + } +} +``` + +You can adapt this contract to your needs. Just remember to use the address of the asset you want to request the price for in the appropriate network and to **deploy your contract to the same network**. Remember we have a [Quickstart](/build-decentralized-apps/01-quickstart-solidity-hardhat.mdx) available that goes through the process of compiling and deploying a contract. + +### Querying a random number through API3 + +[API3 QRNG](https://docs.api3.org/explore/qrng/) is a public utility provided with the courtesy of [Australian National University (ANU)](https://www.anu.edu.au/). It is served as a public good, it is free of charge (apart from the gas costs), and it provides quantum randomness when requiring RNG on-chain. + +To request randomness on-chain, the requester submits a request for a random number to `AirnodeRrpV0`. The ANU Airnode gathers the request from the `AirnodeRrpV0` protocol contract, retrieves the random number off-chain, and sends it back to `AirnodeRrpV0`. Once received, it performs a callback to the requester with the random number. + +Here’s an example of a basic `QrngRequester` that requests a random number. + +API3 provides an npm package with the contracts needed to access the ANU QRNG airnode. We first install that package in our project: + +```bash +yarn add @api3/airnode-protocol +``` + +We’ll need several pieces of data to request a random number: + +- `address airnodeRrp`: Address of the protocol contract. See the [Chains](https://docs.api3.org/reference/qrng/chains.html) page for a list of addresses on different chains. For Arbitrum, we’ll use `0xb015ACeEdD478fc497A798Ab45fcED8BdEd08924`. +- `address airnode`: The address that belongs to the Airnode that will be called to get the QRNG data via its endpoints. See the [Providers](https://docs.api3.org/reference/qrng/providers.html) page for a list of addresses on different chains. For Arbitrum we’ll use `0x9d3C147cA16DB954873A498e0af5852AB39139f2`. +- `bytes32 endpointId`: Endpoint ID known by the Airnode that will map to an API provider call (allowed to be `bytes32(0)`). You can also find that information in the [Providers](https://docs.api3.org/reference/qrng/providers.html) page. For Arbitrum we’ll use `0xfb6d017bb87991b7495f563db3c8cf59ff87b09781947bb1e417006ad7f55a78`. +- `address sponsorWallet`: The address of the wallet that will pay for the gas costs for the callback request to get the random number on-chain. You need to fund this wallet with enough ETH to cover the gas costs. + +To derive your sponsorWallet address, you can use the following command: + +```bash +yarn @api3/airnode-admin derive-sponsor-wallet-address \ + --airnode-address 0x9d3C147cA16DB954873A498e0af5852AB39139f2 \ + --airnode-xpub xpub6DXSDTZBd4aPVXnv6Q3SmnGUweFv6j24SK77W4qrSFuhGgi666awUiXakjXruUSCDQhhctVG7AQt67gMdaRAsDnDXv23bBRKsMWvRzo6kbf \ + --sponsor-address + + # The command outputs. + Sponsor wallet address: 0x6394...5906757 + # Use this address as the value for _sponsorWallet. +``` + +We can now build the function to get a random number. We’ll use this example contract: + +```solidity +import "@api3/airnode-protocol/contracts/rrp/requesters/RrpRequesterV0.sol"; + +contract QrngRequester is RrpRequesterV0 { + event RequestedUint256(bytes32 indexed requestId); + event ReceivedUint256(bytes32 indexed requestId, uint256 response); + + /** + * Network: Arbitrum One + * AirnodeRrpV0 Address: 0xb015ACeEdD478fc497A798Ab45fcED8BdEd08924 + * Airnode: 0x9d3C147cA16DB954873A498e0af5852AB39139f2 + * Endpoint ID: 0xfb6d017bb87991b7495f563db3c8cf59ff87b09781947bb1e417006ad7f55a78 + */ + address constant _airnodeRrp = 0xb015ACeEdD478fc497A798Ab45fcED8BdEd08924; + address constant airnode = 0x9d3C147cA16DB954873A498e0af5852AB39139f2; + bytes32 constant endpointIdUint256 = 0xfb6d017bb87991b7495f563db3c8cf59ff87b09781947bb1e417006ad7f55a78; + mapping(bytes32 => bool) public waitingFulfillment; + address sponsorWallet; + + constructor() RrpRequesterV0(_airnodeRrp) {} + + // Set the sponsor wallet address that you just derived. + function setSponsorWallet(address _sponsorWallet) external { + sponsorWallet = _sponsorWallet; + } + + function makeRequestUint256() external { + bytes32 requestId = airnodeRrp.makeFullRequest( + airnode, + endpointIdUint256, + address(this), + sponsorWallet, + address(this), + this.fulfillUint256.selector, + "" + ); + waitingFulfillment[requestId] = true; + emit RequestedUint256(requestId); + } + + function fulfillUint256(bytes32 requestId, bytes calldata data) + external + onlyAirnodeRrp + { + require( + waitingFulfillment[requestId], + "Request ID not known" + ); + waitingFulfillment[requestId] = false; + uint256 qrngUint256 = abi.decode(data, (uint256)); + + // Use `qrngUint256` here... + + emit ReceivedUint256(requestId, qrngUint256); + } +} +``` + +You can adapt this contract to your needs. Just remember to set the `sponsorWallet` address before making the request to use the appropriate network's addresses, and to **deploy your contract to the same network**. Remember, we have a [Quickstart](/build-decentralized-apps/01-quickstart-solidity-hardhat.mdx) available that goes through the process of compiling and deploying a contract. + +### More examples + +Refer to [API3’s documentation](https://docs.api3.org/) for more examples of querying other data feeds and Airnodes. + +You can also check out some other detailed guides: + +- [Subscribing to dAPIs](https://docs.api3.org/guides/dapis/subscribing-to-dapis/) +- [Reading a dAPI Proxy](https://docs.api3.org/guides/dapis/read-a-dapi/) +- [Using QRNG with Remix](https://docs.api3.org/guides/qrng/qrng-remix/) diff --git a/arbitrum-docs/for-devs/oracles/chainlink/chainlink.mdx b/arbitrum-docs/for-devs/oracles/chainlink/chainlink.mdx new file mode 100644 index 000000000..35a32c96c --- /dev/null +++ b/arbitrum-docs/for-devs/oracles/chainlink/chainlink.mdx @@ -0,0 +1,66 @@ +--- +id: 'chainlink' +title: 'Chainlink' +description: Learn how to integrate oracles into your Arbitrum dapp +user_story: As a developer, I want to understand how to use oracles in Arbitrum to get off-chain data on-chain. +content_type: how-to +--- + +[Chainlink](https://chain.link/) is a widely-recognized Web3 services platform that specializes in decentralized oracle networks. It lets you build Ethereum and Arbitrum dApps that connect to a variety of off-chain data feeds and APIs, including those that provide asset prices, weather data, random number generation, and more. + +### Querying the price of $ARB through Chainlink + +Here’s an example on how to use a price feed from Chainlink to query the current price of $ARB on-chain. We’ll use an interface provided by Chainlink that can be configured with the address of the proxy that holds the information we want to request, and wrap the operation in a contract. + +Chainlink provides an npm package with the contracts needed to access their feeds. We first install that package in our project: + +```tsx +yarn add @chainlink/contracts +``` + +To use a data feed, we retrieve the information through the `AggregatorV3Interface` and the proxy address of the feed we want to query. + +```solidity +import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; +``` + +In this case, we want to obtain the current price of $ARB in $USD in Arbitrum One, so we need to know the address of the proxy that will provide that information. Chainlink maintains a list of price feed address [here](https://docs.chain.link/data-feeds/price-feeds/addresses?network=arbitrum). For $ARB/$USD, we’ll use the address `0xb2A824043730FE05F3DA2efaFa1CBbe83fa548D6`. + +We can now build the function to get the latest price of $ARB. We’ll use this example contract: + +```solidity +contract ARBPriceConsumer { + AggregatorV3Interface internal priceFeed; + + /** + * Network: Arbitrum One + * Aggregator: ARB/USD + * Address: 0xb2A824043730FE05F3DA2efaFa1CBbe83fa548D6 + */ + address constant PROXY = 0xb2A824043730FE05F3DA2efaFa1CBbe83fa548D6; + + constructor() { + priceFeed = AggregatorV3Interface(PROXY); + } + + /** + * Returns the latest price. + */ + function getLatestPrice() public view returns (int) { + ( + /* uint80 roundID */, + int price, + /*uint startedAt*/, + /*uint timeStamp*/, + /*uint80 answeredInRound*/ + ) = priceFeed.latestRoundData(); + return price; + } +} +``` + +You can adapt this contract to your needs. Just remember to use the address of the asset you want to request the price for in the appropriate network, and to **deploy your contract to the same network**. Remember we have a [Quickstart](/build-decentralized-apps/01-quickstart-solidity-hardhat.mdx) available that goes through the process of compiling and deploying a contract. + +### More examples + +Refer to [Chainlink’s documentation](https://docs.chain.link/) for more examples of querying price feeds plus other data feeds available. diff --git a/arbitrum-docs/for-devs/oracles/chronicle/chronicle.mdx b/arbitrum-docs/for-devs/oracles/chronicle/chronicle.mdx new file mode 100644 index 000000000..9a6b4d982 --- /dev/null +++ b/arbitrum-docs/for-devs/oracles/chronicle/chronicle.mdx @@ -0,0 +1,87 @@ +--- +id: 'chronicle' +title: 'Chronicle' +description: Learn how to integrate oracles into your Arbitrum dapp +user_story: As a developer, I want to understand how to use oracles in Arbitrum to get off-chain data on-chain. +content_type: how-to +--- + +[Chronicle Protocol](https://chroniclelabs.org/) is a novel Oracle solution that overcomes the current limitations of transferring data on-chain by developing scalable, cost-efficient, decentralized, and verifiable Oracles, rewriting the rulebook on data transparency and accessibility. + +### Querying the price of $ARB using Chronicle + +Chronicle contracts are read-protected by a whitelist, meaning you won't be able to read them on-chain without your address being added to the whitelist. On the Testnet, users can add themselves to the whitelist through the SelfKisser contract; a process playfully referred to as "kissing" themselves. To access production Oracles on the Mainnet, please open a support ticket in [Discord](https://discord.com/invite/CjgvJ9EspJ) in the 🆘 | support channel. + +For the deployment addresses, please check out the [Dashboard](https://chroniclelabs.org/dashboard/oracles). + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; + +/** + * @title OracleReader + * @notice A simple contract to read from Chronicle oracles + * @dev To see the full repository, visit https://github.com/chronicleprotocol/OracleReader-Example. + * @dev Addresses in this contract are hardcoded for the Arbitrum Sepolia testnet. + * For other supported networks, check the https://chroniclelabs.org/dashboard/oracles. + */ +contract OracleReader { + /** + * @notice The Chronicle oracle to read from. + * Chronicle_ARB_USD_1 - 0xdD7c06561689c73f0A67F2179e273cCF45EFc964 + * Network: Arbitrum Sepolia + */ + + IChronicle public chronicle = IChronicle(address(0xdD7c06561689c73f0A67F2179e273cCF45EFc964)); + + /** + * @notice The SelfKisser granting access to Chronicle oracles. + * SelfKisser_1:0xc0fe3a070Bc98b4a45d735A52a1AFDd134E0283f + * Network: Arbitrum Sepolia + */ + ISelfKisser public selfKisser = ISelfKisser(address(0xc0fe3a070Bc98b4a45d735A52a1AFDd134E0283f)); + + constructor() { + // Note to add address(this) to chronicle oracle's whitelist. + // This allows the contract to read from the chronicle oracle. + selfKisser.selfKiss(address(chronicle)); + } + + /** + * @notice Function to read the latest data from the Chronicle oracle. + * @return val The current value returned by the oracle. + * @return age The timestamp of the last update from the oracle. + */ + function read() external view returns (uint256 val, uint256 age) { + (val, age) = chronicle.readWithAge(); + } +} + +// Copied from [chronicle-std](https://github.com/chronicleprotocol/chronicle-std/blob/main/src/IChronicle.sol). +interface IChronicle { + /** + * @notice Returns the oracle's current value. + * @dev Reverts if no value set. + * @return value The oracle's current value. + */ + function read() external view returns (uint256 value); + + /** + * @notice Returns the oracle's current value and its age. + * @dev Reverts if no value set. + * @return value The oracle's current value using 18 decimals places. + * @return age The value's age as a Unix Timestamp . + * */ + function readWithAge() external view returns (uint256 value, uint256 age); +} + +// Copied from [self-kisser](https://github.com/chronicleprotocol/self-kisser/blob/main/src/ISelfKisser.sol). +interface ISelfKisser { + /// @notice Kisses caller on oracle `oracle`. + function selfKiss(address oracle) external; +} +``` + +### More examples + +For more examples of integrating Chronicle Oracles, please check the [documentation portal](https://docs.chroniclelabs.org/). diff --git a/arbitrum-docs/for-devs/oracles/dia/dia.mdx b/arbitrum-docs/for-devs/oracles/dia/dia.mdx new file mode 100644 index 000000000..9e7b10977 --- /dev/null +++ b/arbitrum-docs/for-devs/oracles/dia/dia.mdx @@ -0,0 +1,67 @@ +--- +id: 'dia' +title: 'DIA' +description: Learn how to integrate oracles into your Arbitrum dapp +user_story: As a developer, I want to understand how to use oracles in Arbitrum to get off-chain data on-chain. +content_type: how-to +--- + +[DIA](https://www.diadata.org/) is a cross-chain oracle provider that enhances data transparency, customization, and accessibility. With a novel architecture aggregating raw trade data directly from first-party sources, namely centralized and decentralized exchanges, DIA offers 100% source transparency, bespoke customization, and chain-native asset price feeds. + +You can find an example on how to use DIA in your project on this [page](https://docs.diadata.org/introduction/intro-to-dia-oracles/request-an-oracle). + +### How to use DIA oracles on Arbitrum + +**Requesting a custom oracle**: DIA deploys oracles tailored to each dApp’s needs. Each oracle is customizable, including data sources, cleansing filters, pricing, computational methodologies, update mechanisms, and more. This flexibility ensures that the data and oracle remain robust and resilient to the market conditions and provide a global market price and specific individual or cross-chain market prices. +→ [Request a Custom Oracle for your dApp | DIA Documentation](https://docs.diadata.org/introduction/intro-to-dia-oracles/request-an-oracle) + +### Token Price Feeds + +DIA token price feeds provide smart contracts with real-time price information for [3,000+ cryptocurrencies](https://diadata.org/app/price), sourced from [80+ trusted, high-volume DEXs and CEXs](https://diadata.org/app/source/defi). + +### How to access DIA oracles? + +Here is an example of how to access a price value on DIA oracles: + +1. Access your custom oracle smart contract on Arbitrum. +2. Call `getValue(pair_name)` with `pair_name` being the full pair name such as `BTC/USD`. You can use the "Read" section on the explorer to execute this call. +3. The response of the call contains two values: + +- The current asset price in USD with a fix-comma notation of 8 decimals. +- The UNIX timestamp of the last oracle update. + +You can find DIA's oracle integration samples in Solidity and Vyper languages by visiting: +→ [Access the Oracle | DIA Documentation](https://docs.diadata.org/products/token-price-feeds/access-the-oracle) + +### Arbitrum demo price oracles + +DIA has deployed the following demo oracles for the Arbitrum community. It provides a limited selection of cryptocurrency price feeds with predefined configuration settings. + +:::note + +DIA demo oracles are not intended for use in production environments. Developers can request a dedicated, production-ready oracle with custom price feeds and configuration settings. Start the request process: [Request a Custom Oracle | DIA Documentation](https://docs.diadata.org/introduction/intro-to-dia-oracles/request-an-oracle) + +::: + +### Demo Oracle Smart Contracts + +| Network | Contract address | +| ------------- | --------------------------------------------------------------------------------------------------------------------------- | +| Arbitrum | [`0xd041478644048d9281f88558e6088e9da97df624`](https://arbiscan.io/address/0xd041478644048d9281f88558e6088e9da97df624) | +| Arbitrum Nova | [`0xa707a5c6a180da0ae2ef17ebff54f1f3589d9670`](https://nova.arbiscan.io/address/0xa707a5c6a180da0ae2ef17ebff54f1f3589d9670) | + +### Included Price Feeds + +[DIA/USD](https://diadata.org/app/price/asset/Ethereum/0x84cA8bc7997272c7CfB4D0Cd3D55cd942B3c9419/), [BTC/USD](https://diadata.org/app/price/asset/Bitcoin/0x0000000000000000000000000000000000000000/), [USDC/USD](https://diadata.org/app/price/asset/Ethereum/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/) + +### Supported token API endpoints + +DIA supports API and GraphQL endpoints to return cryptocurrency price data. You can [visit the DIA Documentation](https://docs.diadata.org/products/token-price-feeds/access-api-endpoints) to see all API endpoints. + +### NFT Price Feeds + +DIA NFT floor price feeds provide smart contracts with real-time price information of [18,000+ NFT collections](https://diadata.org/app/floor-price), sourced on-chain with 100% transparency from [multiple, cross-chain NFT marketplaces](https://diadata.org/app/source/nft). + +### Supported NFT API endpoints + +DIA supports API endpoints to return cryptocurrency price data. Developers can directly access the example endpoints listed below or [visit the DIA Documentation](https://docs.diadata.org/use-nexus-product/readme/token-price-feeds/access-api-endpoints) to see all API endpoints. diff --git a/arbitrum-docs/for-devs/third-party-docs/ORA/ora.md b/arbitrum-docs/for-devs/oracles/ora/ora.mdx similarity index 98% rename from arbitrum-docs/for-devs/third-party-docs/ORA/ora.md rename to arbitrum-docs/for-devs/oracles/ora/ora.mdx index 031a854c6..64e9b905e 100644 --- a/arbitrum-docs/for-devs/third-party-docs/ORA/ora.md +++ b/arbitrum-docs/for-devs/oracles/ora/ora.mdx @@ -1,9 +1,11 @@ --- -title: 'ORA Quickstart - Onchain AI Oracle for Arbitrum' +id: 'ora' +title: 'ORA' description: 'Learn how to use ORA Onchain AI Oracle' author: Gwen-M sme: Gwen-M sidebar_label: 'ORA' +content_type: how-to --- [ORA](https://ora.io) is Ethereum's Trustless AI. diff --git a/arbitrum-docs/for-devs/oracles/oracles-content-map.mdx b/arbitrum-docs/for-devs/oracles/oracles-content-map.mdx new file mode 100644 index 000000000..df7a8799d --- /dev/null +++ b/arbitrum-docs/for-devs/oracles/oracles-content-map.mdx @@ -0,0 +1,72 @@ +--- +id: oracles-content-map +title: Oracles providers +sidebar_label: Oracles overview +--- + +import Card from '@site/src/components/Cards/Card'; + +Learn how to run an Arbitrum node. + +
+ + + + + + + + + +
diff --git a/arbitrum-docs/for-devs/oracles/pyth/pyth.mdx b/arbitrum-docs/for-devs/oracles/pyth/pyth.mdx new file mode 100644 index 000000000..6354b5f06 --- /dev/null +++ b/arbitrum-docs/for-devs/oracles/pyth/pyth.mdx @@ -0,0 +1,77 @@ +--- +id: 'pyth' +title: 'Pyth' +description: 'Learn how to use Pyth Oracle' +author: pete-vielhaber +sme: pete-vielhaber +sidebar_label: 'pyth' +content_type: how-to +--- + +The [Pyth network](https://pyth.network/) a first-party oracle network, securely and transparently delivering real-time market data to [multiple chains](https://docs.pyth.network/price-feeds/contract-addresses). + +The network comprises some of the world’s [largest exchanges, market makers, and financial services providers](https://pyth.network/publishers). These publish proprietary data on-chain for aggregation and distribution to smart contract applications. + +## Pyth price feeds + +The Pyth network introduces an innovative low-latency [pull oracle design](https://docs.pyth.network/price-feeds/pull-updates), where users can pull price updates on-chain when needed, enabling everyone in the blockchain environment to access that data point. Pyth network updates the prices every 400ms, making Pyth the fastest on-chain oracle. + +Here is a working example of a contract that fetches the latest price of ARB/USD on the Arbitrum network. + +You have to pass Pyth's contract address for Arbitrum mainnet/testnet and the desired price feed ID to fetch the latest price. + +Install the Pyth SDK Solidity package in your project: + +```tsx +npm install @pythnetwork/pyth-sdk-solidity +``` + +And then, in a few lines of code you can fetch the latest price on the Arbitrum network. + +```solidity +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; +import "@pythnetwork/pyth-sdk-solidity/IPyth.sol"; +import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol"; +contract MyFirstPythContract { + IPyth pyth; + // Pass the address of Pyth's contract for Arbitrum mainnet(0xff1a0f4744e8582DF1aE09D5611b887B6a12925C) + constructor(address _pyth) { + pyth = IPyth(_pyth); + } + function fetchPrice( + bytes[] calldata updateData, + bytes32 priceFeed + ) public payable returns (int64) { + // Fetch the priceUpdate from hermes. + uint updateFee = pyth.getUpdateFee(updateData); + pyth.updatePriceFeeds{value: updateFee}(updateData); + // Fetch the latest price + PythStructs.Price memory price = pyth.getPrice(priceFeed); + return price.price; + } +} +``` + +Here you can fetch the `updateData` from Pyth's [Hermes](https://hermes.pyth.network/docs/) feed, which listens to Pythnet and Wormhole for price updates; or you can use the [pyth-evm-js](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/ethereum/sdk/js/src/EvmPriceServiceConnection.ts#L15) SDK. Check [How to Fetch Price Updates](https://docs.pyth.network/price-feeds/fetch-price-updates) to pull the latest data. + +## Pyth Entropy + +Pyth Entropy allows developers to quickly and easily generate secure **random numbers** on the blockchain. + +Check [how to generate random numbers in EVM contracts](https://docs.pyth.network/entropy/generate-random-numbers/evm) for a detailed walkthrough. + +### Supported networks for Arbitrum(Pyth Entropy): + +- Arbitrum: [`0x7698E925FfC29655576D0b361D75Af579e20AdAc`](https://arbiscan.io/address/0x7698E925FfC29655576D0b361D75Af579e20AdAc) +- Arbitrum Sepolia: [`0x549Ebba8036Ab746611B4fFA1423eb0A4Df61440`](https://sepolia.arbiscan.io/address/0x549Ebba8036Ab746611B4fFA1423eb0A4Df61440) + +## Additional resources + +Check out the following links to get started with Pyth: + +- [Pyth EVM Integration Guide](https://docs.pyth.network/price-feeds/use-real-time-data/evm) +- [Pyth Docs](https://docs.pyth.network/home) +- [Pyth API Reference](https://api-reference.pyth.network/price-feeds/evm/getPrice) +- [Pyth Examples](https://github.com/pyth-network/pyth-examples) +- [Pyth Price Feed Ids](https://pyth.network/developers/price-feed-ids) diff --git a/arbitrum-docs/for-devs/third-party-docs/Supra/use-supras-price-feed-oracle.mdx b/arbitrum-docs/for-devs/oracles/supra/use-supras-price-feed-oracle.mdx similarity index 96% rename from arbitrum-docs/for-devs/third-party-docs/Supra/use-supras-price-feed-oracle.mdx rename to arbitrum-docs/for-devs/oracles/supra/use-supras-price-feed-oracle.mdx index 8a281d06f..af88a02e1 100644 --- a/arbitrum-docs/for-devs/third-party-docs/Supra/use-supras-price-feed-oracle.mdx +++ b/arbitrum-docs/for-devs/oracles/supra/use-supras-price-feed-oracle.mdx @@ -1,9 +1,10 @@ --- -title: "How to use Supra's price feed oracle" -description: "Learn how to use Supra's price feed oracle" +id: 'supras-price-feed' +title: 'Supra, price feed oracle' +description: 'Learn how to use Supra price feed oracle' author: ksdumont sme: ksdumont -sidebar_label: "How to use Supra's price feed oracle" +sidebar_label: 'How to use Supra price feed oracle' --- :::info Community member contribution diff --git a/arbitrum-docs/for-devs/third-party-docs/Supra/use-supras-vrf.mdx b/arbitrum-docs/for-devs/oracles/supra/use-supras-vrf.mdx similarity index 98% rename from arbitrum-docs/for-devs/third-party-docs/Supra/use-supras-vrf.mdx rename to arbitrum-docs/for-devs/oracles/supra/use-supras-vrf.mdx index d6837c165..b762426e0 100644 --- a/arbitrum-docs/for-devs/third-party-docs/Supra/use-supras-vrf.mdx +++ b/arbitrum-docs/for-devs/oracles/supra/use-supras-vrf.mdx @@ -1,9 +1,10 @@ --- -title: "How to use Supra's VRF" -description: "Learn how to use Supra's VRF" +id: 'supras-vrf' +title: 'Supra, VRF' +description: 'Learn how to use Supra VRF' author: ksdumont sme: ksdumont -sidebar_label: "How to use Supra's VRF" +sidebar_label: 'How to use Supra VRF' --- :::info Community member contribution @@ -16,8 +17,6 @@ Supra’s VRF can provide the exact properties required for a random number gene Integrating with Supras' VRF is quick and easy. Supra currently supports several Solidity/EVM-based networks, like Arbitrum, and non-EVM networks like Sui, Aptos. -To see all of the networks Supra is on, please visit [Supras' Networks](https://supraoracles.com/docs/vrf/networks)! - To get started, you will want to visit [Supras' docs site](https://supraoracles.com/docs/vrf) and review the documentation or continue to follow this guide for a quick start. Latest version of Supra VRF requires a customer controlled wallet address to act as the main reference for access permissions and call back(response) transaction gas fee payments. Therefore, users planning to consume Supra VRF should get in touch with our team to get your wallet registered with Supra. diff --git a/arbitrum-docs/for-devs/oracles/trellor/trellor.mdx b/arbitrum-docs/for-devs/oracles/trellor/trellor.mdx new file mode 100644 index 000000000..1d12fbc5b --- /dev/null +++ b/arbitrum-docs/for-devs/oracles/trellor/trellor.mdx @@ -0,0 +1,54 @@ +--- +id: 'trellor' +title: 'Trellor' +description: Learn how to integrate oracles into your Arbitrum dapp +user_story: As a developer, I want to understand how to use oracles in Arbitrum to get off-chain data on-chain. +sidebar_label: 'Trellor' +content_type: how-to +--- + +[Tellor](https://tellor.io/) is a decentralized oracle network that incentivizes an open, permissionless network of data reporting and validation, ensuring that any verifiable data can be brought on-chain. It supports basic spot prices, sophisticated pricing specs (TWAP/VWAP), Snapshot Vote Results, and custom data needs. + +### Querying the price of $ETH through Tellor + +Here’s an example of how to use a Tellor data feed to query the current price of $ETH on-chain. The way it works is that a query is crafted asking for the price of one currency against another and sent to the oracle contract. If the information for that query is available, it will be returned. Oracle contracts can be found on the [Contracts Reference](https://docs.tellor.io/tellor/the-basics/contracts-reference) page. + +Tellor provides an npm package with the contracts needed to query the contract. We first install that package in our project: + +```bash +npm install usingtellor +``` + +Our function will just wrap the call to the Oracle contract with the query we are interested in. In this case, we want to obtain the “SpotPrice” of “eth” against “usd”. We will request this information to the Arbitrum oracle contract `0xD9157453E2668B2fc45b7A803D3FEF3642430cC0`. We’ll use this example contract: + +```solidity +contract ARBPriceConsumer is UsingTellor { + /** + * Network: Arbitrum One + * Aggregator: ARB/USD + * Address: 0xD9157453E2668B2fc45b7A803D3FEF3642430cC0 + */ + constructor(address payable _tellorAddress) UsingTellor(_tellorAddress) + {} + + /** + * Returns the latest price. + */ + function getLatestPrice() public view returns (uint256) { + bytes memory _queryData = abi.encode("SpotPrice", abi.encode("eth", "usd")); + bytes32 _queryId = keccak256(_queryData); + + (bytes memory _value, uint256 _timestampRetrieved) = + getDataBefore(_queryId, block.timestamp - 20 minutes); + if (_timestampRetrieved == 0) return 0; + require(block.timestamp - _timestampRetrieved < 24 hours); + return abi.decode(_value, (uint256)); + } +} +``` + +You can adapt this contract to your needs. Just remember to use the ticker of the assets you want to request the price for and to **deploy your contract to the appropriate network, with the address of the Oracle contract in that network**. Remember, we have a [Quickstart](/build-decentralized-apps/01-quickstart-solidity-hardhat.mdx) available that goes through the process of compiling and deploying a contract. + +### See also + +- [Tellor’s documentation](https://docs.tellor.io/) demonstrates how to query price feeds and other data feeds. diff --git a/arbitrum-docs/for-devs/partials/_know-more-tools-box-partial.md b/arbitrum-docs/for-devs/partials/_know-more-tools-box-partial.mdx similarity index 100% rename from arbitrum-docs/for-devs/partials/_know-more-tools-box-partial.md rename to arbitrum-docs/for-devs/partials/_know-more-tools-box-partial.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/Circle/usdc-quickstart-guide/usdc.md b/arbitrum-docs/for-devs/third-party-docs/Circle/usdc-quickstart-guide.mdx similarity index 97% rename from arbitrum-docs/for-devs/third-party-docs/Circle/usdc-quickstart-guide/usdc.md rename to arbitrum-docs/for-devs/third-party-docs/Circle/usdc-quickstart-guide.mdx index 3382ac295..964dcf5b3 100644 --- a/arbitrum-docs/for-devs/third-party-docs/Circle/usdc-quickstart-guide/usdc.md +++ b/arbitrum-docs/for-devs/third-party-docs/Circle/usdc-quickstart-guide.mdx @@ -1,4 +1,9 @@ -## QuickStart +--- +title: 'USDC quick start guide' +description: 'Learn how to integrate USDC into your application using the Arbitrum network.' +author: circle-cooper +sme: circle-cooper +--- USDC provides the ability to transfer dollars over the Arbitrum network using a smart contract. The smart contract enables users to send, receive, and store dollars on-chain with a wallet. diff --git a/arbitrum-docs/for-devs/third-party-docs/Covalent/covalent.md b/arbitrum-docs/for-devs/third-party-docs/Covalent/covalent.mdx similarity index 100% rename from arbitrum-docs/for-devs/third-party-docs/Covalent/covalent.md rename to arbitrum-docs/for-devs/third-party-docs/Covalent/covalent.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/Crossmint/crossmint.md b/arbitrum-docs/for-devs/third-party-docs/Crossmint/crossmint.mdx similarity index 100% rename from arbitrum-docs/for-devs/third-party-docs/Crossmint/crossmint.md rename to arbitrum-docs/for-devs/third-party-docs/Crossmint/crossmint.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/Envio/envio.md b/arbitrum-docs/for-devs/third-party-docs/Envio/envio.mdx similarity index 100% rename from arbitrum-docs/for-devs/third-party-docs/Envio/envio.md rename to arbitrum-docs/for-devs/third-party-docs/Envio/envio.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/Flair/flair.md b/arbitrum-docs/for-devs/third-party-docs/Flair/flair.mdx similarity index 100% rename from arbitrum-docs/for-devs/third-party-docs/Flair/flair.md rename to arbitrum-docs/for-devs/third-party-docs/Flair/flair.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/Gelato/gelato-vrf.md b/arbitrum-docs/for-devs/third-party-docs/Gelato/gelato-vrf.mdx similarity index 100% rename from arbitrum-docs/for-devs/third-party-docs/Gelato/gelato-vrf.md rename to arbitrum-docs/for-devs/third-party-docs/Gelato/gelato-vrf.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/Moralis/moralis.md b/arbitrum-docs/for-devs/third-party-docs/Moralis/moralis.mdx similarity index 100% rename from arbitrum-docs/for-devs/third-party-docs/Moralis/moralis.md rename to arbitrum-docs/for-devs/third-party-docs/Moralis/moralis.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/OKX/okx.mdx b/arbitrum-docs/for-devs/third-party-docs/OKX/okx.mdx new file mode 100644 index 000000000..00c341868 --- /dev/null +++ b/arbitrum-docs/for-devs/third-party-docs/OKX/okx.mdx @@ -0,0 +1,41 @@ +--- +title: 'OKX - Crypto exchange, app, and wallet' +description: 'Learn how to use OKX.' +author: pete-vielhaber +sme: midroni +sidebar_label: 'OKX' +--- + +[OKX](https://www.okx.com/) is an innovative and reliable cryptocurrency exchange with advanced financial services. OKX relies on blockchain technology to provide everything you need for wise trading and investment. With OKX, you can trade with confidence, knowing that your assets are in safe hands. + +Users can enjoy hundreds of tokens and trading pairs. With OKX, you can join one of the leading crypto exchanges by trading volume. OKX serves millions of users in over 100 countries, and it’s not just about trading. OKX provides a comprehensive suite of services including spot, margin, expiry, options, perpetual futures trading, DeFi, lending, and mining. + +## Wallet API + +The OKX [wallet API](https://www.okx.com/web3/build/docs/waas/walletapi-introduction) offers a flexible, non-custodial wallet technology solution to build on-chain services and applications. + +- Web3 multi-chain support +- DApp embedded wallet +- Multi-chain Web3 apps +- Exchange wallet + +## DEX API + +The [DEX API](https://www.okx.com/web3/build/docs/waas/dex-introduction) is a comprehensive trading aggregator for multi-chain and cross-chain transactions. You can use it to create Web3 trading services and applications for various scenarios, including wallets, DApp projects, and DeFi projects. + +- Multi-chain support +- Aggregation over multiple cross-chain bridges and DEXs +- Stability and high availability + +## NFT marketplace API + +The [OKX NFT Marketplace](https://www.okx.com/web3/build/docs/waas/marketplace-introduction) is an extensive decentralized platform that supports multi-chain NFT creations and cross-platform transactions. It provides real-time on-chain data for both users and developers. + +- NFT aggregator +- Issuance and secondary marketplace + +## Defi API + +OKX Web3 DeFi is the only all-in-one DeFi investment solution available on the market. OKX’s multi-chain DeFi aggregator provides users with a comprehensive platform to discover and access various investment opportunities in DeFi, making it easy to find products that meet their needs. + +OKX Web3 DeFi connects to over 80 protocols, including Aave, Compound, Curve, Yearn, and Uniswap. OKX supports over 15 networks like Arbitrum, Ethereum, and Polygon. By integrating the [OKX Web3 DeFi Open API](https://www.okx.com/web3/build/docs/waas/defi-introduction) into your application, users can quickly and easily access all DeFi protocols and enjoy the benefits of DeFi investment. diff --git a/arbitrum-docs/for-devs/third-party-docs/Openfort/openfort.md b/arbitrum-docs/for-devs/third-party-docs/Openfort/openfort.mdx similarity index 100% rename from arbitrum-docs/for-devs/third-party-docs/Openfort/openfort.md rename to arbitrum-docs/for-devs/third-party-docs/Openfort/openfort.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/PARSIQ/parsiq.md b/arbitrum-docs/for-devs/third-party-docs/PARSIQ/parsiq.mdx similarity index 100% rename from arbitrum-docs/for-devs/third-party-docs/PARSIQ/parsiq.md rename to arbitrum-docs/for-devs/third-party-docs/PARSIQ/parsiq.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/Particle/particle.md b/arbitrum-docs/for-devs/third-party-docs/Particle/particle.mdx similarity index 100% rename from arbitrum-docs/for-devs/third-party-docs/Particle/particle.md rename to arbitrum-docs/for-devs/third-party-docs/Particle/particle.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/QuickNode/backfill-templates.md b/arbitrum-docs/for-devs/third-party-docs/QuickNode/backfill-templates.mdx similarity index 100% rename from arbitrum-docs/for-devs/third-party-docs/QuickNode/backfill-templates.md rename to arbitrum-docs/for-devs/third-party-docs/QuickNode/backfill-templates.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/SubQuery/subquery.md b/arbitrum-docs/for-devs/third-party-docs/SubQuery/subquery.md deleted file mode 100644 index 6a7cd9dfb..000000000 --- a/arbitrum-docs/for-devs/third-party-docs/SubQuery/subquery.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: 'Indexing Arbitrum data with SubQuery' -description: 'Fast, flexible, universal, open source and decentralised APIs for Arbitrum' -author: subquery-team -sidebar_label: 'SubQuery Indexer' ---- - -SubQuery is a leading blockchain data indexer that provides developers with fast, flexible, universal, open source and decentralised APIs for web3 projects. SubQuery SDK allows developers to get rich indexed data and build intuitive and immersive decentralised applications in a faster and more efficient way. SubQuery supports 100+ ecosystems including Arbitrum, Ethereum, Polkadot, Algorand, NEAR, and Avalanche. - -Another one of SubQuery's competitive advantages is the ability to aggregate data not only within a chain but across multiple blockchains all within a single project. This allows the creation of feature-rich dashboard analytics and multi-chain block scanners. - -Other advantages include superior performance with multiple RPC endpoint configurations, multi-worker capabilities and a configurable caching architecture. To find out more, visit our [documentation](https://academy.subquery/). - -## Useful resources - -- SubQuery docs: [SubQuery Academy (Documentation)](https://academy.subquery.network/) -- Intro quick start guide: [1. Create a New Project](https://academy.subquery.network/quickstart/quickstart.html) -- [Arbitrum Quick Start Guide](https://academy.subquery.network/quickstart/quickstart_chains/arbitrum.html) -- [Arbitrum's starter projects directory](https://github.com/subquery/ethereum-subql-starter/tree/main/Arbitrum) - -For technical questions and support reach out to us `start@subquery.network` - -## Running and hosting your Arbitrum SubQuery APIs - -SubQuery is open-source, meaning you have the freedom to run it in the following three ways: - -- Locally on your own computer (or a cloud provider of your choosing), [view the instructions on how to run SubQuery Locally](https://academy.subquery.network/run_publish/run.html). - -- You can publish it to SubQuery's enterprise-level [Managed Service](https://managedservice.subquery.network/), where we'll host your SubQuery project in production ready services for mission critical data with zero-downtime blue/green deployments. There even is a generous free tier. [Find out how](https://academy.subquery.network/run_publish/publish.html). - -- You can publish it to the decentralised [SubQuery Network](https://subquery.network/network), the most open, performant, reliable, and scalable data service for dApp developers. The SubQuery Network indexes and services data to the global community in an incentivised and verifiable way and supports Arbitrum from launch. diff --git a/arbitrum-docs/for-devs/third-party-docs/TheGraph/thegraph.md b/arbitrum-docs/for-devs/third-party-docs/TheGraph/thegraph.mdx similarity index 100% rename from arbitrum-docs/for-devs/third-party-docs/TheGraph/thegraph.md rename to arbitrum-docs/for-devs/third-party-docs/TheGraph/thegraph.mdx diff --git a/arbitrum-docs/for-devs/third-party-docs/Venly/venly.md b/arbitrum-docs/for-devs/third-party-docs/Venly/venly.md new file mode 100644 index 000000000..66fc4e811 --- /dev/null +++ b/arbitrum-docs/for-devs/third-party-docs/Venly/venly.md @@ -0,0 +1,224 @@ +--- +title: 'Venly Tools <> Arbitrum' +description: 'Venly Tools stand on three pillars: Digital Wallets, Digital Assets, and Payments' +author: Abdullah Baig +sme: abdullahvenly +sidebar_label: 'Venly' +--- + +## [Venly](https://venly.io/) + +Venly stands out as a cutting-edge developer platform, designed to streamline digital asset management and foster the creation of innovative blockchain solutions. Known for its exceptional performance and strong security features, Venly’s non-custodian model ensures you retain complete ownership and control of your assets, distinguishing it from other platforms. + +At Venly, the core principles guide their commitment to you: + +- **Security First**: Venly prioritizes the highest level of security for your assets and operations. +- **Developer-Centric**: Venly's intuitive tools and resources are designed to empower developers to achieve success. +- **Optimal Performance**: Venly guarantees consistent high performance with a focus on efficiency and reliability. +- **Innovation**: They are dedicated to providing cutting-edge solutions, staying at the forefront of technology. + +The [Venly](https://venly.io/) platform is anchored by three main pillars: **Digital Wallets, Digital Assets, and Payments**, each seamlessly integrated to enhance your blockchain experience. + +``` +Venly Tools +│ +├── Digital Wallets: Secure & scalable SSS-based wallets. +│ +├── Digital Assets: API solutions for digital assets. +│ +├── Payments: Customizable payment forms for fiat. +│ +├── Gaming SDK: +│ │ +│ ├── Unity: C# SDK +│ │ +│ └── Unreal Engine: C++ SDK +│ +└── Integrations: + │ + ├── Zapier: no-code NFT minting with zaps. + │ + ├── Shopify: Selling NFTs made easy. + │ + └── SiteManager: Create mint pages in minutes, all no-code. +``` + +### [Digital Wallets](https://docs.venly.io/docs/wallet-api-overview) + +Secure and scalable SSS-based wallets with robust key management custody digital assets. The Venly security protocol redefines private key security, never gathering a private key as one whole, eliminating risk. Venly customers use their wallets for a range of operations, such as treasury, trading, cold storage, royalties, NFTs, smart contracts, user wallets, and other digital assets. + +### [Digital Assets](https://docs.venly.io/docs/nft-api-overview) + +Robust tokenization is based on industry standards and is secured by several code and security audits. The Venly platform facilitates no-code and API solutions to manage, transfer, and gather information on different token asset classes, such as ERC20, ERC721, and ERC1155, which customers use in industries such as Finance, E-commerce, and Gaming. + +### [Payments](https://docs.venly.io/docs/pay-api-overview) + +With PAY, the Venly platform offers a low-code payment integration that creates a customizable form for collecting payments. You can embed Pay directly on your website or redirect customers to a hosted payment page. It offers a wide range of payment methods, from credit cards to PayPal, Apple Pay, Google Pay, instant bank transfers, and more, enabling customers to choose their preferred option. + +## Product Specific Documentation + +| Category | Product | Documentation | +| :-------------- | :------------------------------ | :----------------------------------------------------------------------------- | +| Digital Wallets | Widget | [API Reference](https://venly.readme.io/docs/product-overview) | +| Digital Wallets | Wallet API | [API Reference](https://venly.readme.io/reference/viewwallet) | +| Digital Assets | NFT API | [API Reference](https://docs.venly.io/reference/getcontracts-1) | +| Digital Assets | Shopify NFT Minting Application | [App Store](https://apps.shopify.com/partners/arkane-network1) | +| Digital Assets | Zapier Integration | [Documentation](https://docs.venly.io/docs/zapier-integration) | +| Digital Assets | SiteManager | [Documentation](https://docs.venly.io/docs/sitemanager) | +| Payments | Venly PAY | [API Reference](https://docs.venly.io/docs/pay-api-overview) | +| Gaming SDK | Unity | [Documentation](https://docs.venly.io/docs/getting-started-with-unity) | +| Gaming SDK | Unreal Engine | [Documentation](https://docs.venly.io/docs/getting-started-with-unreal-engine) | + +# [Venly](https://venly.io/) - Arbitrum + +Venly supports the Arbitrum chain on its Wallet API which allows you to create wallets on the Arbitrum chain. You can send and receive funds to/from Arbitrum wallets directly through the Wallet API, enabling seamless integration with applications using the Arbitrum blockchain. + +# Wallet API + +The Wallet API allows developers to interact with blockchain networks and offer wallet functionality to their users without having to build everything from scratch. This can include features like account creation, transaction management, balance inquiries, and more. + +- Welcome your users with custom wallet branding. You can customize the user interface to your requirements. +- You are completely in charge of the wallet user experience to optimize user conversion. Get total freedom with regard to UX and asset management with the Venly Wallet API. +- You and your users have complete control over digital assets without any third-party interference. Securely manage wallets with complete autonomy and privacy. +- In the event of loss of login credentials, you and your users can recover access to wallets with a security code or biometric verification. + +## Key features + +| Features | Description | +| :-------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Wallet management | Developers can use the API to create, manage, and secure wallets for their users. | +| Transaction services | The API can enable the initiation and monitoring of blockchain transactions. | +| Token support | It may allow the handling of various tokens and assets on supported blockchain networks. | +| Blockchain interactions | Developers can integrate functionalities like reading data from the blockchain or writing data to it, along with creating and interacting with smart contracts. | +| Security features | The API might offer features to enhance the security of user funds and transactions. | +| User experience enhancement | It can contribute to a smoother and more user-friendly interaction with blockchain applications. | +| Multi-blockchain support | Venly supports multiple blockchain networks, allowing developers to offer wallets for different cryptocurrencies. | + +## Creating an Arbitrum wallet + +### Prerequisites + +1. You need a Venly business account. If you don't have one, click to register [Developer Portal](https://portal.venly.io), or follow the [Getting Started with Venly](https://venly.readme.io/docs/getting-started) guide. + +2. You need your client ID and client secret which can be obtained from the [Portal](https://portal.venly.io/). + +3. You need a bearer token to authenticate API calls. Click [here](https://docs.venly.io/docs/authentication) to read how to authenticate. + +### Request Endpoint: [reference](https://docs.venly.io/reference/createwallet) + +```https +POST /api/wallets +``` + +#### Header params + +| Parameter | Param type | Value | Description | +| :--------------- | :--------- | :--------- | :-------------------------------------------------------------------------------------------- | +| `Signing-Method` | Header | `id:value` | `id`: This is the ID of the signing method. `value`: This is the value of the signing method. | + +#### Body params + +| Parameter | Param type | Description | Data type | Mandatory | +| :----------- | :--------- | :----------------------------------------------------- | :-------- | :-------- | +| `secretType` | Body | The blockchain on which to create the wallet | String | ✅ | +| `userId` | Body | The ID of the user who you want to link this wallet to | String | ❌ | + +### Request body + +```json +{ + "secretType": "ARBITRUM", + "userId": "9cf9228e-1f2b-4940-9508-4335064cbc76" +} +``` + +### Response body + +> Wallet created! The wallet has been created and linked to the specified user (`userId`). + +```json +{ + "success": true, + "result": { + "id": "590f7276-2886-475c-a2d6-a28421f8f367", + "address": "0xADc25e8A385213Fd820bc17Aa799076688f9fBd5", + "walletType": "API_WALLET", + "secretType": "ARBITRUM", + "createdAt": "2024-06-05T11:19:12.038340492", + "archived": false, + "description": "Elegant Moose", + "primary": false, + "hasCustomPin": false, + "userId": "9cf9228e-1f2b-4940-9508-4335064cbc76", + "custodial": false, + "balance": { + "available": true, + "secretType": "ARBITRUM", + "balance": 0, + "gasBalance": 0, + "symbol": "ETH", + "gasSymbol": "ETH", + "rawBalance": "0", + "rawGasBalance": "0", + "decimals": 18 + } + } +} +``` + +## Transferring Arbitrum Tokens + +### Request Endpoint: [reference](https://docs.venly.io/reference/executetransaction_1) + +```http +POST /api/transactions/execute +``` + +#### Header params + +| Parameter | Param type | Value | Description | +| :--------------- | :--------- | :--------- | :-------------------------------------------------------------------------------------------- | +| `Signing-Method` | Header | `id:value` | `id`: This is the ID of the signing method. `value`: This is the value of the signing method. | + +#### Body params + +| Parameter | Param Type | Description | Data Type | Mandatory | +| :------------------------------ | :--------- | :----------------------------------------------------------------- | :-------- | :-------- | +| `transactionRequest` | Body | This object includes the transaction information | Object | ✅ | +| transactionRequest.`type` | Body | This will be **TRANSFER** | String | ✅ | +| transactionRequest.`walletId` | Body | The `id` of the wallet that will initiate the tx | String | ✅ | +| transactionRequest.`to` | Body | Destination Address (can be a blockchain address or email address) | String | ✅ | +| transactionRequest.`secretType` | Body | On which blockchain the tx will be executed | String | ✅ | +| transactionRequest.`value` | Body | The amount you want to transfer | Integer | ✅ | + +### Request Body: + +```json +{ + "transactionRequest": { + "type": "TRANSFER", + "walletId": "590f7276-2886-475c-a2d6-a28421f8f367", + "to": "0x1588aCD59c9baF27C1b777eAa71A67d6b6024077", + "value": "0.0005", + "secretType": "ARBITRUM" + } +} +``` + +### Response Body: + +> The coins were successfully transferred! + +```json +{ + "success": true, + "result": { + "id": "34d51bb3-c963-486d-856e-1e3f12638e3d", + "transactionHash": "0x804d14bcda10628e61e7ae9085ecad63eafea09d3fdb3cb4ec8cb8dc312dc5b7" + } +} +``` + +### Next Steps + +> Ready to try it out? Click to read the [getting started guide for Wallet API.](https://docs.venly.io/docs/wallet-api-getting-started) diff --git a/arbitrum-docs/for-devs/third-party-docs/Webacy/webacy.md b/arbitrum-docs/for-devs/third-party-docs/Webacy/webacy.md new file mode 100644 index 000000000..e363b45f6 --- /dev/null +++ b/arbitrum-docs/for-devs/third-party-docs/Webacy/webacy.md @@ -0,0 +1,129 @@ +--- +title: 'What is the Webacy Risk Data Network?' +description: 'Learn about the Webacy Risk Data Network, and how you can use it in your products.' +author: cvince +sme: cvince +sidebar_label: 'Webacy' +third_party_content_owner: cvince +--- + +[Webacy](https://webacy.com/) is a risk data network that helps wallets & applications protect their users against scams, hacks, and mistakes across the blockchain. + +Wallets, protocols, & applications use Webacy throughout their user experience: + +### Address trust and safety + +- Assess the safety of interacting with a given address (any address: EOA, smart contract, token, etc.). Screen for blocklists, sanctioned addresses, malicious behavior, and other potential flags +- Analyze smart contract code in real-time +- Filter spam and sybil addresses + +### Connected wallets + +- Block sanctioned addresses and wallets involved in malicious behavior +- Educate users with a Wallet Safety Score +- Delight users by enabling additional features or providing additional value +- Display open approvals and the risks associated + +### Before a transaction + +- Block harmful dApps and links +- Review address trust and safety prior to signature +- Protect users from interacting with malicious smart contracts + +### Monitoring and Notifications + +- Monitor all on-chain activity associated with your protocol or smart contracts +- Enable wallet monitoring and flag for risky transactions +- Proactively notify users (or be notified) of any potentially risk activity involved with a given address + +## Get started with Webacy + +Start building in minutes: + +- Reach out to info\@webacy.com for an API key +- Check out the[ Quick Start Integration Guide](https://docs.webacy.com/api-embedded-safety/quick-start-integration-guide) + +## APIs + +[Webacy’s APIs](https://www.webacy.com/safetyscore) are REST-based APIs that expose your platform to Webacy's Risk Engine and Wallet Watch Notifications Platform. + +With over 15+ data providers, along with their data analytics and algorithms, Webacy has the broadest risk coverage across the blockchain ecosystem. From compliance and regulatory data to social engineering scams and crowdsourced reports, they process millions of monthly signals, updating their models with the latest and most up-to-date information. + +For detailed technical documentation and to begin testing the APIs directly, visit their [technical documentation](https://webacy.readme.io/reference/webacy-api-overview-pre-release). +Available APIs and corresponding use cases include: + +### Threat risks API + +This API indicates if a given address is a risk or a threat to others. +It returns risk data associated with the supplied address. It flags if the address appears in any sanctioned databases, has been historically flagged as malicious, is associated with a scam smart contract, and so on. It also includes filtering for spam/sybil signals. + +Some common use cases for this endpoint include: + +- Filtering addresses for spam +- Blocking high-risk addresses from utilizing your service +- Presenting high-risk addresses to others as potentially risky to interact with +- Protecting your platform by restricting high-risk addresses + +### Approval risks API + +This API returns a list of approvals for a given address and the associated risk of the spender for that approval. Approvals are commonplace in crypto - now you know which ones put you at risk. Check out your open approvals [here](https://dapp.webacy.com/?mode=approvals). + +If you're a wallet interested in native revoke and approval risk scoring, [reach out to Webacy](https://docs.webacy.com/other/contact-us). + +### Transaction risks API + +This API returns risk data for a given transaction. Pass in any transaction hash, and the API will return a risk score result that incorporates counterparty EOA risk profiles, address risk, involved asset smart contract risk, and more. + +Some common use cases for this endpoint include: + +- Understanding the historical behavior of an address +- Providing data to give recommendations about on-chain activity +- Gaining insight into a particular transaction or action +- Flagging previously unknown activity that was potentially at risk + +### Exposure risk API + +The original Webacy Safety Score, this API returns a 'risk profile' or 'exposure risk' of a given address. + +This indicates the exposure the address has to risky activity through historical transactions, behavior, and owned assets. This endpoint **does not** assess whether the supplied address is a risk to others (Threat Risk). Instead, it assesses whether the supplied address is **at risk** from others. + +Some common use cases for this endpoint include: + +- Gaining a holistic understanding of a client or personal wallet +- Enabling recommendations and analysis on past behavior +- Assessing common traits of a user base +- Determining types of users to better serve them +- Triggering warnings to internal teams or external users based on changes in risk profile based on ongoing activity +- Understanding the behavioral activity of a user base + +Check out your risk exposure[ here](https://dapp.webacy.com/risk-score). + +### Contract risk API + +This API returns a contract risk analysis for a given contract address. + +The on-demand analysis leverages multiple techniques, such as fuzzing, static analysis, and dynamic analysis, for real-time smart contract scanning. + +Some common use cases for this endpoint include: + +- Scanning contracts before listing them on your site +- Verifying that you are not promoting malicious contracts +- Checking a contract before interacting with it +- Reviewing code as you build +- Assessing your contracts before submitting them for a formal audit process + +### URL risk + +Given a URL, this endpoint analyzes its safety. It helps you determine if a given link is a phishing scam, sending you to a dangerous place, or is otherwise malicious. + +Some common use cases for this endpoint include: + +- Assessing the safety of a dapp/website +- Warning your end-users from interacting with a potentially malicious website +- Blocking websites + +### Wallet watch API + +These APIs enable you to register users to Webacy's real-time notification infrastructure. + +If you're interested in setting up your own private instance with custom messaging and triggers, [contact us](https://docs.webacy.com/other/contact-us). diff --git a/arbitrum-docs/for-devs/third-party-docs/contribute.mdx b/arbitrum-docs/for-devs/third-party-docs/contribute.mdx index 6d5839f3c..1996c8c78 100644 --- a/arbitrum-docs/for-devs/third-party-docs/contribute.mdx +++ b/arbitrum-docs/for-devs/third-party-docs/contribute.mdx @@ -1,13 +1,9 @@ --- title: 'Contribute third-party docs' -description: "Learn how to contribute to Arbitrum's documentation" +description: "Discover how to contribute third-party resources to Arbitrum's documentation. Share your expertise and help expand the largest Ethereum Layer 2 developer ecosystem." sidebar_position: 0 --- -import PublicPreviewBannerPartial from '../../partials/_public-preview-banner-partial.mdx'; - - - **Third-party docs** are documents that help readers of Arbitrum docs use other products, services, and protocols (like the ones listed in the [Arbitrum portal](https://portal.arbitrum.io/)) with Arbitrum products. These documents are usually authored by partner teams, but can be authored by anyone. They follow the same general process that [core docs](/for-devs/contribute#add-a-new-core-document) follow, in addition to the following guidelines: diff --git a/arbitrum-docs/for-devs/troubleshooting-building.md b/arbitrum-docs/for-devs/troubleshooting-building.mdx similarity index 100% rename from arbitrum-docs/for-devs/troubleshooting-building.md rename to arbitrum-docs/for-devs/troubleshooting-building.mdx diff --git a/arbitrum-docs/for-users/contribute.md b/arbitrum-docs/for-users/contribute.mdx similarity index 100% rename from arbitrum-docs/for-users/contribute.md rename to arbitrum-docs/for-users/contribute.mdx diff --git a/arbitrum-docs/hosted-audit-reports/2023_08_02_trail_of_bits_security_audit_challenge_protocol_v2.pdf b/arbitrum-docs/hosted-audit-reports/2023_08_02_trail_of_bits_security_audit_challenge_protocol_v2.pdf new file mode 100644 index 000000000..30a4f6157 Binary files /dev/null and b/arbitrum-docs/hosted-audit-reports/2023_08_02_trail_of_bits_security_audit_challenge_protocol_v2.pdf differ diff --git a/arbitrum-docs/hosted-audit-reports/2024_08_05_trail_of_bits_security_audit_bold_and_dac_rewards_updates.pdf b/arbitrum-docs/hosted-audit-reports/2024_08_05_trail_of_bits_security_audit_bold_and_dac_rewards_updates.pdf new file mode 100644 index 000000000..229adf860 Binary files /dev/null and b/arbitrum-docs/hosted-audit-reports/2024_08_05_trail_of_bits_security_audit_bold_and_dac_rewards_updates.pdf differ diff --git a/arbitrum-docs/hosted-audit-reports/2024_10_07_trail_of_bits_security_audit_bold_optimized_history_commitments.pdf b/arbitrum-docs/hosted-audit-reports/2024_10_07_trail_of_bits_security_audit_bold_optimized_history_commitments.pdf new file mode 100644 index 000000000..f7253df16 Binary files /dev/null and b/arbitrum-docs/hosted-audit-reports/2024_10_07_trail_of_bits_security_audit_bold_optimized_history_commitments.pdf differ diff --git a/arbitrum-docs/hosted-audit-reports/2024_10_23_trail_of_bits_security_audit_arbos32_emergency_fixes.pdf b/arbitrum-docs/hosted-audit-reports/2024_10_23_trail_of_bits_security_audit_arbos32_emergency_fixes.pdf new file mode 100644 index 000000000..358b77c5b Binary files /dev/null and b/arbitrum-docs/hosted-audit-reports/2024_10_23_trail_of_bits_security_audit_arbos32_emergency_fixes.pdf differ diff --git a/arbitrum-docs/hosted-audit-reports/2024_10_30_trail_of_bits_security_audit_Nitro_Contracts_with_BoLD.pdf b/arbitrum-docs/hosted-audit-reports/2024_10_30_trail_of_bits_security_audit_Nitro_Contracts_with_BoLD.pdf new file mode 100644 index 000000000..5effdd721 Binary files /dev/null and b/arbitrum-docs/hosted-audit-reports/2024_10_30_trail_of_bits_security_audit_Nitro_Contracts_with_BoLD.pdf differ diff --git a/arbitrum-docs/hosted-audit-reports/2024_12_26_trail_of_bits_boldfixes_securityreview.pdf b/arbitrum-docs/hosted-audit-reports/2024_12_26_trail_of_bits_boldfixes_securityreview.pdf new file mode 100644 index 000000000..0f9568c1e Binary files /dev/null and b/arbitrum-docs/hosted-audit-reports/2024_12_26_trail_of_bits_boldfixes_securityreview.pdf differ diff --git a/arbitrum-docs/how-arbitrum-works/01-a-gentle-introduction.mdx b/arbitrum-docs/how-arbitrum-works/01-a-gentle-introduction.mdx new file mode 100644 index 000000000..e8ae0214d --- /dev/null +++ b/arbitrum-docs/how-arbitrum-works/01-a-gentle-introduction.mdx @@ -0,0 +1,74 @@ +--- +title: 'A gentle introduction' +description: 'Learn the fundamentals of Nitro, Arbitrum stack.' +author: dzgoldman +sme: dzgoldman +user_story: As a current or prospective Arbitrum user, I need learn more about Nitros design. +content_type: get-started +--- + +import ImageWithCaption from '@site/src/components/ImageCaptions/'; + +This document is a deep-dive explanation of Arbitrum Nitro’s design and the rationale for it. This isn’t API documentation, nor is it a guided tour of the code--look elsewhere for those. “Inside Arbitrum Nitro” is for people who want to understand Nitro's design. + +The body of this document will describe Arbitrum Rollup, the primary use case of the Nitro technology and the one used on the Arbitrum One chain. There is a variant use case, called [AnyTrust](/how-arbitrum-works/08-anytrust-protocol.mdx), which is used by the Arbitrum Nova chain. + +## Why use Arbitrum? Why use Nitro? + +Arbitrum is an L2 scaling solution for Ethereum, offering a unique combination of benefits: + +- Trustless security: security rooted in Ethereum, with any one + party able to ensure correct Layer 2 results +- Compatibility with Ethereum: able to run unmodified EVM contracts and unmodified Ethereum transactions +- Scalability: moving contracts’ computation and storage off of the main Ethereum chain, allowing much higher throughput +- Minimum cost: designed and engineered to minimize the L1 gas footprint of the system, minimizing per-Transaction cost. + +Some other Layer 2 systems provide some of these features, but to our knowledge no other system offers the same combination of features at the same cost. + +Nitro is a major upgrade to Arbitrum including: + +- **Advanced Calldata Compression,** which further drives down transaction costs on Arbitrum by reducing the amount of data posted to L1. +- **Separate Contexts For Common Execution and Fault Proving,** increasing the performance of L1 nodes, and thus offering lower fees. +- **Ethereum L1 Gas Compatibility,** bringing pricing and accounting for EVM operations perfectly in line with Ethereum. +- **Additional L1 Interoperability,** including tighter synchronization with L1 Block numbers, and full support for all Ethereum L1 precompiles. +- **Safe Retryables,** eliminating the failure mode where a Retryable Ticket fails to get created. +- **Geth Tracing,** for even broader debugging support. +- And many, many more changes. + +## The Big Picture + +At the most basic level, an Arbitrum chain works like this: + + + +Users and contracts put messages into the inbox. The chain reads the messages one at a time, and processes each one. This updates the state of the chain and produces some outputs. + +If you want an Arbitrum chain to process a transaction for you, you need to put that transaction into the chain’s inbox. Then the chain will see your transaction, execute it, and produce some outputs: a transaction receipt, and any withdrawals that your transaction initiated. + +Execution is deterministic -- which means that the chain’s behavior is uniquely determined by the contents of its inbox. Because of this, the result of your transaction is knowable as soon as your transaction has been put in the inbox. Any Arbitrum node will be able to tell you the result. (And you can run an Arbitrum node yourself if you want.) + +All of the technical detail in this document is connected to this diagram. To get from this diagram to a full description of Arbitrum, we’ll need to answer questions like these: + +- Who keeps track of the inbox, Chain state, and outputs? +- How does Arbitrum make sure that the chain state and outputs are correct? +- How can Ethereum users and contracts interact with Arbitrum? +- How does Arbitrum support Ethereum-compatible contracts and transactions? +- How are ETH and tokens transferred into and out of Arbitrum chains, and how are they managed while on the chain? +- How can I run my own Arbitrum node or Validator? + +## Nitro's Design: The Four Big Ideas + +The essence of Nitro, and its key innovations, lie in four big ideas. We'll list them here with a very quick summary of each, then we'll unpack them in more detail in later sections. + +**Big Idea: Sequencing, Followed by Deterministic Execution**: Nitro processes transactions with a two-phase strategy. First, the transactions are organized into a single ordered sequence, and Nitro commits to that sequence. Then the transactions are processed, in that sequence, by a deterministic State Transition Function. + +**Big Idea: Geth at the Core**: Nitro supports Ethereum's data structures, formats, and virtual machine by compiling in the core code of the popular go-ethereum ("Geth") Ethereum node software. Using Geth as a library in this way ensures a very high degree of compatibility with Ethereum. + +**Big Idea: Separate Execution from Proving**: Nitro takes the same source code and compiles it twice, once to native code for execution in a Nitro node, optimized for speed, and again to WASM for use in proving, optimized for portability and security. + +**Big Idea: Optimistic Rollup with Interactive Fraud Proofs**: Nitro settles transactions to the Layer 1 Ethereum chain using an optimistic rollup protocol, including the interactive fraud proofs pioneered by Arbitrum. + +Now that we have covered the foundational concepts, the big picture, and the four big ideas of Arbitrum Nitro, we will begin a journey following a transaction through the Arbitrum protocol. In the next section, the transaction lifecycle begins. diff --git a/arbitrum-docs/how-arbitrum-works/02-transaction-lifecycle.mdx b/arbitrum-docs/how-arbitrum-works/02-transaction-lifecycle.mdx new file mode 100644 index 000000000..bd2928e9a --- /dev/null +++ b/arbitrum-docs/how-arbitrum-works/02-transaction-lifecycle.mdx @@ -0,0 +1,62 @@ +--- +title: Sequencing, Followed by Deterministic Execution +description: 'Learn the fundamentals of the Arbitrum Transaction Lifecycle, sequencing, and deterministic execution.' +author: pete-vielhaber +sme: gmehta2 +user_story: As a current or prospective Arbitrum user, I need to learn more about the transaction lifecycle. +content_type: get-started +--- + +This section explores the various methods users can employ to submit transactions for inclusion on the Arbitrum chain. We discuss the different pathways available—sending transactions to the Sequencer or bypassing it by submitting transactions through the Delayed Inbox contract on the Parent chain. By outlining these options, we aim to clarify how users can interact with the network, detail the processes involved in each method, and identify the modules responsible for handling these transactions. This overview will enhance your understanding of the initial steps in Arbitrum ecosystem's Transaction lifecycle and prepare you for a detailed exploration of transaction inclusion mechanisms in the subsequent sections. + +The first subsection, [Submitting Transactions to the Sequencer](#submitting-transactions-to-the-sequencer), presents four different methods users can utilize to send their transactions to the sequencer: via Public RPC, Third-Party RPC, Arbitrum Nodes, and the Sequencer Endpoint. Transactions sent through the first three pathways will route through our Load Balancer before reaching the sequencer. In contrast, the Sequencer Endpoint allows transactions to bypass the Load Balancer and be sent directly to the sequencer. + +The second subsection, [Bypassing the Sequencer](#bypassing-the-sequencer), describes an alternative method where users can include their transactions on the Arbitrum chain without relying on the sequencer. By sending transactions directly to the delayed inbox contract on the parent chain (Layer 1), users gain additional flexibility, ensuring that their transactions can be processed even if the sequencer is unavailable or if they prefer not to use it. + +This diagram illustrates the various pathways for submitting transactions to the Arbitrum chain. It highlights the options for sending transactions through the sequencer or bypassing it and using the delayed inbox contract on the parent chain. + +## Submitting transactions to the Sequencer + +This section outlines the different methods for users to submit transactions to the sequencer on the Arbitrum chain. There are four primary ways to do this: Public RPC, Third-Party RPCs, Arbitrum Nodes, and the Sequencer Endpoint. We will explore these methods in detail, explaining when to choose one over the other and how to use each to effectively submit transactions to the Arbitrum sequencer. + +### 1. Public RPC + +Arbitrum provides public RPCs for its main chains: Arbitrum One, Arbitrum Nova, and Arbitrum Sepolia. Due to their rate-limited nature, these RPC endpoints are suitable for less resource-intensive operations. Public RPCs can be an accessible option for general use cases and light interactions with the network. + +For more details on the specific RPC endpoints for each chain, please see [this section](https://docs.arbitrum.io/build-decentralized-apps/reference/node-providers#arbitrum-public-rpc-endpoints) of the documentation. + +### 2. Third-Party RPC + +Users also have the option to interact with Arbitrum's public chains using third-party node providers. These providers are often the same popular ones used for Ethereum, making them reliable choices for resource-intensive operations. We recommend using these third-party providers when performance and scalability are critical. + +You can find a list of supported third-party providers [here](https://docs.arbitrum.io/build-decentralized-apps/reference/node-providers#third-party-rpc-providers). + +### 3. Arbitrum Nodes + +Another approach for sending transactions to the sequencer is through self-hosted Arbitrum nodes. Running a node gives you direct control over your transactions, which go to the sequencer via the Sequencer Feed. + +Please see the [Arbitrum Node](https://docs.arbitrum.io/run-arbitrum-node/overview) documentation to learn more about setting up and running a node. + +### 4. Sequencer Endpoint + +The Sequencer Endpoint is the most direct method for users looking to minimize delays in their transactions reaching the sequencer. Unlike standard RPC URLs, the Sequencer Endpoint supports only `eth_sendRawTransaction` and `eth_sendRawTransactionConditional` calls, bypassing the load balancer entirely. This endpoint makes it an optimal choice for users who require the quickest transaction processing time. + +The diagram below shows different ways to submit transactions to the sequencer: + +
+ ![submit-transaction-to-sequencer](../assets/submit-tx-to-sequencer.png) +
+ +## Bypassing the Sequencer + +This section delves into an alternative method for submitting transactions to the Arbitrum chain, bypassing the sequencer. This page focuses on how users can send their transactions directly to the delayed inbox contract on the parent chain rather than through the sequencer. This method offers two distinct paths a transaction can take, with each route interacting with the network differently to achieve transaction inclusion. This approach provides users with greater flexibility and ensures that transactions can still be processed if the sequencer is unavailable or if users choose not to depend on it. This section highlights these alternative submission mechanisms and underscores the robustness and decentralization features inherent in the Arbitrum network. + +In **Diagram 3**, we demonstrate how users can submit their transactions using the delayed inbox contract to bypass the sequencer. As illustrated in the diagram, there are two possible paths for transaction handling. When a transaction is submitted to the delayed inbox, the sequencer may automatically pick it up, include it as an ordered transaction, and send it to the sequencer feed. However, if the sequencer does not process the transaction within 24 hours, users have the reliable option to call the `forceInclude` function on the sequencer inbox contract. This action ensures that the sequencer to picks up the transaction and includes it in the ordered transaction list, providing users with a sense of security about their transactions. + +
![bypassing-the-sequencer](../assets/bypassing-the-sequencer.png)
+ +To send a transaction to the delayed inbox instead of submitting it to the sequencer, users can construct their transaction and then call the [`sendL2Message`](https://github.com/OffchainLabs/nitro-contracts/blob/fbbcef09c95f69decabaced3da683f987902f3e2/src/bridge/AbsInbox.sol#L150) function, passing the data of the serialized signed transaction as an argument. This function allows users to send a generic L2 message to the chain, suitable for any message that does not require L1 validation. + +If the sequencer is not back online within 24 hours or decides to censor the transaction, users can invoke the [`forceInclusion`](https://github.com/OffchainLabs/nitro-contracts/blob/fbbcef09c95f69decabaced3da683f987902f3e2/src/bridge/SequencerInbox.sol#L284) function on the SequencerInbox contract. This action ensures their transaction is included on the chain, bypassing the sequencer's role. + +Additionally, the Arbitrum SDK provides the [`InboxTools`](https://github.com/OffchainLabs/arbitrum-sdk/blob/792a7ee3ccf09842653bc49b771671706894cbb4/src/lib/inbox/inbox.ts#L64C14-L64C24) class, which simplifies the process of submitting transactions to the delayed inbox. Users can utilize the [`sendChildSignedTx`](https://github.com/OffchainLabs/arbitrum-sdk/blob/792a7ee3ccf09842653bc49b771671706894cbb4/src/lib/inbox/inbox.ts#L401C16-L401C33) method to send the transaction and the [`forceInclude`](https://github.com/OffchainLabs/arbitrum-sdk/blob/792a7ee3ccf09842653bc49b771671706894cbb4/src/lib/inbox/inbox.ts#L367) method to ensure its inclusion. The SDK also offers helper methods like [`signChildTx`](https://github.com/OffchainLabs/arbitrum-sdk/blob/792a7ee3ccf09842653bc49b771671706894cbb4/src/lib/inbox/inbox.ts#L429) to assist with signing the transaction during the creation of the serialized signed transaction hex string, streamlining the entire process. diff --git a/arbitrum-docs/how-arbitrum-works/03-sequencer.mdx b/arbitrum-docs/how-arbitrum-works/03-sequencer.mdx new file mode 100644 index 000000000..fb0aff31f --- /dev/null +++ b/arbitrum-docs/how-arbitrum-works/03-sequencer.mdx @@ -0,0 +1,263 @@ +--- +title: The Sequencer and Censorship Resistance +description: 'Learn the fundamentals of the Arbitrum Sequencer.' +author: pete-vielhaber +sme: gmehta2 +user_story: As a current or prospective Arbitrum user, I need to learn more about the Sequencer. +content_type: get-started +--- + +The Sequencer is a pivotal component of the Arbitrum network and is responsible for efficiently ordering and processing transactions. It plays a crucial role in providing users with fast Transaction confirmations while maintaining the security and integrity of the Blockchain. In Arbitrum, the Sequencer orders incoming transactions and manages the batching, compression, and posting of transaction data to Parent chain, optimizing costs and performance. + +
![sequencer-operations](../assets/sequencer-operations.png)
+ +In this section, we will explore the operation of the Sequencer in detail. The topics covered include: + +- [Sequencing and Broadcasting (Sequencer Feed)](#sequencing-and-broadcasting): An overview of the real-time transaction feed provided by the Sequencer, which allows nodes to receive instant updates on the transaction sequence. +- [Batch-Posting](#batch-posting): How the Sequencer groups transactions into batches, compresses them to reduce data size and sends them to the Sequencer Inbox Contract on the parent chain. This section also delves into the L1 pricing model and how it affects transaction costs. + - [Batching](#batching-and-compression) + - [Compression](#compression) + - [Submitting to the Sequencer Inbox Contract](#submitting-to-the-sequencer-inbox-contract) +- [Finality](#finality): Understanding how transaction finality is achieved in Arbitrum through both soft and hard finality mechanisms, ensuring that transactions are confirmed securely and reliably. (not as a sequencer task) + +By examining these aspects, you will understand the Sequencer's role within the Arbitrum ecosystem, including how it enhances transaction throughput, reduces latency, and maintains a fair and decentralized network. + +## Sequencing and Broadcasting + +The **Sequencer Feed** is a critical component of the Arbitrum network's Nitro architecture. It enables real-time dissemination of transaction data as they are accepted and ordered by the Sequencer. It allows users and nodes to receive immediate updates on transaction sequencing, facilitating rapid transaction confirmations and enhancing the network's overall responsiveness. + +### How the Sequencer Publishes the Sequence + +The Sequencer communicates the transaction sequence through two primary channels: + +1. **Real-Time Sequencer Feed**: A live broadcast that publishes transactions instantly as they are sequenced. Nodes and clients subscribed to this feed receive immediate notifications, allowing them to process transactions without delay. +2. **Batches Posted on the Parent Chain**: At regular intervals, the Sequencer aggregates transactions and posts them to the parent chain for finality. (Refer to the Batch-Posting section for detailed information on this process.) + +
![sequencer-feed](../assets/sequencer-feed.png)
+ +### Real-Time Sequencer Feed + +The real-time feed represents the Sequencer's commitment to process transactions in a specific order. By subscribing to this feed, nodes and clients can: + +- **Receive Immediate Notifications**: Obtain instant information about newly sequenced transactions and their ordering. +- **Process Transactions Promptly**: Utilize the sequenced transactions to update the state locally, enabling rapid application responses and user interactions. +- **Benefit from Soft Finality**: Gain provisional assurance about transaction acceptance and ordering before the parent chain reaches finality. + +This mechanism is particularly valuable for applications requiring low latency and high throughput, such as decentralized exchanges or real-time gaming platforms. + +### Soft Finality and Trust Model + +"Soft finality" refers to the preliminary Confirmation of transactions based on the Sequencer's real-time feed. Key aspects include: + +- **Dependence on Sequencer Integrity**: The feed's accuracy and reliability depend on the Sequencer operating honestly and without significant downtime. +- **Immediate User Feedback**: Users can act on transaction confirmations swiftly, improving the user experience. +- **Eventual Consistency with the Parent Chain**: While the real-time feed provides quick updates, ultimate security, and finality are established once transactions are posted to and finalized on the parent chain. (See the **Finality** section for an in-depth discussion.) + +Understanding this trust model is essential. While we expect the Sequencer to behave correctly, users and developers should know that soft finality depends on this assumption. In scenarios where absolute certainty is required, parties may wait for transactions to achieve finality on the parent chain. + +### Role of the Sequencer Feed in the Network + +The Sequencer Feed serves several vital functions within the Arbitrum ecosystem: + +- **State Synchronization**: Nodes use the feed to stay synchronized with the latest state of the network, ensuring consistency across the decentralized platform. +- **Application Development**: Developers can build applications that respond instantly to network events, enabling features like live updates, instant notifications, and real-time analytics. +- **Ecosystem Transparency**: The feed promotes transparency and trust within the community by providing visibility into transaction sequencing and network activity. + +### Considerations and Limitations + +While the Sequencer Feed offers significant advantages, consider the following: + +- **Reliance on Sequencer Availability**: The effectiveness of the real-time feed depends on the Sequencer's uptime and responsiveness. Network issues or Sequencer downtime can delay transaction visibility. +- **Provisional Nature of Soft Finality**: Until transactions reach finality on the parent chain, there is a small risk that the provisional ordering provided by the feed could change in exceptional circumstances. +- **Security Implications**: For high-stakes transactions where security is paramount (e.g., centralized exchange deposits and withdrawals), users may prefer to wait for parent chain confirmation despite the longer latency. + +Developers and users should design their applications and interactions with these factors in mind, choosing the appropriate balance between speed and certainty based on their requirements. + +### **Delayed Messages on the Sequencer Feed** + +As illustrated in the diagram, the Sequencer feed not only sends Child chain transactions posted directly to the Sequencer but also incorporates parent chain-submitted child chain transactions. These include L2 messages submitted on L1 and retryable transactions. The Sequencer agent monitors the finalized messages submitted to the parent chain's Delayed Inbox Contract. Once finalized, it processes them as incoming messages to the feed, ensuring they are added as ordered transactions. + +It is important to note that the Nitro node can be configured to add delayed inbox transactions immediately after their submission to the parent chain, even before finalization. However, this approach introduces a risk of child chain reorganization if the transaction fails to finalize on the parent chain. To mitigate this risk, on Arbitrum One and Nova, the Sequencer only includes these transactions in the feed once they are finalized on the Ethereum chain. + +You can also explore how the feed sends incoming messages via WebSocket and learn how to extract message data from the feed on this page: [Read Sequencer Feed](https://docs.arbitrum.io/run-arbitrum-node/sequencer/read-sequencer-feed). + +## Batch-Posting + +Batch-Posting is a fundamental process in the operation of the Sequencer within the Arbitrum network. It involves collecting multiple child chain transactions, organizing them into batches, compressing the data to reduce size, and sending these batches to the Sequencer Inbox Contract on parent chain. This mechanism is crucial for ensuring that transactions are securely recorded on the parent chain blockchain while optimizing for cost and performance. + +In this section, we will explore the Batch-Posting process in detail, covering the following topics: + +- **Batching**: How the Sequencer groups incoming transactions into batches for efficient processing and posting. +- **Compression**: The methods used to compress transaction data, minimizing the amount of data that needs to be posted on parent chain and thereby reducing costs. +- **Sending to Sequencer Inbox Contract**: The procedure for submitting compressed batches to the Sequencer Inbox Contract on parent chain, ensuring secure and reliable recording of transactions. + +Understanding Batch-Posting is essential for grasping how Arbitrum achieves scalability and cost-efficiency without compromising security. By delving into these subtopics, you'll gain insight into the Sequencer's role in optimizing transaction throughput and minimizing fees, as well as the innovative solutions implemented to address the challenges of Layer 1 data pricing. + +## Batching and compression + +The Sequencer in Arbitrum is critical in collecting and organizing child chain transactions before posting them to the parent chain. The batching process is designed to optimize for both cost efficiency and timely transaction inclusion. + +
![batching](../assets/batching.png)
+ +**Transaction Collection and Ordering:** + +- **Continuous Reception:** The Sequencer continuously receives transactions submitted by users. +- **Ordering:** Transactions are ordered based on the sequence in which they are received, maintaining a deterministic transaction order. +- **Buffering:** Received transactions are temporarily stored in a buffer awaiting batch formation. + +**Batch Formation Criteria:** + +- **Size Thresholds:** Batch formation occurs when accumulated transactions reach a predefined size limit. This limit ensures that the fixed costs of posting data to the parent chain are amortized over more transaction, improving cost efficiency. +- **Time Constraints:** The Sequencer also monitors the time elapsed since the last posted batch to prevent undue delays. Upon reaching the maximum time threshold, the Sequencer will create a batch with the transactions collected so far, even if the batch doesn't meet the size threshold. + +**Batch Creation Process:** + +- **Aggregation:** Once the batch formation criteria ( the size or time threshold) are satisfied, the Sequencer aggregates the buffered transactions into a single batch. +- **Metadata Inclusion:** The batch includes the necessary metadata of all transactions. +- **Preparation for Compression:** Batch preparation for the compression stage begins, where techniques will minimize the data size before posting to parent chain. + +This batching mechanism allows the Sequencer to efficiently manage transactions by balancing the need for cost-effective parent chain posting with the requirement for prompt transaction processing. By strategically grouping transactions into batches based on size and time criteria, the Sequencer reduces per-transaction costs and enhances the overall scalability of the Arbitrum network. + +### Compression + +The Sequencer employs compression when forming transaction batches to optimize the data and cost of batches posted to the parent chain. Arbitrum uses the Brotli compression algorithm due to its high compression ratio and efficiency, crucial for reducing parent chain posting costs. + +
![compression](../assets/compression.png)
+ +### Compression level in the Brotli algorithm + +Brotli’s compression algorithm includes a parameter: **compression level**, which ranges from **0 to 11**. This parameter allows you to balance two key factors: + +- **Compression Efficiency**: Higher levels result in greater size reduction. +- **Computational Cost**: Higher levels require more processing power and time. + +As the compression level increases, you achieve better compression ratios at the expense of longer compression times. + +### Dynamic compression level setting + +The compression level on Arbitrum is dynamically adjusted based on the current backlog of batches waiting to be posted to parent chain by Sequencer. In scenarios where multiple batches are queued in the buffer, the **compression level** can be dynamically adjusted to improve throughput. When the buffer becomes overloaded with overdue batches, the compression level decreases. + +This tradeoff prioritizes speed over compression efficiency, enabling faster processing and transmitting pending batches. Doing so, clears the buffer more quickly, ensuring smoother overall system performance. + +Now that transactions are batched and compressed, they can be passed to batch-poster to be sent to the parent chain. + +## Submitting to the Sequencer Inbox Contract + +After batching and compressing transactions, the Sequencer posts these batches to the parent chain to ensure security and finality. This process involves the **Batch Poster**, an Externally Owned Account (EOA) controlled by the Sequencer. The Batch Poster is responsible for submitting the compressed transaction batches to the **Sequencer Inbox Contract** on parent chain. + +There are two primary methods the Sequencer uses to send batches to the parent chain, depending on whether the chain supports EIP-4844 (Proto-Danksharding) and the current network conditions: + +
+ ![submit-to-sequencer-inbox](../assets/submit-to-sequencer-inbox.png) +
+ +### 1. Using Blobs with `addSequencerL2BatchFromBlobs` + +- **Default Approach**: When the parent chain supports EIP-4844, the Sequencer utilizes blob transactions to post batches efficiently. +- **Method**: The Batch Poster calls the `addSequencerL2BatchFromBlobs` function of the Sequencer Inbox Contract. +- **Process**: + - Batch data gets included as blobs—large binary data structures optimized for scalability. + - The transaction includes metadata about the batch but does not include the batch data itself in the calldata. +- **Benefits**: + - **Cost Efficiency**: Blobs allow cheaper data inclusion than calldata, reducing gas costs. + - **Scalability**: Leveraging blobs enhances the network's ability to handle large volumes of transactions. + +### 2. Using Calldata with `addSequencerL2Batch` + +- **Alternative Approach**: If the **Blob Base Fee** is significantly high or the blob space is constrained during batch posting, the Sequencer may opt to use calldata. +- **Method**: The Batch Poster calls the `addSequencerL2Batch` function of the Sequencer Inbox Contract. +- **Process**: + - The compressed batch transactions are included directly in the transaction's calldata. +- **Considerations**: + - **Cost Evaluation**: The Sequencer dynamically assesses whether using calldata is more cost-effective than blobs based on current gas prices and blob fees. + - **Compatibility**: If the parent chain does not support EIP-4844, this method is the default and only option for batch posting. + +:::note +The Sequencer continuously monitors network conditions to choose the most economical method for batch posting, ensuring optimal operation under varying circumstances. +::: + +### Authority and Finality + +- **Exclusive Access**: Only the Sequencer can call these methods on the Sequencer Inbox Contract. This exclusivity ensures that no other party can directly include messages. +- **Soft-Confirmation Receipts**: The Sequencer's unique ability to immediately process and include transactions allows it to provide users with instant, "soft-confirmation" receipts, +- **Parent chain Finality**: Once batches post, the transactions achieve parent-chain-level finality, secured by Parent chain’s consensus mechanism. + +By efficiently sending compressed transaction batches to the Sequencer Inbox Contract using the most cost-effective method available, the Sequencer ensures transactions are securely recorded on parent chain. This process maintains the integrity and reliability of the network, providing users with fast and secure transaction processing. + +## Finality + +Finality in blockchain systems refers to the point at which a transaction becomes irreversible and permanently included in the blockchain's ledger. In the context of Arbitrum's Nitro architecture, understanding finality is crucial for developers and users to make informed decisions about transaction confirmations, security guarantees, and application design. + +Arbitrum offers two levels of finality: + +1. **Soft Finality**: Provided by the Sequencer's real-time feed, offering immediate but provisional transaction confirmations. +2. **Hard Finality**: Occurs when transactions are included in batches posted to and finalized on the parent chain, providing strong security assurances. + +This section explores the concepts of soft and hard finality, their implications, trust considerations, and guidance for utilizing them effectively within the Arbitrum network. + +### Soft Finality + +Soft finality refers to the preliminary confirmation of transactions based on the Sequencer's real-time feed. Key characteristics include: + +- **Immediate Confirmation**: Transactions are confirmed almost instantly as they are accepted and ordered by the Sequencer. +- **Provisional Assurance**: The confirmations are provisional and rely on the Sequencer's integrity and availability. +- **High Performance**: Enables applications to offer rapid responses and real-time interactions, enhancing user experience. + +**Advantages of Soft Finality**: + +- **Low Latency**: Users receive immediate feedback on transaction status. +- **Optimized for Speed**: Ideal for applications where responsiveness is critical. +- **Improved User Experience**: Reduces waiting times and uncertainty. + +**Limitations of Soft Finality**: + +- **Trust Dependency**: Relies on the Sequencer's honesty and ability to maintain uptime.. +- **Potential for Reordering**: In rare cases, if the Sequencer acts maliciously or encounters issues, the provisional ordering could change. +- **Not Suitable for High-Value Transactions**: For transactions requiring strong security guarantees, soft finality may not suffice. + +### Hard Finality + +Hard finality occurs when batched transactions get posted to the parent chain. Key characteristics include: + +- **Strong Security Guarantees**: When included in blocks on the parent chain, transactions inherit the parent chain's security assurances. +- **Irreversibility**: Once finalized, transactions are immutable and cannot be altered or reversed. +- **Data Availability**: All transaction data is recorded on-chain, ensuring transparency and verifiability. + +**Advantages of Hard Finality**: + +- **Maximum Security**: Protected by the robustness of the parent chain's consensus mechanism. +- **Trust Minimization**: This does not require trust in the Sequencer; security comes from the underlying blockchain. +- **Suitable for High-Value Transactions**: Ideal for scenarios where security and immutability are paramount. + +**Limitations of Hard Finality**: + +- **Higher Latency**: Achieving hard finality takes longer due to the time required for the parent chain to process and finalize batches. +- **Cost Considerations**: Posting batches to the parent chain incurs fees, which may affect transaction costs. + +### Trust Considerations + +Understanding the trust assumptions associated with each level of finality is essential: + +- **Soft Finality Trust Model**: + - **Reliance on the Sequencer**: Users must trust that the Sequencer operates honestly, sequences transactions correctly, and remains available. + - **Risk of Misbehavior**: If the Sequencer acts maliciously, it could reorder or censor certain transactions before they achieve hard finality. +- **Hard Finality Trust Model**: + - **Reliance on the Parent Chain**: Security is based on the consensus and integrity of the parent chain. + - **Reduced Trust in Sequencer**: Even if the Sequencer misbehaves, transactions included in posted batches are secured once finalized on the parent chain. + +### Application Implications + +Developers and users should consider the appropriate level of finality based on their specific use cases: + +- **When to Rely on Soft Finality**: + - **Low-Risk Transactions**: For transactions where the potential impact of reordering or delays is minimal. + - **User Experience Priority**: Applications where responsiveness and immediacy enhance user engagement, such as gaming or social platforms. + - **Frequent Transactions**: Scenarios involving a high volume of small transactions where waiting for hard finality is impractical. +- **When to Require Hard Finality**: + - **High-Value Transactions**: Financial transfers, large trades, or any transaction where security is critical. + - **Regulatory Compliance**: Situations requiring strict adherence to security standards and auditable records. + - **Centralized Exchanges (CeXs)**: For deposit and withdrawal operations where certainty of transaction finality is mandatory. + +### Decentralized Fair Sequencing + +Arbitrum’s long-term vision includes transitioning from a centralized Sequencer to a decentralized, fair sequencing model. In this framework, a committee of servers (or validators) collectively determines transaction ordering, ensuring fairness, reducing the influence of any single party, and making it more resistant to manipulation. By requiring a supermajority consensus, this approach distributes sequencing power among multiple honest participants, mitigates the risks of front-running or censorship, and aligns with the broader blockchain principles of enhanced security, transparency, and decentralization. diff --git a/arbitrum-docs/how-arbitrum-works/04-geth-at-the-core.mdx b/arbitrum-docs/how-arbitrum-works/04-geth-at-the-core.mdx new file mode 100644 index 000000000..f8e8e539b --- /dev/null +++ b/arbitrum-docs/how-arbitrum-works/04-geth-at-the-core.mdx @@ -0,0 +1,423 @@ +--- +title: Geth at the core +description: Learn the fundamentals of Geth and ArbOS. +author: pete-vielhaber +sme: TucksonDev +user_story: As a current or prospective Arbitrum user, I need to learn more about Geth and ArbOS. +content_type: get-started +--- + +The second key design idea in Nitro is "Geth at the core." Here "geth" refers to go-ethereum, the most common node software for Ethereum. As its name would suggest, go-ethereum is written in the Go programming language, as is almost all of Nitro. + +![geth-sandwich](../assets/geth-sandwich.png) + +The software that makes up a Nitro node can be thought of as built in three main layers, which are shown above: + +- The base layer is the core of geth--the parts of Geth that emulate the execution of EVM contracts and maintain the data structures that make up the Ethereum state. Nitro compiles in this code as a library, with a few minor modifications to add necessary hooks. +- The middle layer, which we call ArbOS, is custom software that provides additional functions associated with Layer 2 functionality, such as decompressing and parsing the Sequencer's data batches, accounting for Layer 1 gas costs and collecting fees to reimburse for them, and supporting cross-chain Bridge functionalities such as deposits of Ether and tokens from L1 and withdrawals of the same back to L1. We'll dig in to the details of ArbOS below. +- The top layer consists of node software, mostly drawn from geth. This handles connections and incoming RPC requests from clients and provides the other top-level functionality required to operate an Ethereum-compatible Blockchain node. + +Because the top and bottom layers rely heavily on code from geth, this structure has been dubbed a "geth sandwich." Strictly speaking, Geth plays the role of the bread in the sandwich, and ArbOS is the filling, but this sandwich is named for the bread. + +The State Transition Function consists of the bottom Geth layer, and a portion of the middle ArbOS layer. In particular, the STF is a designated function in the source code, and implicitly includes all of the code called by that function. The STF takes as input the bytes of a Transaction received in the inbox, and has access to a modifiable copy of the Ethereum state tree. Executing the STF may modify the state, and at the end will emit the header of a new block (in Ethereum's block header format) which will be appended to the Nitro chain. + +The rest of this section will be a deep dive into Geth and ArbOS. If deep technical knowledge does not suit you, skip to the next section [Separating Execution from Proving](/how-arbitrum-works/05-separating-execution-from-proving.mdx). + +## Geth + +Nitro makes minimal modifications to Geth in hopes of not violating its assumptions. This section will explore the relationship between Geth and ArbOS, which consists of a series of hooks, interface implementations, and strategic re-appropriations of Geth's basic types. + +We store ArbOS's state at an address inside a Geth `statedb`. In doing so, ArbOS inherits the `statedb`'s statefulness and lifetime properties. For example, a transaction's direct state changes to ArbOS are discarded upon a revert. + +**0xA4B05FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF**
+The fictional account representing ArbOS + +:::info + +Please note any links on this page may be referencing old releases of Nitro or our fork of Geth. While we try to keep this up to date and most of this should be stable, please check against latest releases for [Nitro](https://github.com/OffchainLabs/nitro/releases) and [Geth](https://github.com/OffchainLabs/go-ethereum/releases) for most recent changes. + +::: + +### Hooks + +Arbitrum uses various hooks to modify Geth's behavior when processing +transactions. Each provides an opportunity for ArbOS to update its state and make decisions about the +transaction during its lifetime. Transactions are applied using Geth's [`ApplyTransaction`][applytransaction_link] +function. + +Below is [`ApplyTransaction`][applytransaction_link]'s callgraph, with additional info on where the various Arbitrum-specific hooks are inserted. Click on any to go to their section. By default, these hooks do nothing so as to leave Geth's default behavior unchanged, but for chains configured with [`EnableArbOS`](#enablearbos) set to true, [`ReadyEVMForL2`](#ReadyEVMForL2) installs the alternative L2 hooks. + +- `core.ApplyTransaction` ⮕ `core.applyTransaction` ⮕ `core.ApplyMessage` + - `core.NewStateTransition` + - [`ReadyEVMForL2`](#ReadyEVMForL2) + - `core.TransitionDb` + - [`StartTxHook`](#StartTxHook) + - `core.transitionDbImpl` + - if `IsArbitrum()` remove tip + - [`GasChargingHook`](/how-arbitrum-works/geth-at-the-core#gascharginghook) + - `evm.Call` + - `core.vm.EVMInterpreter.Run` + - [`PushCaller`](#PushCaller) + - `PopCaller` + - `core.StateTransition.refundGas` + - [`ForceRefundGas`](#ForceRefundGas) + - [`NonrefundableGas`](#NonrefundableGas) + - [`EndTxHook`](#EndTxHook) + - added return parameter: `transactionResult` + +What follows is an overview of each hook, in chronological order. + +#### [`ReadyEVMForL2`][readyevmforl2_link]{#ReadyEVMForL2} + +A call to [`ReadyEVMForL2`][readyevmforl2_link] installs the other transaction-specific hooks into each Geth [`EVM`][evm_link] right before it performs a state transition. Without this call, the state transition will instead use the default [`DefaultTxProcessor`][defaulttxprocessor_link] and get exactly the same results as vanilla Geth. A [`TxProcessor`][txprocessor_link] object is what carries these hooks and the associated Arbitrum-specific state during the transaction's lifetime. + +#### [`StartTxHook`][starttxhook_link]{#StartTxHook} + +The [`StartTxHook`][starttxhook_link] is called by Geth before a transaction starts executing. This allows ArbOS to handle two Arbitrum-specific transaction types. + +If the transaction is `ArbitrumDepositTx`, ArbOS adds balance to the destination account. This is safe because the L1 bridge submits such a transaction only after collecting the same amount of funds on L1. + +If the transaction is an `ArbitrumSubmitRetryableTx`, ArbOS creates a retryable based on the transaction's fields. If the transaction includes sufficient gas, ArbOS schedules a retry of the new retryable. + +The hook returns `true` for both of these transaction types, signifying that the state transition is complete. + +#### [`GasChargingHook`][gascharginghook_link] + +This fallible hook ensures the user has enough funds to pay their poster's L1 calldata costs. If not, the transaction is reverted and the [`EVM`][evm_link] does not start. In the common case that the user can pay, the amount paid for calldata is set aside for later reimbursement of the poster. All other fees go to the network account, as they represent the transaction's burden on validators and nodes more generally. + +If the user attempts to purchase compute gas in excess of ArbOS's per-block gas limit, the difference is [set aside][difference_set_aside_link] and [refunded later][refunded_later_link] via [`ForceRefundGas`](#ForceRefundGas) so that only the gas limit is used. Note that the limit observed may not be the same as that seen [at the start of the block][that_seen_link] if ArbOS's larger gas pool falls below the [`MaxPerBlockGasLimit`][max_perblock_limit_link] while processing the block's previous transactions. + +[difference_set_aside_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L407 +[refunded_later_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/state_transition.go#L419 +[that_seen_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/block_processor.go#L176 +[max_perblock_limit_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/l2pricing/l2pricing.go#L86 + +#### [`PushCaller`][pushcaller_link]{#PushCaller} + +These hooks track the callers within the EVM callstack, pushing and popping as calls are made and complete. This provides [`ArbSys`](/build-decentralized-apps/precompiles/02-reference.mdx#arbsys) with info about the callstack, which it uses to implement the methods `WasMyCallersAddressAliased` and `MyCallersAddressWithoutAliasing`. + +#### [`L1BlockHash`][l1blockhash_link] + +In Arbitrum, the BlockHash and Number operations return data that relies on underlying L1 blocks instead of L2 blocks, to accommodate the normal use-case of these opcodes, which often assume Ethereum-like time passes between different blocks. The L1BlockHash and L1BlockNumber hooks have the required data for these operations. + +#### [`ForceRefundGas`][forcerefundgas_link]{#ForceRefundGas} + +This hook allows ArbOS to add additional refunds to the user's tx. This is currently only used to refund any compute gas purchased in excess of ArbOS's per-block gas limit during the [`GasChargingHook`](/how-arbitrum-works/geth-at-the-core#gascharginghook). + +#### [`NonrefundableGas`][nonrefundablegas_link]{#NonrefundableGas} + +Because poster costs come at the expense of L1 aggregators and not the network more broadly, the amounts paid for L1 calldata should not be refunded. This hook provides Geth access to the equivalent amount of L2 gas the poster's cost equals, ensuring this amount is not reimbursed for network-incentivized behaviors like freeing storage slots. + +#### [`EndTxHook`][endtxhook_link]{#EndTxHook} + +The [`EndTxHook`][endtxhook_link] is called after the [`EVM`][evm_link] has returned a transaction's result, allowing one last opportunity for ArbOS to intervene before the state transition is finalized. Final gas amounts are known at this point, enabling ArbOS to credit the network and poster each's share of the user's gas expenditures as well as adjust the pools. The hook returns from the [`TxProcessor`][txprocessor_link] a final time, in effect discarding its state as the system moves on to the next transaction where the hook's contents will be set afresh. + +[applytransaction_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/state_processor.go#L152 +[evm_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/vm/evm.go#L101 +[defaulttxprocessor_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/vm/evm_arbitrum.go#L42 +[txprocessor_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L38 +[starttxhook_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L100 +[readyevmforl2_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbstate/geth-hook.go#L47 +[gascharginghook_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L354 +[pushcaller_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L76 +[popcaller_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L80 +[forcerefundgas_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L425 +[nonrefundablegas_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L418 +[endtxhook_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L429 +[l1blockhash_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L617 +[l1blocknumber_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L600 + +### Interfaces and components + +#### [`APIBackend`][apibackend_link] + +APIBackend implements the [`ethapi.Backend`][ethapi.backend_link] interface, which allows simple integration of the Arbitrum chain to existing Geth API. Most calls are answered using the Backend member. + +[apibackend_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/apibackend.go#L34 +[ethapi.backend_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/internal/ethapi/backend.go#L42 + +#### [`Backend`][backend_link] + +This struct was created as an Arbitrum equivalent to the [`Ethereum`][ethereum_link] struct. It is mostly glue logic, including a pointer to the ArbInterface interface. + +[backend_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/backend.go#L15 +[ethereum_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/eth/backend.go#L68 + +#### [`ArbInterface`][arbinterface_link] + +This interface is the main interaction-point between geth-standard APIs and the Arbitrum chain. Geth APIs mostly either check status by working on the Blockchain struct retrieved from the [`Blockchain`][blockchain_link] call, or send transactions to Arbitrum using the [`PublishTransactions`][publishtransactions_link] call. + +[arbinterface_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/arbos_interface.go#L10 +[blockchain_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/arbos_interface.go#L12 +[publishtransactions_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/arbos_interface.go#L11 + +#### [`RecordingKV`][recordingkv_link] + +RecordingKV is a read-only key-value store, which retrieves values from an internal trie database. All values accessed by a RecordingKV are also recorded internally. This is used to record all preimages accessed during block creation, which will be needed to prove execution of this particular block. +A [`RecordingChainContext`][recordingchaincontext_link] should also be used, to record which block headers the block execution reads (another option would be to always assume the last 256 block headers were accessed). +The process is simplified using two functions: [`PrepareRecording`][preparerecording_link] creates a stateDB and chaincontext objects, running block creation process using these objects records the required preimages, and [`PreimagesFromRecording`][preimagesfromrecording_link] function extracts the preimages recorded. + +[recordingkv_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/recordingdb.go#L22 +[recordingchaincontext_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/recordingdb.go#L123 +[preparerecording_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/recordingdb.go#L152 +[preimagesfromrecording_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/recordingdb.go#L174 + +### Transaction Types + +Nitro Geth includes a few L2-specific transaction types. Click on any to jump to their section. + +| Tx Type | Represents | Last Hook Reached   | Source | +| :------------------------------------------------ | :----------------------------------------------------------------------- | :------------------------- | ------ | +| [`ArbitrumUnsignedTx`][arbtxunsigned] | An L1 to L2 message | [`EndTxHook`][he] | Bridge | +| [`ArbitrumContractTx`][arbtxcontract] | A nonce-less L1 to L2 message   | [`EndTxHook`][he] | Bridge | +| [`ArbitrumDepositTx`][arbtxdeposit] | A user deposit | [`StartTxHook`][hs] | Bridge | +| [`ArbitrumSubmitRetryableTx`][arbtxsubmit]   | Creating a retryable | [`StartTxHook`][hs]   | Bridge | +| [`ArbitrumRetryTx`][arbtxretry] | A Retryable Redeem attempt | [`EndTxHook`][he] | L2 | +| [`ArbitrumInternalTx`][arbtxinternal] | ArbOS state update | [`StartTxHook`][hs] | ArbOS | + +[arbtxunsigned]: #ArbitrumUnsignedTx +[arbtxcontract]: #ArbitrumContractTx +[arbtxsubmit]: #ArbitrumSubmitRetryableTx +[arbtxretry]: #ArbitrumRetryTx +[arbtxdeposit]: #ArbitrumDepositTx +[arbtxinternal]: #ArbitrumInternalTx +[hs]: #StartTxHook +[he]: #EndTxHook + +The following reference documents each type. + +#### [`ArbitrumUnsignedTx`][arbitrumunsignedtx_link]{#ArbitrumUnsignedTx} + +Provides a mechanism for a user on L1 to message a contract on L2. This uses the bridge for authentication rather than requiring the user's signature. Note, the user's acting address will be remapped on L2 to distinguish them from a normal L2 caller. + +#### [`ArbitrumContractTx`][arbitrumcontracttx_link]{#ArbitrumContractTx} + +These are like an [`ArbitrumUnsignedTx`][arbitrumunsignedtx_link] but are intended for smart contracts. These use the bridge's unique, sequential nonce rather than requiring the caller specify their own. An L1 contract may still use an [`ArbitrumUnsignedTx`][arbitrumunsignedtx_link], but doing so may necessitate tracking the nonce in L1 state. + +#### [`ArbitrumDepositTx`][arbitrumdeposittx_link]{#ArbitrumDepositTx} + +Represents a user deposit from L1 to L2. This increases the user's balance by the amount deposited on L1. + +#### [`ArbitrumSubmitRetryableTx`][arbitrumsubmitretryabletx_link]{#ArbitrumSubmitRetryableTx} + +Represents a retryable submission and may schedule an [`ArbitrumRetryTx`](#ArbitrumRetryTx) if provided enough gas. Please see the [retryables documentation](/how-arbitrum-works/10-l1-to-l2-messaging.mdx#retryable-tickets) for more info. + +#### [`ArbitrumRetryTx`][arbitrumretrytx_link]{#ArbitrumRetryTx} + +These are scheduled by calls to the `redeem` method of the [ArbRetryableTx](/build-decentralized-apps/precompiles/02-reference.mdx#arbretryabletx) precompile and via retryable auto-redemption. Please see the [retryables documentation](/how-arbitrum-works/10-l1-to-l2-messaging.mdx#retryable-tickets) for more info. + +#### [`ArbitrumInternalTx`][arbitruminternaltx_link]{#ArbitrumInternalTx} + +Because tracing support requires ArbOS's state-changes happen inside a transaction, ArbOS may create a transaction of this type to update its state in-between user-generated transactions. Such a transaction has a [`Type`][internaltype_link] field signifying the state it will update, though currently this is just future-proofing as there's only one value it may have. Below are the internal transaction types. + +##### [`InternalTxStartBlock`][arbinternaltxstartblock_link] + +Updates the L1 block number and L1 base fee. This transaction [is generated][block_generated_link] whenever a new block is created. They are [guaranteed to be the first][block_first_link] in their L2 Block. + +[arbitrumunsignedtx_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L43 +[arbitrumcontracttx_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L104 +[arbitrumsubmitretryabletx_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L232 +[arbitrumretrytx_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L161 +[arbitrumdeposittx_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L338 +[arbitruminternaltx_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/internal_tx.go +[internaltype_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L387 +[arbinternaltxstartblock_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/internal_tx.go#L22 +[block_generated_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/block_processor.go#L181 +[block_first_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/block_processor.go#L182 + +### Transaction Run Modes and Underlying Transactions + +A [geth message][geth_message_link] may be processed for various purposes. For example, a message may be used to estimate the gas of a contract call, whereas another may perform the corresponding state transition. Nitro Geth denotes the intent behind a message by means of its [`TxRunMode`][txrunmode_link], [which it sets][set_run_mode_link] before processing it. ArbOS uses this info to make decisions about the transaction the message ultimately constructs. + +A message [derived from a transaction][asmessage_link] will carry that transaction in a field accessible via its [`UnderlyingTransaction`][underlying_link] method. While this is related to the way a given message is used, they are not one-to-one. The table below shows the various run modes and whether each could have an underlying transaction. + +| Run Mode | Scope | Carries an Underlying Tx? | +| :--------------------------------------- | :---------------------- | :----------------------------------------------------------------------------------------------------------- | +| [`MessageCommitMode`][mc0] | state transition   | always | +| [`MessageGasEstimationMode`][mc1]   | gas estimation | when created via [NodeInterface](/build-decentralized-apps/nodeinterface/02-reference.mdx) or when scheduled | +| [`MessageEthcallMode`][mc2] | eth_calls | never | + +[mc0]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L654 +[mc1]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L655 +[mc2]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L656 +[geth_message_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L634 +[txrunmode_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L701 +[set_run_mode_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/internal/ethapi/api.go#L955 +[asmessage_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L676 +[underlying_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L700 + +### Arbitrum Chain Parameters + +Nitro's Geth may be configured with the following [l2-specific chain parameters][chain_params_link]. These allow the rollup creator to customize their rollup at genesis. + +#### `EnableArbos` + +Introduces [ArbOS](/how-arbitrum-works/04-geth-at-the-core.mdx#arbos), converting what would otherwise be a vanilla L1 chain into an L2 Arbitrum rollup. + +#### `AllowDebugPrecompiles` + +Allows access to debug precompiles. Not enabled for Arbitrum One. When false, calls to debug precompiles will always revert. + +#### `DataAvailabilityCommittee` + +Currently does nothing besides indicate that the rollup will access a data availability service for preimage resolution in the future. This is not enabled for Arbitrum One, which is a strict state-function of its L1 inbox messages. + +[chain_params_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/params/config_arbitrum.go#L25 + +### Miscellaneous Geth Changes + +#### ABI Gas Margin + +Vanilla Geth's abi library submits txes with the exact estimate the node returns, employing no padding. This means a transaction may revert should another arriving just before even slightly change the transaction's codepath. To account for this, we've added a `GasMargin` field to `bind.TransactOpts` that [pads estimates][pad_estimates_link] by the number of basis points set. + +#### Conservation of L2 ETH + +The total amount of L2 ether in the system should not change except in controlled cases, such as when bridging. As a safety precaution, ArbOS checks Geth's [balance delta][conservation_link] each time a block is created, [alerting or panicking][alert_link] should conservation be violated. + +#### MixDigest and ExtraData + +To aid with [Outbox proof construction][proof_link], the root hash and leaf count of ArbOS's [send merkle accumulator][merkle_link] are stored in the `MixDigest` and `ExtraData` fields of each L2 block. The yellow paper specifies that the `ExtraData` field may be no larger than 32 bytes, so we use the first 8 bytes of the `MixDigest`, which has no meaning in a system without miners/stakers, to store the send count. + +#### Retryable Support + +Retryables are mostly implemented in [ArbOS](/how-arbitrum-works/10-l1-to-l2-messaging.mdx). Some modifications were required in Geth to support them. + +- Added ScheduledTxes field to ExecutionResult. This lists transactions scheduled during the execution. To enable using this field, we also pass the ExecutionResult to callers of ApplyTransaction. +- Added gasEstimation param to DoCall. When enabled, DoCall will also also executing any retryable activated by the original call. This allows estimating gas to enable retryables. + +#### Added accessors + +Added [`UnderlyingTransaction`][underlyingtransaction_link] to Message interface +Added [`GetCurrentTxLogs`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/state/statedb_arbitrum.go) to StateDB +We created the AdvancedPrecompile interface, which executes and charges gas with the same function call. This is used by [Arbitrum's precompiles](/build-decentralized-apps/precompiles/01-overview.mdx), and also wraps Geth's standard precompiles. + +#### WASM build support + +The WASM Arbitrum executable does not support file operations. We created [`fileutil.go`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/rawdb/fileutil.go) to wrap fileutil calls, stubbing them out when building WASM. [`fake_leveldb.go`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/ethdb/leveldb/fake_leveldb.go) is a similar WASM-mock for leveldb. These are not required for the WASM block-replayer. + +#### Types + +Arbitrum introduces a new [`signer`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arbitrum_signer.go), and multiple new [`transaction types`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go). + +#### ReorgToOldBlock + +Geth natively only allows reorgs to a fork of the currently-known network. In nitro, reorgs can sometimes be detected before computing the forked block. We added the [`ReorgToOldBlock`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/blockchain_arbitrum.go#L38) function to support reorging to a block that's an ancestor of current head. + +#### Genesis block creation + +Genesis block in nitro is not necessarily block #0. Nitro supports importing blocks that take place before genesis. We split out [`WriteHeadBlock`][writeheadblock_link] from genesis.Commit and use it to commit non-zero genesis blocks. + +[pad_estimates_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/accounts/abi/bind/base.go#L355 +[conservation_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/state/statedb.go#L42 +[alert_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/block_processor.go#L424 +[proof_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/system_tests/outbox_test.go#L26 +[merkle_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/merkleAccumulator/merkleAccumulator.go#L13 +[underlyingtransaction_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/state_transition.go#L69 +[writeheadblock_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/genesis.go#L415 + +## ArbOS + +ArbOS is the Layer 2 EVM hypervisor that facilitates the execution environment of L2 Arbitrum. ArbOS is a trusted "system glue" component that runs at Layer 2 as part of the State Transition Function, it accounts for and manages network resources, produces blocks from incoming messages, cross-chain messaging, and operates its instrumented instance of Geth for Smart Contract execution. + +In Arbitrum, much of the work that would otherwise have to be done expensively at Layer 1 is instead done by ArbOS, trustlessly performing these functions at the speed and low cost of Layer 2. + +Supporting these functions in Layer 2 trusted software, rather than building them in to the L1-enforced rules of the architecture as Ethereum does, offers significant advantages in cost because these operations can benefit from the lower cost of computation and storage at Layer 2, instead of having to manage those resources as part of a Layer 1 contract. Having a trusted operating system at Layer 2 also has significant advantages in flexibility, because Layer 2 code is easier to evolve, or to customize for a particular chain, than a Layer-1 enforced architecture would be. + +### Precompiles + +ArbOS provides L2-specific precompiles with methods smart contracts can call the same way they can solidity functions. Visit the [precompiles conceptual page](/build-decentralized-apps/precompiles/01-overview.mdx) for more information about how these work, and the [precompiles reference page](/build-decentralized-apps/precompiles/02-reference.mdx) for a full reference of the precompiles available in Arbitrum chains. + +A precompile consists of a solidity interface in [`contracts/src/precompiles/`][nitro_precompiles_dir] and a corresponding Golang implementation in [`precompiles/`][precompiles_dir]. Using Geth's ABI generator, [`solgen/gen.go`][gen_file] generates [`solgen/go/precompilesgen/precompilesgen.go`][precompilesgen_link], which collects the ABI data of the precompiles. The [runtime installer][installer_link] uses this generated file to check the type safety of each precompile's implementer. + +[The installer][installer_link] uses runtime reflection to ensure each implementer has all the right methods and signatures. This includes restricting access to stateful objects like the EVM and statedb based on the declared purity. Additionally, the installer verifies and populates event function pointers to provide each precompile the ability to emit logs and know their gas costs. Additional configuration like restricting a precompile's methods to only be callable by chain owners is possible by adding precompile wrappers like [`ownerOnly`][owneronly_link] and [`debugOnly`][debugonly_link] to their [installation entry][installation_link]. + +The calling, dispatching, and recording of precompile methods are done via runtime reflection as well. This avoids any human error manually parsing and writing bytes could introduce, and uses Geth's stable APIs for [packing and unpacking][packing_link] values. + +Each time a transaction calls a method of an L2-specific precompile, a [`call context`][call_context_link] is created to track and record the gas burnt. For convenience, it also provides access to the public fields of the underlying [`TxProcessor`][txprocessor_link]. Because sub-transactions could revert without updates to this struct, the [`TxProcessor`][txprocessor_link] only makes public that which is safe, such as the amount of L1 calldata paid by the top level transaction. + +[nitro_precompiles_dir]: https://github.com/OffchainLabs/nitro-contracts/tree/main/src/precompiles +[precompiles_dir]: https://github.com/OffchainLabs/nitro/tree/master/precompiles +[installer_link]: https://github.com/OffchainLabs/nitro/blob/bc6b52daf7232af2ca2fec3f54a5b546f1196c45/precompiles/precompile.go#L379 +[installation_link]: https://github.com/OffchainLabs/nitro/blob/bc6b52daf7232af2ca2fec3f54a5b546f1196c45/precompiles/precompile.go#L403 +[gen_file]: https://github.com/OffchainLabs/nitro/blob/master/solgen/gen.go +[owneronly_link]: https://github.com/OffchainLabs/nitro/blob/f11ba39cf91ee1fe1b5f6b67e8386e5efd147667/precompiles/wrapper.go#L58 +[debugonly_link]: https://github.com/OffchainLabs/nitro/blob/f11ba39cf91ee1fe1b5f6b67e8386e5efd147667/precompiles/wrapper.go#L23 +[precompilesgen_link]: https://github.com/OffchainLabs/nitro/blob/f11ba39cf91ee1fe1b5f6b67e8386e5efd147667/solgen/gen.go#L55 +[packing_link]: https://github.com/OffchainLabs/nitro/blob/bc6b52daf7232af2ca2fec3f54a5b546f1196c45/precompiles/precompile.go#L438 +[call_context_link]: https://github.com/OffchainLabs/nitro/blob/f11ba39cf91ee1fe1b5f6b67e8386e5efd147667/precompiles/context.go#L26 + +### Messages + +An [`L1IncomingMessage`][l1incomingmessage_link] represents an incoming sequencer message. A message includes one or more user transactions depending on load, and is made into a [unique L2 block][produceblockadvanced_link]. The L2 block may include additional system transactions added in while processing the message's user transactions, but ultimately the relationship is still bijective: for every [`L1IncomingMessage`][l1incomingmessage_link] there is an L2 block with a unique L2 block hash, and for every L2 block after chain initialization there was an [`L1IncomingMessage`][l1incomingmessage_link] that made it. A sequencer Batch may contain more than one [`L1IncomingMessage`][l1incomingmessage_link]. + +[l1incomingmessage_link]: https://github.com/OffchainLabs/nitro/blob/4ac7e9268e9885a025e0060c9ec30f9612f9e651/arbos/incomingmessage.go#L54 +[produceblockadvanced_link]: https://github.com/OffchainLabs/nitro/blob/4ac7e9268e9885a025e0060c9ec30f9612f9e651/arbos/block_processor.go#L118 + +### Retryables + +A Retryable is a special message type for creating atomic L1 to L2 messages; for details, see [L1 To L2 Messaging](/how-arbitrum-works/10-l1-to-l2-messaging.mdx). + +### ArbOS State + +ArbOS's state is viewed and modified via [`ArbosState`][arbosstate_link] objects, which provide convenient abstractions for working with the underlying data of its [`backingStorage`][backingstorage_link]. The backing storage's [keyed subspace strategy][subspace_link] makes possible [`ArbosState`][arbosstate_link]'s convenient getters and setters, minimizing the need to directly work with the specific keys and values of the underlying storage's [`stateDB`][statedb_link]. + +Because two [`ArbosState`][arbosstate_link] objects with the same [`backingStorage`][backingstorage_link] contain and mutate the same underlying state, different [`ArbosState`][arbosstate_link] objects can provide different views of ArbOS's contents. [`Burner`][burner_link] objects, which track gas usage while working with the [`ArbosState`][arbosstate_link], provide the internal mechanism for doing so. Some are read-only, causing transactions to revert with `vm.ErrWriteProtection` upon a mutating request. Others demand the caller have elevated privileges. While yet others dynamically charge users when doing stateful work. For safety the kind of view is chosen when [`OpenArbosState()`][openarbosstate_link] creates the object and may never change. + +Much of ArbOS's state exists to facilitate its [precompiles](/build-decentralized-apps/precompiles/02-reference.mdx). The parts that aren't are detailed below. + +[arbosstate_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/arbosState/arbosstate.go#L36 +[backingstorage_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/storage/storage.go#L51 +[statedb_link]: https://github.com/OffchainLabs/go-ethereum/blob/0ba62aab54fd7d6f1570a235f4e3a877db9b2bd0/core/state/statedb.go#L66 +[subspace_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/storage/storage.go#L21 +[openarbosstate_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/arbosState/arbosstate.go#L57 +[burner_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/burn/burn.go#L11 + +#### [`arbosVersion`][arbosversion_link], [`upgradeVersion`][upgradeversion_link] and [`upgradeTimestamp`][upgradetimestamp_link] + +ArbOS upgrades are scheduled to happen [when finalizing the first block][finalizeblock_link] after the [`upgradeTimestamp`][upgradetimestamp_link]. + +[arbosversion_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/arbosState/arbosstate.go#L37 +[upgradeversion_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/arbosState/arbosstate.go#L38 +[upgradetimestamp_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/arbosState/arbosstate.go#L39 +[finalizeblock_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/block_processor.go#L350 + +#### [`blockhashes`][blockhashes_link] + +This component maintains the last 256 L1 block hashes in a circular buffer. This allows the [`TxProcessor`][txprocessor_link] to implement the `BLOCKHASH` and `NUMBER` opcodes as well as support precompile methods that involve the outbox. To avoid changing ArbOS state outside of a transaction, blocks made from messages with a new L1 block number update this info during an [`InternalTxUpdateL1BlockNumber`][internaltxupdatel1blocknumber_link] [`ArbitrumInternalTx`][arbitruminternaltx_link] that is included as the first transaction in the block. + +[blockhashes_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/blockhash/blockhash.go#L15 +[internaltxupdatel1blocknumber_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/internal_tx.go#L24 +[arbitruminternaltx_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/block_processor.go#L116 +[txprocessor_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/tx_processor.go#L33 + +#### [`l1PricingState`][l1pricingstate_link] + +In addition to supporting the [`ArbAggregator precompile`](/build-decentralized-apps/precompiles/02-reference.mdx#arbaggregator), the L1 pricing state provides tools for determining the L1 component of a transaction's gas costs. This part of the state tracks both the total amount of funds collected from transactions in L1 gas fees, as well as the funds spent by batch posters to post data batches on L1. + +Based on this information, ArbOS maintains an L1 data fee, also tracked as part of this state, which determines how much transactions will be charged for L1 fees. ArbOS dynamically adjusts this value so that fees collected are approximately equal to batch posting costs, over time. + +[l1pricingstate_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/l1pricing/l1pricing.go#L16 + +#### [`l2PricingState`][l2pricingstate_link] + +The L2 pricing state tracks L2 resource usage to determine a reasonable L2 gas price. This process considers a variety of factors, including user demand, the state of Geth, and the computational Speed Limit. The primary mechanism for doing so consists of a pair of pools, one larger than the other, that drain as L2-specific resources are consumed and filled as time passes. L1-specific resources like L1 `calldata` are not tracked by the pools, as they have little bearing on the actual work done by the network actors that the speed limit is meant to keep stable and synced. + +While much of this state is accessible through the [`ArbGasInfo`](/build-decentralized-apps/precompiles/02-reference.mdx#arbgasinfo) and [`ArbOwner`](/build-decentralized-apps/precompiles/02-reference.mdx#arbowner) precompiles, most changes are automatic and happen during [block production][block_production_link] and [the transaction hooks](#hooks). Each of an incoming message's transactions removes from the pool the L2 component of the gas it uses, and afterward the message's timestamp [informs the pricing mechanism][notify_pricer_link] of the time that's passed as ArbOS [finalizes the block][finalizeblock_link]. + +ArbOS's larger gas pool [determines][maintain_limit_link] the per-block gas limit, setting a dynamic [upper limit][per_block_limit_link] on the amount of compute gas an L2 block may have. This limit is always enforced, though for the [first transaction][first_transaction_link] it's done in the [GasChargingHook](/how-arbitrum-works/geth-at-the-core#gascharginghook) to avoid sharp decreases in the L1 gas price from over-inflating the compute component purchased to above the gas limit. This improves UX by allowing the first transaction to succeed rather than requiring a resubmission. Because the first transaction lowers the amount of space left in the block, subsequent transactions do not employ this strategy and may fail from such compute-component inflation. This is acceptable because such transactions are only present in cases where the system is under heavy load and the result is that the user's transaction is dropped without charges since the state transition fails early. Those trusting the sequencer can rely on the transaction being automatically resubmitted in such a scenario. + +The reason we need a per-block gas limit is that Arbitrator WAVM execution is much slower than native transaction execution. This means that there can only be so much gas -- which roughly translates to wall-clock time -- in an L2 block. It also provides an opportunity for ArbOS to limit the size of blocks should demand continue to surge even as the price rises. + +ArbOS's per-block gas limit is distinct from Geth's block limit, which ArbOS [sets sufficiently high][geth_pool_set_link] so as to never run out. This is safe since Geth's block limit exists to constrain the amount of work done per block, which ArbOS already does via its own per-block gas limit. Though it'll never run out, a block's transactions use the [same Geth gas pool][same_geth_pool_link] to maintain the invariant that the pool decreases monotonically after each tx. Block headers [use the Geth block limit][use_geth_pool_link] for internal consistency and to ensure gas estimation works. These are both distinct from the [`gasLeft`][per_block_limit_link] variable, which ephemerally exists outside of global state to both keep L2 blocks from exceeding ArbOS's per-block gas limit and to [deduct space][deduct_space_link] in situations where the state transition failed or [used negligible amounts][negligible_amounts_link] of compute gas. ArbOS does not need to persist [`gasLeft`][per_block_limit_link] because it is its _pool_ that induces a revert and because transactions use the Geth block limit during EVM execution. + +[l2pricingstate_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/l2pricing/l2pricing.go#L14 +[block_production_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/block_processor.go#L77 +[notify_pricer_link]: https://github.com/OffchainLabs/nitro/blob/fa36a0f138b8a7e684194f9840315d80c390f324/arbos/block_processor.go#L336 +[maintain_limit_link]: https://github.com/OffchainLabs/nitro/blob/2ba6d1aa45abcc46c28f3d4f560691ce5a396af8/arbos/l2pricing/pools.go#L98 +[per_block_limit_link]: https://github.com/OffchainLabs/nitro/blob/2ba6d1aa45abcc46c28f3d4f560691ce5a396af8/arbos/block_processor.go#L146 +[first_transaction_link]: https://github.com/OffchainLabs/nitro/blob/2ba6d1aa45abcc46c28f3d4f560691ce5a396af8/arbos/block_processor.go#L237 +[geth_pool_set_link]: https://github.com/OffchainLabs/nitro/blob/2ba6d1aa45abcc46c28f3d4f560691ce5a396af8/arbos/block_processor.go#L166 +[same_geth_pool_link]: https://github.com/OffchainLabs/nitro/blob/2ba6d1aa45abcc46c28f3d4f560691ce5a396af8/arbos/block_processor.go#L199 +[use_geth_pool_link]: https://github.com/OffchainLabs/nitro/blob/2ba6d1aa45abcc46c28f3d4f560691ce5a396af8/arbos/block_processor.go#L67 +[deduct_space_link]: https://github.com/OffchainLabs/nitro/blob/faf55a1da8afcabb1f3c406b291e721bfde71a05/arbos/block_processor.go#L272 +[negligible_amounts_link]: https://github.com/OffchainLabs/nitro/blob/faf55a1da8afcabb1f3c406b291e721bfde71a05/arbos/block_processor.go#L328 diff --git a/arbitrum-docs/how-arbitrum-works/05-separating-execution-from-proving.mdx b/arbitrum-docs/how-arbitrum-works/05-separating-execution-from-proving.mdx new file mode 100644 index 000000000..d77c2726f --- /dev/null +++ b/arbitrum-docs/how-arbitrum-works/05-separating-execution-from-proving.mdx @@ -0,0 +1,36 @@ +--- +title: Separating Execution from Proving +description: 'Learn the fundamentals of Arbitrum Rollup protocol.' +author: pete-vielhaber +sme: TucksonDev +user_story: As a current or prospective Arbitrum user, I need to learn more about the Arbitrum Rollup protocol. +content_type: get-started +--- + +One of the challenges in designing a practical Rollup system is the tension between wanting the system to perform well in ordinary execution versus being able to reliably prove the results of execution. Nitro resolves this tension by using the same source code for both execution and proving, but compiling it to different targets for the two cases. + +When compiling the Nitro node software for _execution_, the ordinary Go compiler is used, producing native code for the target architecture, which of course will be different for different node deployments. (The node software is distributed in source code form and as a Docker image containing a compiled binary.) + +Separately, for _proving_, the portion of the code that is the State Transition Function is compiled by the Go compiler to WebAssembly (WASM), which is a typed, portable machine code format. The wasm code then goes through a simple transformation into a format we call WAVM, which is detailed below. If there is a dispute about the correct result of computing the STF, it is resolved with reference to the WAVM code. + +## WAVM + +The Wasm format has many features that make it a good vehicle for fraud proofs—it is portable, structured, well-specified, and has reasonably good tools and support. However, it needs a few modifications to do the job completely. Nitro uses a slightly modified version of Wasm, which we call WAVM. A simple transformation stage turns the Wasm code produced by the Go compiler into WAVM code suitable for proving. + +WAVM differs from wasm in three main ways. First, WAVM removes some wasm features that the Go compiler does not generate; the transformation phase verifies that these features are not present. + +Second, WAVM restricts a few features of wasm. For example, WAVM does not contain floating-point instructions, so the transformer replaces floating-point instructions with calls to the Berkeley SoftFloat library. (We use software floating-point to reduce the risk of floating-point incompatibilities between architectures. The core Nitro functions never use floating-point, but the Go runtime does use some floating-point operations.) WAVM does not contain nested control flow, so the transformer flattens control flow constructs, turning control flow instructions into jumps. Some wasm instructions take a variable amount of time to execute, which we avoid in WAVM by transforming them into constructs using fixed-cost instructions. These transformations simplify proving. + +Third, WAVM adds a few opcodes to enable interaction with the Blockchain environment. For example, new instructions allow the WAVM code to read and write the chain's global state, to get the next message from the chain's inbox, or to signal a successful end to execute the State Transition Function. + +## ReadPreImage and the Hash Oracle Trick + +The most interesting new instruction is `ReadPreImage` which takes as input a hash `H` and an offset `I`, and returns the word of data at offset `I` in the preimage of `H` (and the number of bytes written, which is zero if `I` is at or after the end of the preimage). Of course, it is not feasible in general to produce a preimage from an arbitrary hash. For safety, the `ReadPreImage` instruction can only be used in a context where the preimage is publicly known, and where the size of the preimage is known to be less than a fixed upper bound of about 110 kbytes. + +(In this context, "publicly known" information is information that can be derived or recovered efficiently by any honest party, assuming that the full history of the L1 Ethereum chain is available. For convenience, a hash preimage can also be supplied by a third party such as a public server, and the correctness of the supplied value is easily verified.) + +As an example, the state of a Nitro chain is maintained in Ethereum's state tree format, which is organized as a Merkle tree. Nodes of the tree are stored in a database, indexed by the Merkle hash of the node. In Nitro, the state tree is kept outside of the State Transition Function's storage, with the STF only knowing the root hash of the tree. Given the hash of a tree node, the STF can recover the tree node's contents by using `ReadPreImage`, relying on the fact that the full contents of the tree are publicly known and that nodes in the Ethereum state tree will always be smaller than the upper bound on preimage size. In this manner, the STF is able to arbitrarily read and write to the state tree, despite only storing its root hash. + +The only other use of `ReadPreImage` is to fetch the contents of recent L2 Block headers, given the header hash. This is safe because the block headers are publicly known and have bounded size. + +This "hash oracle trick" of storing the Merkle hash of a data structure, and relying on protocol participants to store the full structure and thereby support fetch-by-hash of the contents, goes back to the original Arbitrum design. diff --git a/arbitrum-docs/how-arbitrum-works/06-optimistic-rollup.mdx b/arbitrum-docs/how-arbitrum-works/06-optimistic-rollup.mdx new file mode 100644 index 000000000..b240fb7b3 --- /dev/null +++ b/arbitrum-docs/how-arbitrum-works/06-optimistic-rollup.mdx @@ -0,0 +1,269 @@ +--- +title: Optimistic Rollup +description: Learn the fundamentals of Arbitrum's optimistic rollup. +author: pete-vielhaber +sme: TucksonDev +user_story: As a current or prospective Arbitrum user, I need to learn more about Arbitrum's Optimistic Rollup protocol. +content_type: get-started +--- + +Arbitrum is an optimistic rollup. Let’s unpack that term. + +_Rollup_ + +Arbitrum is a Rollup, which means that the inputs to the chain -- the messages that are put into the inbox -- are all recorded on the Ethereum chain as calldata. Because of this, everyone has the information they would need to determine the current correct state of the chain -- they have the full history of the inbox, and the results are uniquely determined by the inbox history, so they can reconstruct the state of the chain based only on public information, if needed. + +This also allows anyone to be a full participant in the Arbitrum protocol, to run an Arbitrum node or participate as a Validator. Nothing about the history or state of the chain is a secret. + +_Optimistic_ + +Arbitrum is optimistic, which means that Arbitrum advances the state of its chain by letting any party (a “validator”) post on Layer 1 a rollup block that that party claims is correct, and then giving everyone else a chance to Challenge that claim. If the Challenge Period (6.4 days) passes and nobody has challenged the claimed rollup block, Arbitrum confirms the rollup block as correct. If someone challenges the claim during the challenge period, then Arbitrum uses an efficient dispute resolution protocol (detailed below) to identify which party is lying. The liar will forfeit a deposit, and the truth-teller will take part of that deposit as a reward for their efforts (some of the deposit is burned, guaranteeing that the liar is punished even if there's some collusion going on). + +Because a party who tries to cheat will lose a deposit, attempts to cheat should be very rare, and the normal case will be a single party posting a correct rollup block, and nobody challenging it. + +## Resolving disputes using interactive fraud proofs + +Among optimistic rollups, the most important design decision is how to resolve disputes. Suppose Alice claims that the chain will produce a certain result, and Bob disagrees. How will the protocol decide which version to accept? + +There are basically two choices: interactive proving, or re-executing transactions. Arbitrum uses interactive proving, which we believe is more efficient and more flexible. Much of the design of Arbitrum follows from this fact. + +### Interactive proving + +The idea of interactive proving is that Alice and Bob will engage in a back-and-forth protocol, refereed by an L1 contract, to resolve their dispute with minimal work required from any L1 contract. + +Arbitrum's approach is based on Dissection of the dispute. If Alice's claim covers N steps of execution, she posts two claims of size N/2 which combine to yield her initial N-step claim, then Bob picks one of Alice's N/2-step claims to challenge. Now the size of the dispute has been cut in half. This process continues, cutting the dispute in half at each stage, until they are disagreeing about a single step of execution. Note that so far the L1 referee hasn't had to think about execution "on the merits". It is only once the dispute is narrowed down to a single step that the L1 referee needs to resolve the dispute by looking at what the instruction actually does and whether Alice's claim about it is correct. + +The key principle behind interactive proving is that if Alice and Bob are in a dispute, Alice and Bob should do as much off-chain work as possible needed to resolve their dispute, rather than putting that work onto an L1 contract. + +### Re-executing transactions + +The alternative to interactive proving would be to have a rollup block contain a claimed machine state hash after every individual Transaction. Then in case of a dispute, the L1 referee would emulate the execution of an entire transaction, to see whether the outcome matches Alice's claim. + +### Why interactive proving is better + +We believe strongly that interactive proving is the superior approach, for the following reasons. + +**More efficient in the optimistic case**: Because interactive proving can resolve disputes that are larger than one transaction, it can allow a rollup block to contain only a single claim about the end state of the chain after all of the execution covered by the block. By contrast, reexecution requires posting a state claim for each transaction within the rollup block. With hundred or thousands of transactions per rollup block, this is a substantial difference in L1 footprint -- and L1 footprint is the main component of cost. + +**More efficient in the pessimistic case**: In case of a dispute, interactive proving requires the L1 referee contract only to check that Alice and Bob's actions "have the right shape", for example, that Alice has divided her N-step claim into two claims half as large. (The referee doesn't need to evaluate the correctness of Alice's claims--Bob does that, off-chain.) Only one instruction needs to be reexecuted. By contrast, reexecution requires the L1 referee to emulate the execution of an entire transaction. + +**Higher per-tx gas limit:** Interactive proving can escape from Ethereum's tight per-transaction gas limit. The gas limit isn't infinite, for obvious reasons, but it can be larger than on Ethereum. As far as Ethereum is concerned, the only downside of a gas-heavy Arbitrum transaction is that it may require an interactive Fraud proof with slightly more steps (and only if indeed it is fraudulent). By contrast, reexecution must impose a _lower_ gas limit than Ethereum, because it must be possible to emulate execution of the transaction (which is more expensive than executing it directly) within a single Ethereum transaction. + +**More implementation flexibility:** Interactive proving allows more flexibility in implementation. All that is necessary is the ability to verify a one-step proof on Ethereum. By contrast, reexecution approaches are tethered to limitations of the EVM. + +### Interactive proving drives the design of Arbitrum + +Much of the design of Arbitrum is driven by the opportunities opened up by interactive proving. If you're reading about some feature of Arbitrum, and you're wondering why it exists, two good questions to ask are: "How does this support interactive proving?" and "How does this take advantage of interactive proving?" The answers to most "why" questions about Arbitrum relate to interactive proving. + +## Arbitrum Rollup Protocol + +Before diving into the Rollup protocol, there are two things we need to cover. + +First, _if you’re an Arbitrum user or developer, you don’t need to understand the Rollup protocol_. You don’t ever need to think about it unless you want to. Your relationship with it can be like a train passenger’s relationship with the train’s engine: you know it exists, and you rely on it to keep working, but you don’t spend your time monitoring it or studying its internals. + +You’re welcome to study, observe, and even participate in the Rollup protocol, but you don’t need to, and most people won’t. So if you’re a typical train passenger who just wants to read or talk to your neighbor, you can skip right to the [next section](#validators) of this document. If not, read on! + +The second thing to understand about the Rollup protocol is that _the protocol doesn’t decide the results of transactions, it only confirms the results_. The results are uniquely determined by the sequence of messages in the chain’s inbox. So once your transaction message is in the chain’s inbox, its result is knowable, and Arbitrum nodes will report that your transaction has been completed. The role of the Rollup protocol is to confirm transaction results that, as far as Arbitrum users are concerned, have already occurred. (This is why Arbitrum users can effectively ignore the Rollup protocol.) + +You might wonder why we need the Rollup protocol. If everyone knows the results of transactions already, why bother confirming them? The Rollup protocol exists for two reasons. First, somebody might lie about a result, and we need a definitive, Trustless way to tell who is lying. Second, Ethereum doesn’t know the results. The whole point of a Layer 2 scaling system is to run transactions without Ethereum needing to do all of the work--and indeed, Arbitrum can go fast enough that Ethereum couldn’t hope to monitor every Arbitrum transaction. However, once the result is confirmed, Ethereum knows about it and can rely on it, enabling operations on Ethereum, such as processing withdrawals of funds from Nitro back to L1. + +With those preliminaries behind us, let’s jump into the details of the Rollup protocol. + +The parties who participate in the protocol are called _validators_. Some validators will choose to be bonders--they will place an ETH deposit which they’ll be able to recover if they’re not caught cheating. In the common case, it's expected that only one validator will be bonded, since as long as it's bonded on the current outcome, and there are no conflicting claims, there's no need for other parties to bond/take any action. The protocol allows for these roles to be permissionless in principle; currently on Arbitrum One, validators/bonders are allowlisted (see ["State of Progressive Decentralization"](https://docs.arbitrum.foundation/state-of-progressive-decentralization)). "Watchtower validators," who monitor the chain but don't take any on-chain actions, can be run permissionlessly (see ["validators"](#validators) below). + +The key security property of the Rollup protocol is that any one honest validator can force the correct execution of the chain to be confirmed. This means that the execution of an Arbitrum chain is as trustless as Ethereum. You, and you alone (or someone you hire), can force your transactions to be processed correctly. And that is true, no matter how many malicious people are trying to stop you. + +### The Rollup Chain + +The Rollup protocol tracks a chain of Rollup blocks---we'll call these "RBlocks" for clarity. They're not the same as Layer 1 Ethereum blocks, and also not the same as Layer 2 Nitro blocks. You can think of the RBlocks as forming a separate chain, which the Arbitrum Rollup Protocol manages and oversees. + +Validators can propose RBlocks. New RBlocks will be _unresolved_ at first. Eventually, every RBlock will be _resolved_, by being either _confirmed_ or _rejected_. The confirmed RBlocks make up the confirmed history of the chain. + +:::note + +Validators and proposers serve different roles. Validators validate transactions to the State Transition Function (STF) and Chain state, whereas proposers can also assert and challenge the chain state. + +::: + +Each RBlock contains: + +- the RBlock number +- the predecessor RBlock number: RBlock number of the last RBlock before this one that is (claimed to be) correct +- the number of L2 blocks that have been created in the chain's history +- the number of inbox messages that have been consumed in the chain’s history +- a hash of the outputs produced over the chain’s history. + +Except for the RBlock number, the contents of the RBlock are all just claims by the RBlock's proposer. Arbitrum doesn’t know at first whether any of these fields are correct. If all of these fields are correct, the protocol should eventually confirm the RBlock. If one or more of these fields are incorrect, the protocol should eventually reject the RBlock. + +An RBlock is implicitly claiming that its predecessor RBlock is correct. This implies, transitively, that an RBlock implicitly claims the correctness of a complete history of the chain: a sequence of ancestor RBlocks that reaches all the way back to the birth of the chain. + +An RBlock is also implicitly claiming that its older siblings (older RBlocks with the same predecessor), if there are any, are incorrect. If two RBlocks are siblings, and the older sibling is correct, then the younger sibling is considered incorrect, even if everything else in the younger sibling is true. + +The RBlock is assigned a deadline, which says how long other validators have to respond to it. If you’re a validator, and you agree that an RBlock is correct, you don’t need to do anything. If you disagree with an RBlock, you can post another RBlock with a different result, and you’ll probably end up in a challenge against the first RBlock's bonder. (More on challenges below.) + +In the normal case, the rollup chain will look like this: + +```mermaid +graph RL + f["First unresolved block"] + l["Latest confirmed block"] + + 98-->97-->96-->95 + f-.-95 + + 95-->94 + l-.-94 + + 94-->93-->92-->91-->90-->x[...] + + subgraph Legend + direction RL + Confirmed + Unconfirmed + end + + classDef confirmed fill:#47b860,stroke:#37914c,stroke-width:2px,color:#fff + class 94,93,92,91,90,x,Confirmed confirmed + + + classDef unconfirmed fill:#2aa1f0,stroke:#1c86ca,stroke-width:2px,color:#fff + class 98,97,96,95,Unconfirmed unconfirmed + + classDef note fill:#F1F5F6,stroke:#dbdede,stroke-width:1px,color:#000 + class l,f note +``` + +On the left, representing an earlier part of the chain’s history, we have confirmed RBlocks. These have been fully accepted and recorded by the Layer 1 contracts that manage the chain. The newest of the confirmed RBlocks, RBlock 94, is called the “latest confirmed RBlock.” On the right, we see a set of newer proposed RBlocks. The protocol can’t yet confirm or reject them, because their deadlines haven’t run out yet. The oldest RBlock whose fate has yet to be determined, RBlock 95, is called the “first unresolved RBlock.” + +Notice that a proposed RBlock can build on an earlier proposed RBlock. This allows validators to continue proposing RBlocks without needing to wait for the protocol to confirm the previous one. Normally, all of the proposed RBlocks will be valid, so they will all eventually be accepted. + +Here’s another example of what the chain state might look like, if several validators are being malicious. It’s a contrived example, designed to illustrate a variety of cases that can come up in the protocol, all smashed into a single scenario. + +```mermaid +graph RL + subgraph Legend + direction RL + Confirmed + Rejected + Unconfirmed + end + + f["First unresolved block"] + l["Latest confirmed block"] + + + l-.-103 + f-.-106 + + 108-->107-->106-->103 + 111-->104 + 101-->100 + 105-->104-->103 + 110-->109-->103-->102-->100-->x[...] + + classDef confirmed fill:#47b860,stroke:#37914c,stroke-width:2px,color:#fff + class 100,102,103,x,Confirmed confirmed + + classDef rejected fill:#fdaa07,stroke:#fd8607,stroke-width:2px,color:#fff + class 101,104,105,Rejected rejected + + classDef unconfirmed fill:#2aa1f0,stroke:#1c86ca,stroke-width:2px,color:#fff + class 106,107,108,109,110,111,Unconfirmed unconfirmed + + classDef note fill:#F1F5F6,stroke:#dbdede,stroke-width:1px,color:#000 + class l,f note + +``` + +There’s a lot going on here, so let’s unpack it. + +- RBlock 100 has been confirmed. +- RBlock 101 claimed to be a correct successor to RBlock 100, but 101 was rejected (hence it is orange). +- RBlock 102 was eventually confirmed as the correct successor to 100. +- RBlock 103 was confirmed and is now the latest confirmed RBlock. +- RBlock 104 was proposed as a successor to RBlock 103, and 105 was proposed as a successor to 104. 104 was rejected as incorrect, and as a consequence 105 was rejected because its predecessor was rejected. +- RBlock 106 is unresolved. It claims to be a correct successor to RBlock 103 but the protocol hasn’t yet decided whether to confirm or reject it. It is the first unresolved RBlock. +- RBlocks 107 and 108 claim to chain from 106. They are also unresolved. If 106 is rejected, they will be automatically rejected too. +- RBlock 109 disagrees with RBlock 106, because they both claim the same predecessor. At least one of them will eventually be rejected, but the protocol hasn’t yet resolved them. +- RBlock 110 claims to follow 109. It is unresolved. If 109 is rejected, 110 will be automatically rejected too. +- RBlock 111 claims to follow 104. 111 will inevitably be rejected because its predecessor has already been rejected. But it hasn’t been rejected yet, because the protocol resolves RBlocks in RBlock number order, so the protocol will have to resolve 106 through 110, in order, before it can resolve 111. After 110 has been resolved, 111 can be rejected immediately. + +Again: this sort of thing is very unlikely in practice. In this diagram, at least four parties must have bonded on wrong RBlocks, and when the dust settles at least four parties will have lost their bonds. The protocol handles these cases correctly, of course, but they’re rare corner cases. This diagram is designed to illustrate the variety of situations that are possible in principle, and how the protocol would deal with them. + +### Staking + +At any given time, some validators will be bonders, and some will not. Bonders deposit funds that are held by the Arbitrum Layer 1 contracts and will be confiscated if the bonder loses a challenge. Nitro chains accept bonds in ETH. + +A single bond can cover a chain of RBlocks. Every bonder is bonded on the latest confirmed RBlock; and if you’re bonded on an RBlock, you can also bond on one successor of that RBlock. So you might be bonded on a sequence of RBlocks that represent a single coherent claim about the correct history of the chain. A single bond suffices to commit you to that sequence of RBlocks. + +In order to create a new RBlock, you must be a bonder, and you must already be bonded on the predecessor of the new RBlock you’re creating. The bond requirement for RBlock creation ensures that anyone who creates a new RBlock has something to lose if that RBlock is eventually rejected. + +The protocol keeps track of the current required bond amount. Normally this will equal the base bond amount, which is a parameter of the Nitro chain. But if the chain has been slow to make progress lately, the required bond will increase, as described in more detail below. + +The rules for staking are as follows: + +- If you’re not bonded, you can bond on the latest confirmed RBlock. When doing this, you deposit the current minimum bond amount. +- If you’re bonded on an RBlock, you can also add your bond to any one successor of that RBlock. (The protocol tracks the maximum RBlock number you’re bonded on, and lets you add your bond to any successor of that RBlock, updating your maximum to that successor.) This doesn’t require you to place a new bond. + - A special case of adding your bond to a successor RBlock is when you create a new RBlock as a successor to an RBlock you’re already bonded on. +- If you’re bonded only on the latest confirmed RBlock (and possibly earlier RBlocks), you or anyone else can ask to have your bond refunded. Your bonded funds will be returned to you, and you will no longer be a bonder. +- If you lose a challenge, your bond is removed from all RBlocks and you forfeit your bonded funds. + +Notice that once you are bonded on an RBlock, there is no way to unbond. You are committed to that RBlock. Eventually one of two things will happen: that RBlock will be confirmed, or you will lose your bond. The only way to get your bond back is to wait until all of the RBlocks you are bonded on are confirmed. + +#### Setting the current minimum bond amount + +One detail we deferred earlier is how the current minimum bond amount is set. Normally, this is just equal to the base bond amount, which is a parameter of the Nitro chain. However, if the chain has been slow to make progress in confirming RBlocks, the bond requirement will escalate temporarily. Specifically, the base bond amount is multiplied by a factor that is exponential in the time since the deadline of the first unresolved RBlock passed. This ensures that if malicious parties are placing false bonds to try to delay progress (despite the fact that they’re losing those bonds), the bond requirement goes up so that the cost of such a delay attack increases exponentially. As RBlock resolution starts advancing again, the bond requirement will go back down. + +### Rules for Confirming or Rejecting RBlocks + +The rules for resolving RBlocks are fairly simple. + +The first unresolved RBlock can be confirmed if: + +- the RBlock's predecessor is the latest confirmed RBlock, and +- the RBlock's deadline has passed, and +- there is at least one bonder, and +- All bonders are bonded to the RBlock. + +The first unresolved RBlock can be rejected if: + +- the RBlock's predecessor has been rejected, or +- all of the following are true: + - the RBlock's deadline has passed, and + - there is at least one bonder, and + - no bonder is bonded on the RBlock. + +A consequence of these rules is that once the first unresolved RBlock's deadline has passed (and assuming there is at least one bonder bonded on something other than the latest confirmed RBlock), the only way the RBlock can be unresolvable is if at least one bonder is bonded on it and at least one bonder is bonded on a different RBlock with the same predecessor. If this happens, the two bonders are disagreeing about which RBlock is correct. It’s time for a challenge, to resolve the disagreement. + +## Delays + +Even if the Assertion Tree has multiple conflicting RBlocks and, say, multiple disputes are in progress, validators can continue making assertions; honest validators will simply build on the one valid RBlock (intuitively: an assertion is also an implicit claim of the validity of all of its parent-assertions.) Likewise, users can continue transacting on L2, since transactions continue to be posted in the chain's inbox. + +The only delay that users experience during a dispute is of their [L2 to L1 messages](/how-arbitrum-works/11-l2-to-l1-messaging.mdx) (i.e., "their withdrawals"). Note that a "delay attacker" who seeks to grief the system by deliberately causing such delays will find this attack quite costly, since each bit of delay-time gained requires the attacker lose another stake. + +## Validators + +Arbitrum full nodes normally "live at Layer 2" which means that they don’t worry about the rollup protocol but simply treat their Arbitrum chain as a mechanism that feeds inbox messages to the State Transition Function to evolve the Layer 2 chain and produce outputs. + +Some Arbitrum nodes will choose to act as _validators_. This means that they watch the progress of the rollup protocol and participate in that protocol to advance the state of the chain securely. + +Not all nodes will choose to do this. Because the Rollup protocol doesn’t decide what the chain will do but merely confirms the correct behavior that is fully determined by the inbox messages, a node can ignore the rollup protocol and simply compute for itself the correct behavior. + +Offchain Labs provides open source validator software, including +a pre-built Docker image. + +Every validator can choose their own approach, but we expect validators to follow three common strategies: + +- The _active validator_ strategy tries to advance the state of the chain by proposing new RBlocks. An Active Validator is always bonded, because creating an RBlock requires being bonded. A chain really only needs one honest active validator; any more is an inefficient use of resources. For the Arbitrum One chain, Offchain Labs runs an active validator. +- The _defensive validator_ strategy watches the rollup protocol operate. If only correct RBlocks are proposed, this strategy doesn't bond. But if an incorrect RBlock is proposed, this strategy intervenes by posting a correct RBlock or staking on a correct RBlock that another party has posted. This strategy avoids staking when things are going well, but if someone is dishonest it bonds in order to defend the correct outcome. +- The _watchtower validator_ strategy never bonds. It simply watches the Rollup protocol, and if an incorrect RBlock is proposed, it raises the alarm (by whatever means it chooses) so that others can intervene. This strategy assumes that other parties who are willing to bond will be willing to intervene in order to take some of the dishonest proposer’s bond and that that can happen before the dishonest RBlock’s deadline expires. (In practice, this will allow several days for a response.) + +Under normal conditions, validators using the defensive and watchtower strategies won’t do anything except observe. A malicious actor who is considering whether to try cheating won’t be able to tell how many defensive and watchtower validators are operating incognito. Perhaps some defensive validators will announce themselves, but others probably won’t, so a would-be attacker will always have to worry that defenders are waiting to emerge. + +The underlying protocol supports permissionless validation, i.e.,--anyone can do it. Currently on Arbitrum One, validators that require bond (i.e., active and defensive validators) are whitelisted; see ["State of Progressive Decentralization"](https://docs.arbitrum.foundation/state-of-progressive-decentralization). + +Who will be validators? Anyone will be able to do it, but most people will choose not to. In practice we expect people to validate a chain for several reasons. + +- Validators could be paid for their work, by the party that created the chain or someone else. A chain could be configured such that a portion of the funds from user transaction fees are paid directly to validators. +- Parties who have significant assets at bond on a chain, such as dApp developers, exchanges, power-users, and liquidity providers, may choose to validate in order to protect their investment. +- Anyone who chooses to validate can do so. Some users will probably choose to validate in order to protect their own interests or just to be good citizens. But ordinary users don’t need to validate, and we expect that the vast majority of users won’t. diff --git a/arbitrum-docs/how-arbitrum-works/07-interactive-fraud-proofs.mdx b/arbitrum-docs/how-arbitrum-works/07-interactive-fraud-proofs.mdx new file mode 100644 index 000000000..7c1b76980 --- /dev/null +++ b/arbitrum-docs/how-arbitrum-works/07-interactive-fraud-proofs.mdx @@ -0,0 +1,435 @@ +--- +title: 'Challenges: Interactive Fraud Proofs' +description: Learn the fundamentals of Arbitrum's Interactive Fraud Proofs and challenges. +author: pete-vielhaber +sme: TucksonDev +user_story: As a current or prospective Arbitrum user, I need to learn more about Interactive Fraud Proofs and challenges. +content_type: get-started +--- + +Suppose the rollup chain looks like this: + +![img](https://lh4.googleusercontent.com/kAZY9H73dqcHvboFDby9nrtbYZrbsHCYtE5X9NIZQsvcz58vV0WUWUq1xsYKzYWQSc1nPZ8W86LLX0lD3y-ctEaG2ISa2Wpz2pYxTzW09P1UvqSDuoqkHlGDYLLMTzLqX4rlP8Ca) + +RBlocks 93 and 95 are siblings (they both have 92 as predecessor). Alice is bonded on 93 and Bob is bonded on 95. + +At this point we know that Alice and Bob disagree about the correctness of RBlock 93, with Alice committed to 93 being correct and Bob committed to 93 being incorrect. (Bob is bonded on 95, and 95 implicitly claims that 92 is the last correct RBlock before it, which implies that 93 must be incorrect.) + +Whenever two bonders are bonded on sibling RBlocks, and neither of those bonders is already in a Challenge, anyone can start a challenge between the two. The rollup protocol will record the challenge and referee it, eventually declaring a winner and confiscating the loser’s bond. The loser will be removed as a bonder. + +The challenge is a game in which Alice and Bob alternate moves, with an Ethereum contract as the referee. Alice, the defender, moves first. + +The game will operate in two phases: Dissection, followed by one-step proof. Dissection will narrow down the size of the dispute until it is a dispute about just one instruction of execution. Then the one-step proof will determine who is right about that one instruction. + +We’ll describe the dissection part of the protocol twice. First, we’ll give a simplified version which is easier to understand but less efficient. Then we’ll describe how the real version differs from the simplified one. + +## Dissection Protocol: Simplified Version + +Alice is defending the claim that starting with the state in the predecessor RBlock, the state of the Virtual Machine can advance to the state specified in RBlock A. Essentially she is claiming that the Virtual Machine can execute N instructions, and that that execution will consume M inbox messages and transform the hash of outputs from H’ to H. + +Alice’s first move requires her to dissect her claims about intermediate states between the beginning (0 instructions executed) and the end (N instructions executed). So we require Alice to divide her claim in half, and post the state at the half-way point, after N/2 instructions have been executed. + +Now Alice has effectively bisected her N-step Assertion into two (N/2)-step assertions. Bob has to point to one of those two half-size assertions and claim it is wrong. + +At this point we’re effectively back in the original situation: Alice having made an assertion that Bob disagrees with. But we have cut the size of the assertion in half, from N to N/2. We can apply the same method again, with Alice bisecting and Bob choosing one of the halves, to reduce the size to N/4. And we can continue bisecting, so that after a logarithmic number of rounds Alice and Bob will be disagreeing about a single step of execution. That’s where the dissection phase of the protocol ends, and Alice must make a one-step proof which will be checked by the EthBridge. + +## Why Dissection Correctly Identifies a Cheater + +Before talking about the complexities of the real Challenge protocol, let’s stop to understand why the simplified version of the protocol is correct. Here correctness means two things: (1) if Alice’s initial claim is correct, Alice can always win the challenge, and (2) if Alice’s initial claim is incorrect, Bob can always win the challenge. + +To prove (1), observe that if Alice’s initial claim is correct, she can offer a truthful midpoint claim, and both of the implied half-size claims will be correct. So whichever half Bob objects to, Alice will again be in the position of defending a correct claim. At each stage of the protocol, Alice will be defending a correct claim. At the end, Alice will have a correct one-step claim to prove, so that claim will be provable and Alice can win the challenge. + +To prove (2), observe that if Alice’s initial claim is incorrect, this can only be because her claimed endpoint after N steps is incorrect. Now when Alice offers her midpoint state claim, that midpoint claim is either correct or incorrect. If it’s incorrect, then Bob can challenge Alice’s first-half claim, which will be incorrect. If Alice’s midpoint state claim is correct, then her second-half claim must be incorrect, so Bob can challenge that. So whatever Alice does, Bob will be able to challenge an incorrect half-size claim. At each stage of the protocol, Bob can identify an incorrect claim to challenge. At the end, Alice will have an incorrect one-step claim to prove, which she will be unable to do, so Bob can win the challenge. + +(If you’re a stickler for mathematical precision, it should be clear how these arguments can be turned into proofs by induction on N.) + +## The Real Dissection Protocol + +The real dissection protocol is conceptually similar to the simplified one described above, but with several changes that improve efficiency or deal with necessary corner cases. Here is a list of the differences. + +**Dissection over L2 blocks, then over instructions:** Alice's assertion is over an RBlock, which asserts the result of creating some number of Layer 2 Nitro blocks. Dissection first occurs over these Layer 2 blocks, to narrow the dispute down to a dispute about a single Layer 2 Nitro block. At this point, the dispute transforms into a dispute about a single execution of the State Transition Function or in other words about the execution of a sequence of WAVM instructions. The protocol then executes the recursive dissection sub-protocol again, this time over WAVM instructions, to narrow the dispute to a single instruction. The dispute concludes with a one-step proof of a single instruction (or a party failing to act and losing by timeout). + +**K-way dissection:** Rather than dividing a claim into two segments of size N/2, we divide it into K segments of size N/K. This requires posting K-1 intermediate claims, at points evenly spaced through the claimed execution. This reduces the number of rounds by a factor of log(K)/log(2). + +**Answer a dissection with a dissection:** Rather than having each round of the protocol require two moves, where Alice dissects and Bob chooses a segment to challenge, we instead require Bob, in challenging a segment, to post his own claimed endpoint state for that segment (which must differ from Alice’s) as well as his own dissection of his version of the segment. Alice will then respond by identifying a subsegment, posting an alternative endpoint for that segment, and dissecting it. This reduces the number of moves in the game by an additional factor of 2, because the size is cut by a factor of K for every move, rather than for every two moves. + +**Deal With the Empty-Inbox Case**: The real AVM can’t always execute N units of gas without getting stuck. The machine might halt, or it might have to wait because its inbox is exhausted so it can’t go on until more messages arrive. So Bob must be allowed to respond to Alice’s claim of N units of execution by claiming that N steps are not possible. The real protocol thus allows any response (but not the initial claim) to claim a special end state that means essentially that the specified amount of execution is not possible under the current conditions. + +**Time Limits:** Each player is given a time allowance. The total time a player uses for all of their moves must be less than the time allowance, or they lose the game. Think of the time allowance as being about a week. + +It should be clear that these changes don’t affect the basic correctness of the challenge protocol. They do, however, improve its efficiency and enable it to handle all of the cases that can come up in practice. + +## Efficiency + +The challenge protocol is designed so that the dispute can be resolved with a minimum of work required by the protocol (via its Layer 1 Ethereum contracts) in its role as referee. When it is Alice’s move, the protocol only needs to keep track of the time Alice uses, and ensure that her move does include K-1 intermediate points as required. The protocol doesn’t need to pay attention to whether those claims are correct in any way; it only needs to know whether Alice’s move “has the right shape”. + +The only point where the protocol needs to evaluate a move “on the merits” is at the one-step proof, where it needs to look at Alice’s proof and determine whether the proof that was provided does indeed establish that the virtual machine moves from the before state to the claimed after state after one step of computation. + +import ChallengeManagerDiagram from '../diagrams/_challenge-manager.mdx'; + +## ChallengeManager + +This section is a technical deep dive into the `ChallengeManager` and will walk through the arbitration of a challenge game in great detail. The `ChallengeManager` plays the role of the arbiter of challenge games. Here's a diagram of the challenge state machine: + + + +### Block challenge + +The challenge begins by bisecting over global states (including block hashes). +Before actual machine execution is disputed, the dispute is narrowed down to an individual block. +Once the challenge has been bisected down to an individual block, +`challengeExecution` can be called by the current responder. +This operates similarly to a bisection in that the responder must provide a competing global state and machine state, +but it uses that information to transition to the execution challenge phase. + +### Execution challenge + +Once narrowed down to an individual block, the actual machine execution can be bisected. +Once the execution has been bisected down to an individual step, +`oneStepProveExecution` can be called by the current responder. +The current responder must provide proof data to execute a step of the machine. +If executing that step ends in a different state than was previously asserted, +the current responder wins the challenge. + +### General bisection protocol + +_**Note:** the term bisection in this document is used for clarity but refers to a dissection of any degree._ + +The `ChallengeLib` helper library contains a `hashChallengeState` method which hashes a list of segment hashes, +a start position, and a total segments length, which generates the `ChallengeLib.Challenge`'s `challengeStateHash`. +This is enough information to infer the position of each segment hash. +The challenge "degree" refers to the number of segment hashes minus one. +The distance (in steps) between one segment and the next is `floor(segmentsLength / degree)`, except for the +last pair of segments, where `segmentsLength % degree` is added to the normal distance, so that +the total distance is `segmentsLength`. + +A challenge begins with only two segments (a degree of one), which is the asserter's initial assertion. +Then, the bisection game begins on the challenger's turn. +In each round of the game, the current responder must choose an adjacent pair of segments to challenge. +By doing so, they are disputing their opponent's claim that starting with the first segment and executing +for the specified distance (number of steps) will result in the second segment. At this point the two parties +agree on the correctness of the first segment but disagree about the correctness of the second segment. +The responder must provide a bisection with a start segment equal to the first segment, but an end segment +different from the second segment. +In doing so, they break the challenge down into smaller distances, and it becomes their opponent's turn. +Each bisection must have degree `min(40, numStepsInChallengedSegment)`, ensuring the challenge makes progress. + +In addition, a segment with a length of only one step cannot be bisected. +What happens there is specific to the phase of the challenge, as either a `challengeExecution` or `oneStepProveExecution`. + +Note that unlike in a traditional bisection protocol, where one party proposes segments and the other decides which to challenge, +this protocol is symmetric in that both players take turns deciding where to challenge and proposing bisections +when challenging. + +### Winning the challenge + +Note that for the time being, winning the challenge isn't instant. +Instead, it simply makes the current responder the winner's opponent, +and sets the state hash to 0. In that state the party does not have any +valid moves, so it will eventually lose by timeout. +This is done as a precaution, so that if a challenge is resolved incorrectly, +there is time to diagnose and fix the error with a contract upgrade. + +## One Step Proof Assumptions + +The One Step Proof (OSP) implementation makes certain assumptions about the cases that can arise +in a correct execution. This documents those assumptions about what's being executed. + +If a case is "unreachable", that is, the case is assumed to never arise in correct execution, +then the OSP can implement any instruction semantics in that case. + +- In a challenge between malicious parties, any case can arise. The challenge protocol must do + something safe in every case. But the instruction semantics can be weird in such cases because + if both parties to a challenge are malicious, the protocol doesn't care who wins the challenge. +- In a challenge with one honest party, the honest party will never need to one-step prove an + unreachable case. The honest party will only assert correct executions, so it will only have to + prove reachable cases. +- In a challenge with one honest party, the dishonest party could assert an execution that transitions + into an unreachable case, but such an execution must include an invalid execution of a reachable case + earlier in the assertion. Because a challenge involving an honest party will eventually require an OSP + over the first instruction where the parties disagree, the eventual OSP will be over the earlier point + of divergence, and not over the later execution from an unreachable case. + +In general, some unreachable cases will be detectable by the OSP checker and some will not. For safety, the +detectable unreachable cases should be defined by transition the machine into an error state, allowing +governance to eventually push an upgrade to recover from the error. An undetectable unreachable case, if +such a case were reached in correct execution, could lead to a security failure. + +The following assumptions, together, must prevent an unreachable case from arising in correct execution. + +### The WAVM code is generated by Arbitrator from valid WASM + +WAVM is the name of the custom instruction set similar to WASM used for proving. +Arbitrator transpiles WASM code into WAVM. +It also invokes wasm-validate from [wabt](https://github.com/WebAssembly/wabt) +(the WebAssembly Binary Toolkit) to ensure the input WASM is valid. +WAVM produced otherwise may not be executable, as it may try to close a non-existent block, +mismatch types, or do any other number of invalid things which are prevented by WASM validation. + +WAVM code generated from by Arbitrator from valid WASM is assumed to never encounter an unreachable case. + +### Inbox messages must not be too large + +The current method of inbox hashing requires the full inbox message be available for proving. +That message must not be too large as to prevent it from being supplied for proving, +which is enforced by the inboxes. + +The current length limit is 117,964 bytes, which is 90% of the +[max transaction size Geth will accept](https://github.com/ethereum/go-ethereum/blob/356bbe343a30789e77bb38f25983c8f2f2bfbb47/core/tx_pool.go#L53), +leaving 13,108 bytes for other proving data. + +### Requested preimages must be known and not too large + +WAVM has an opcode which resolves the preimage of a Keccak-256 hash. +This can only be executed if the preimage is already known to all nodes, +and can only be proven if the preimage isn't too long. Violations of this assumption are +undetectable by the OSP checker. + +The current length limit is 117,964 bytes for the reasons mentioned above. +Here's a list of which preimages may be requested by Nitro, and why they're known to all parties, +and not too large: + +#### Block headers + +Nitro may request up to the last 256 L2 Block headers. +The last block header is required to determine the current state, +and blocks before it are required to implement the `BLOCKHASH` evm instruction. + +This is safe as previous block headers are a fixed size, and are known to all nodes. + +#### State trie access + +To resolve state, Nitro traverses the state trie by resolving preimages. + +This is safe as validators retain archive state of unconfirmed blocks, +each trie branch is of a fixed size, +and the only variable sized entry in the trie is contract code, +which is limited by EIP-170 to about 24KB. + +## WASM to WAVM + +Not all WASM instructions are 1:1 with WAVM opcodes. +This document lists those which are not, and explains how they're expressed in WAVM. +Many of the WAVM representations use opcodes not in WASM, +which are documented in [`wavm-custom-opcodes`](#wavm-custom-opcodes-not-in-wasm). + +### `block` and `loop` + +In WASM, a block contains instructions. +Branch instructions exit a fixed number of blocks, jumping to their destination. +A normal `block`'s destination is the end of the block, whereas a `loop`'s destination is the start of the loop. + +In WAVM, instructions are flat. +At transpilation time, any branch instructions are replaced with jumps to the corresponding block's destination. +This means that WAVM interpreters don't need to track blocks, and thus block instructions are unnecessary. + +### `if` and `else` + +These are translated to a block with an `ArbitraryJumpIf` as follows: + +``` +begin block with endpoint end + conditional jump to else + [instructions inside if statement] + branch + else: [instructions inside else statement] +end +``` + +### `br` and `br_if` + +`br` and `br_if` are translated into `ArbitraryJump` and `ArbitraryJumpIf` respectively. +The jump locations can be known at transpilation time, making blocks obsolete. + +### `br_table` + +`br_table` is translated to a check for each possible branch in the table, +and then if none of the checks hit, a branch of the default level. + +Each of the non-default branches has a conditional jump to a section afterwards, +containing a `drop` for the selector, and then a jump to the target branch. + +### `local.tee` + +`local.tee` is translated to a WAVM `Dup` and then a `LocalSet`. + +### `return` + +To translate a return, the number of return values must be known from the function signature. +A WAVM `MoveFromStackToInternal` is added for each return value. +Then, a loop checks `IsStackBoundary` (which implicitly pops a value) until it's true and the stack boundary has been popped. +Next, a `MoveFromInternalToStack` is added for each return value to put the return values back on the stack. +Finally, a WAVM `Return` is added, returning control flow to the caller. + +### Floating point instructions + +A floating point library module must be present to translate floating point instructions. +They are translated by bitcasting `f32` and `f64` arguments to `i32`s and `i64`s, +then a cross module call to the floating point library, +and finally bitcasts of any return values from `i32`s and `i64`s to `f32`s and `f64`s. + +## WAVM Custom opcodes not in WASM + +In addition to the MVP WASM specification, +WAVM implements the multi value and sign extension ops WASM proposals. + +WAVM also implements the following unique opcodes, +which are not part of WASM nor any WASM proposal. + +### Invariants + +Many of these opcodes have implicit invariants about what's on the stack, +e.g. "Pops an i32 from the stack" assumes that the top of the stack has an i32. +If these conditions are not satisfied, execution is generally not possible. +These invariants are maintained by WASM validation and Arbitrator codegen. (See [One Step Proof Assumptions](#one-step-proof-assumptions).) + +### Codegen internal + +These are generated when breaking down a WASM instruction that does many things into many WAVM instructions which each do one thing. +For instance, a WASM `local.tee` is implemented in WAVM with `dup` and then `local.set`, the former of which doesn't exist in WASM. + +Other times, these opcodes help out an existing WASM opcode by splitting out functionality. +For instance, the WAVM `return` opcode by itself does not clean up the stack, +but its WASM->WAVM codegen includes a loop that utilizes `IsStackBoundary` to perform the stack cleanup +specified for WASM's `return`. + +| Opcode | Name | Description | +| ------ | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0x8000 | EndBlock | Pops an item from the block stack. | +| 0x8001 | EndBlockIf | Peeks the top value on the stack, assumed an i32. If non-zero, pops an item from the block stack. | +| 0x8002 | InitFrame | Pops a caller module index i32, then a caller module internals offset i32, and finally a return InternalRef from the stack. Creates a stack frame with the popped info and the locals merkle root in proving argument data. | +| 0x8003 | ArbitraryJumpIf | Pops an i32 from the stack. If non-zero, jumps to the program counter in the argument data. | +| 0x8004 | PushStackBoundary | Pushes a stack boundary to the stack. | +| 0x8005 | MoveFromStackToInternal | Pops an item from the stack and pushes it to the internal stack. | +| 0x8006 | MoveFromInternalToStack | Pops an item from the internal stack and pushes it to the stack. | +| 0x8007 | IsStackBoundary | Pops an item from the stack. If a stack boundary, pushes an i32 with value 1. Otherwise, pushes an i32 with value 0. | +| 0x8008 | Dup | Peeks an item from the stack and pushes another copy of that item to the stack. | + +The above opcodes eliminate the need for the following WASM opcodes (which are transpiled into other WAVM opcodes): + +- loop +- if/else +- br_table +- local.tee + +### Linking + +This is only generated to link modules together. +Each import is replaced with a local function consisting primarily of this opcode, +which handles the actual work needed to change modules. + +| Opcode | Name | Description | +| ------ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0x8009 | CrossModuleCall | Pushes the current program counter, module number, and module's internals offset to the stack. Then splits its argument data into the lower 32 bits being a function index, and the upper 32 bits being a module index, and jumps to the beginning of that function. | + +### Host calls + +These are only used in the implementation of "host calls". +Each of these has an equivalent host call method, which can be invoked from libraries. +The exception is `CallerModuleInternalCall`, +which is used for the implementation of all of the `wavm_caller_*` host calls. +Those calls are documented in `wavm-modules.mdx`. + +For these instruction descriptions, all pointers and offsets are represented as WASM i32s. + +| Opcode | Name | Description | +| ------ | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 0x800A | CallerModuleInternalCall | Pushes the current program counter, module number, and module's internals offset (all i32s) to the stack. Then, it retrieves the caller module internals offset from the current stack frame. If 0, errors, otherwise, jumps to the caller module at function (internals offset + opcode argument data) and instruction 0. | +| 0x8010 | GetGlobalStateBytes32 | Pops a pointer and then an index from the stack. If the index is greater than or equal to the number of global state bytes32s, errors. If the pointer mod 32 is not zero, errors. If the pointer + 32 is outside the programs memory, errors. Otherwise, writes the global state bytes32 value of the specified index to the specified pointer in memory. | +| 0x8011 | SetGlobalStateBytes32 | Pops a pointer and then an index from the stack. If the index is greater than or equal to the number of global state bytes32s, errors. If the pointer mod 32 is not zero, errors. If the pointer + 32 is outside the programs memory, errors. Otherwise, reads a bytes32 from the specified pointer in memory and sets the global state bytes32 value of the specified index to it. | +| 0x8012 | GetGlobalStateU64 | Pops a pointer and then an index from the stack. If the index is greater than or equal to the number of global state u64s, errors. If the pointer mod 32 is not zero, errors. If the pointer + 8 is outside the programs memory, errors. Otherwise, writes the global state u32 value of the specified index to the specified pointer in memory. | +| 0x8013 | SetGlobalStateU64 | Pops a pointer and then an index from the stack. If the index is greater than or equal to the number of global state u64s, errors. If the pointer mod 32 is not zero, errors. If the pointer + 8 is outside the programs memory, errors. Otherwise, reads a u64 from the specified pointer in memory and sets the global state u64 value of the specified index to it. | +| 0x8020 | ReadPreImage | Pops an offset and then a pointer from the stack. If the pointer mod 32 is not zero, errors. If the pointer + 32 is outside the programs memory, errors. Reads a 32 byte Keccak-256 hash from the specified pointer in memory. Writes up to 32 bytes of the preimage to that hash, beginning with the `offset` byte of the preimage. If `offset` is greater than or equal to the number of bytes in the preimage, writes nothing. Pushes the number of bytes written to the stack as an i32. | +| 0x8021 | ReadInboxMessage | Pops an offset, then a pointer, and then an i64 message number from the stack. If the pointer mod 32 is not zero, errors. If the pointer + 32 is outside the programs memory, errors. Attempts to read an inbox message from the inbox identifier contained in the argument data (0 for the Sequencer inbox, 1 for the Delayed Inbox) at the specified message number. If this exceeds the machine's inbox limit, enters the "too far" state. Otherwise, writes up to 32 bytes of the specified inbox message, beginning with the `offset` byte of the message. If `offset` is greater than or equal to the number of bytes in the preimage, writes nothing. Pushes the number of bytes written to the stack as an i32. | +| 0x8022 | HaltAndSetFinished | Sets the machine status to finished, halting execution and marking it as a success. | + +## WAVM Floating point implementation + +Implementing correct, consistent, and deterministic floating point operations directly in WAVM +(meaning both a Rust Arbitrator implementation and Solidity OSP implementation) +would be an extremely tricky endeavor. +WASM specifies floating point operations as being compliant to IEEE 754-2019, +which is not deterministic, and full of edge cases. + +Instead, floating point operations (apart from trivial bit-casts like i32 \<-\> f32) +are implemented using the C Berkeley SoftFloat-3e library running inside WAVM. +Arbitrator links other WAVM guests against this, +by replacing float point operations with cross module calls to the library. + +Berkeley SoftFloat does not implement all necessary floating point operations, however. +Most importantly, it does not provide a min function, despite IEEE 754-2019 specifying one. +The implementation of these operations, +along with the export of convenient APIs for WASM opcode implementations, +are contained in bindings32.c for 32 bit integers and bindings64.c for 64 bit integers. + +This ensures that floating point operations are deterministic and consistent between Arbitrator and the OSP, +as they are implemented exclusively using operations already known to be deterministic and consistent. +However, it does not ensure that the floating point operations are perfectly compliant to the WASM specification. +Go uses floating points in its JS\<-\>Go WASM interface, +and floating points may be used outside core state transition code for imprecise computations, +but the former is well exercised as used in Nitro, +and the latter generally doesn't rely on details like the minimum of NaN and infinity. + +### Known divergences from the WASM specification + +Floating point to integer truncation will saturate on overflow, instead of erroring. +This is generally safer, because on x86, overflowing simply produces an undefined result. +A WASM proposal exists to add new opcodes which are defined to saturate, but it's not widely adopted. + +## WAVM Modules + +WASM natively has a notion of modules. +Normally, in WASM, a module is the entire program. +A `.wasm` file represents one module, and generally they aren't combined. +An exception to this is C compiled via Clang, where wasm files are also used as object files, +but [its linking scheme](https://github.com/WebAssembly/tool-conventions/blob/main/Linking.mdx) is not supported in other languages. + +In WAVM this is extended to make the executing program composed of multiple modules. +These may call each other, and library modules may write to their caller's memory to return results. + +### The entrypoint module + +The entrypoint module is where execution begins. +It calls modules' `start` functions if specified, +and then calls the main module's main function, which is language specific. +For Go it sets argv to `["js"]` to match the JS environment, and calls `run`. +For Rust it calls `main` with no arguments. + +### Library exports + +Libraries may export functions with the name pattern `module__name`, +which future libraries or the main module can import as `"module" "name"`. + +For instance, this is used for wasi-stub to provide functions rust imports according +to the WebAssembly System Interface. + +### Floating point operations + +To provide floating point operations for future libraries, +the soft float library exports functions which perform floating point ops. +These have the same name as the WASM instruction names, except `.` is replaced with `_`. +Their type signature is also the same, except all `f32`s and `f64`s are bitcasted to `i32`s and `i64`s. + +Future modules can implicitly use these by using WASM floating point operations, +which are replaced at the WASM->WAVM level with bitcasts and cross module calls to these functions. + +### WAVM guest calls + +Libraries may call the main module's exports via `"env" "wavm_guest_call__*"`. + +For instance, go-stub calls Go's resume function when queueing async events +via `wavm_guest_call_resume()`, and then retrieves the new stack pointer with +`wavm_guest_call_getsp()`. + +### Caller module internals call + +Every stack frame retains its caller module and its caller module's "internals offset", +which is the first internal function index. +WAVM appends 4 "internal" functions to each module, which perform a memory load or store of 1 or 4 bytes. + +Via `wavm_caller_{load,store}{8,32}`, a library may access its caller's memory, +which is implemented by calling these internal functions of the caller's module. +Only libraries can access their caller's memory; the main module cannot. + +For instance, this is used to read arguments from and write return values to the Go stack, +when Go calls into go-stub. diff --git a/arbitrum-docs/how-arbitrum-works/inside-anytrust.md b/arbitrum-docs/how-arbitrum-works/08-anytrust-protocol.mdx similarity index 62% rename from arbitrum-docs/how-arbitrum-works/inside-anytrust.md rename to arbitrum-docs/how-arbitrum-works/08-anytrust-protocol.mdx index c490cdcc2..24799e8f9 100644 --- a/arbitrum-docs/how-arbitrum-works/inside-anytrust.md +++ b/arbitrum-docs/how-arbitrum-works/08-anytrust-protocol.mdx @@ -1,20 +1,23 @@ --- -author: dzgoldman +title: AnyTrust Protocol +description: 'Learn the fundamentals of the Arbitrum AnyTrust protocol.' +author: pete-vielhaber +sme: TucksonDev +user_story: As a current or prospective Arbitrum user, I need to learn more about AnyTrust. +content_type: get-started --- -# Inside AnyTrust +AnyTrust is a variant of Arbitrum Nitro technology that lowers costs by accepting a mild trust assumption. -AnyTrust is a variant of Arbitrum Nitro technology that lowers costs by accepting a mild trust assumption. +The Arbitrum protocol requires that all Arbitrum nodes, including validators (nodes that verify correctness of the chain and are prepared to stake on correct results), have access to the data of every L2 Transaction in the Arbitrum chain's inbox. An Arbitrum rollup provides data access by posting the data (in batched, compressed form) on L1 Ethereum as calldata. The Ethereum gas to pay for this is the largest component of cost in Arbitrum. -The Arbitrum protocol requires that all Arbitrum nodes, including validators (nodes that verify correctness of the chain and are prepared to stake on correct results), have access to the data of every L2 transaction in the Arbitrum chain's inbox. An Arbitrum rollup provides data access by posting the data (in batched, compressed form) on L1 Ethereum as calldata. The Ethereum gas to pay for this is the largest component of cost in Arbitrum. - -AnyTrust relies instead on an external Data Availability Committee (hereafter, "the Committee") to store data and provide it on demand. The Committee has N members, of which AnyTrust assumes at least two are honest. This means that if N - 1 Committee members promise to provide access to some data, at least one of the promising parties must be honest. Since there are two honest members, and only one failed to make the promise, it follows that at least one of the promisers must be honest — and that honest member will provide data when it is needed to ensure the chain can properly function. +AnyTrust relies instead on an external Data Availability Committee (hereafter, "the Committee") to store data and provide it on demand. The Committee has `N` members, of which AnyTrust assumes at least two are honest. This means that if `N - 1` Committee members promise to provide access to some data, at least one of the promising parties must be honest. Since there are two honest members, and only one failed to make the promise, it follows that at least one of the promisers must be honest — and that honest member will provide data when it is needed to ensure the chain can properly function. ## Keysets -A Keyset specifies the public keys of Committee members and the number of signatures required for a Data Availability Certificate to be valid. Keysets make Committee membership changes possible and provide Committee members the ability to change their keys. +A Keyset specifies the BLS public keys of Committee members and the number of signatures required for a Data Availability Certificate to be valid. Keysets make Committee membership changes possible and provide Committee members the ability to change their keys. -A Keyset contains +A Keyset contains: - the number of Committee members, and - for each Committee member, a BLS public key, and @@ -37,9 +40,9 @@ A central concept in AnyTrust is the Data Availability Certificate (hereafter, a - a bitmap saying which Committee members signed, and - a BLS aggregated signature (over the BLS12-381 curve) proving that those parties signed. -Because of the 2-of-N trust assumption, a DACert constitutes proof that the block's data (i.e., the preimage of the hash in the DACert) will be available from at least one honest Committee member, at least until the expiration time. +Because of the `2-of-N` trust assumption, a DACert constitutes proof that the block's data (i.e., the preimage of the hash in the DACert) will be available from at least one honest Committee member, at least until the expiration time. -In ordinary (non-AnyTrust) Nitro, the Arbitrum sequencer posts data blocks on the L1 chain as calldata. The hashes of the data blocks are committed by the L1 Inbox contract, allowing the data to be reliably read by L2 code. +In ordinary (non-AnyTrust) Nitro, the Arbitrum Sequencer posts data blocks on the L1 chain as calldata. The hashes of the data blocks are committed by the L1 Inbox contract, allowing the data to be reliably read by L2 code. AnyTrust gives the sequencer two ways to post a data block on L1: it can post the full data as above, or it can post a DACert proving availability of the data. The L1 inbox contract will reject any DACert that uses an invalid Keyset; the other aspects of DACert validity are checked by L2 code. @@ -64,7 +67,7 @@ The DAS software, based on configuration options, can store its data in local fi ## Sequencer-Committee Interaction -When the Arbitrum sequencer produces a data batch that it wants to post using the Committee, it sends the batch's data, along with an expiration time (normally three weeks in the future) via RPC to all Committee members in parallel. Each Committee member stores the data in its backing store, indexed by the data's hash. Then the member signs the (hash, expiration time) pair using its BLS key, and returns the signature with a success indicator to the sequencer. +When the Arbitrum sequencer produces a data Batch that it wants to post using the Committee, it sends the batch's data, along with an expiration time (normally three weeks in the future) via RPC to all Committee members in parallel. Each Committee member stores the data in its backing store, indexed by the data's hash. Then the member signs the (hash, expiration time) pair using its BLS key, and returns the signature with a success indicator to the sequencer. Once the Sequencer has collected enough signatures, it can aggregate the signatures and create a valid DACert for the (hash, expiration time) pair. The Sequencer then posts that DACert to the L1 inbox contract, making it available to the AnyTrust chain software at L2. diff --git a/arbitrum-docs/how-arbitrum-works/09-gas-fees.mdx b/arbitrum-docs/how-arbitrum-works/09-gas-fees.mdx new file mode 100644 index 000000000..a8a0137dc --- /dev/null +++ b/arbitrum-docs/how-arbitrum-works/09-gas-fees.mdx @@ -0,0 +1,134 @@ +--- +title: Gas and Fees +description: 'Learn the fundamentals of how to calculate fees on Arbitrum.' +author: pete-vielhaber +sme: TucksonDev +user_story: As a current or prospective Arbitrum user, I need to learn more about gas/fee calculations on Arbitrum. +content_type: get-started +--- + +Gas is used by Arbitrum to track the cost of execution on a Nitro chain. It works the same as Ethereum gas, in the sense that every EVM instruction costs the same amount of gas that it would on Ethereum. + +There are two parties a user pays when submitting a tx: + +- the poster, if reimbursable, for L1 resources such as the L1 calldata needed to post the tx +- the network fee account for L2 resources, which include the computation, storage, and other burdens L2 nodes must bear to service the tx + +The L1 component is the product of the Transaction's estimated contribution to its Batch's size — computed using Brotli on the transaction by itself — and the L2's view of the L1 data price, a value which dynamically adjusts over time to ensure the batch-poster is ultimately fairly compensated. + +The L2 component consists of the traditional fees Geth would pay to stakers in a vanilla L1 chain, such as the computation and storage charges applying the State Transition Function entails. ArbOS charges additional fees for executing its L2-specific [precompiles](/build-decentralized-apps/precompiles/01-overview.mdx), whose fees are dynamically priced according to the specific resources used while executing the call. + +The following sections will detail how to calculate L1 and L2 fees. If you do not need precise calculations or a technical understanding, skip to the next section, [L1 to L2 messaging](/how-arbitrum-works/10-l1-to-l2-messaging.mdx). + +## L1 gas pricing + +ArbOS dynamically prices L1 gas, with the price adjusting to ensure that the amount collected in L1 gas fees is as close as possible to the costs that must be covered, over time. + +### L1 costs + +There are two types of L1 costs: batch posting costs, and rewards. + +Batch posting costs reflect the actual cost a batch poster pays to post batch data on L1. Whenever a batch is posted, the L1 contract that records the batch will send a special "batch posting report" message to L2 ArbOS, reporting who paid for the batch and what the L1 basefee was at the time. This message is placed in the chain's Delayed Inbox, so it will be delivered to L2 ArbOS after some delay. + +When a batch posting report message arrives at L2, ArbOS computes the cost of the referenced batch by multiplying the reported basefee by the batch's data cost. (ArbOS retrieves the batch's data from its inbox state, and computes the L1 gas that the batch would have used by counting the number of zero bytes and non-zero bytes in the batch.) The resulting cost is recorded by the pricer as funds due to the party who is reported to have submitted the batch. + +The second type of L1 cost is an optional (per chain) per-unit reward for handling transaction calldata. In general the reward might be paid to the Sequencer, or to members of the Data Availability Committee in an AnyTrust chain, or to anyone else who incurs per-calldata-byte costs on behalf of the chain. The reward is a fixed number of wei per data unit, and is paid to a single address. + +The L1 pricer keeps track of the funds due to the reward address, based on the number of data units handled so far. This amount is updated whenever a batch posting report arrives at L2. + +### L1 calldata fees + +L1 calldata fees exist because the Sequencer, or the batch poster which posts the Sequencer's transaction batches on Ethereum, incurs costs in L1 gas to post transactions on Ethereum as calldata. Funds collected in L1 calldata fees are credited to the batch poster to cover its costs. + +Every transaction that comes in through the Sequencer will pay an L1 calldata fee. Transactions that come in through the delayed inbox do not pay this fee because they don't add to batch posting costs--but these transactions pay gas fees to Ethereum when they are put into the delayed inbox. + +The L1 pricing algorithm assigns an L1 calldata fee to each Sequencer transaction. First, it computes the transaction's size, which is an estimate of how many bytes the transaction will add to the compressed batch it is in; the formula for this includes an estimate of how compressible the transaction is. Second, it multiplies the computed size estimate by the current price per estimated byte, to determine the transaction's L1 calldata wei, in wei. Finally, it divides this cost by the current L2 basefee to translate the fee into L2 gas units. The result is reported as the "poster fee" for the transaction. + +The price per estimated byte is set by a dynamic algorithm that compares the total L1 calldata fees collected to the total fees actually paid by batch posters, and tries to bring the two as close to equality as possible. If the batch posters' costs have been less than fee receipts, the price will increase, and if batch poster costs have exceeded fee receipts, the price will decrease. + +### L1 fee collection + +A transaction is charged for L1 gas if and only if it arrived as part of a sequencer batch. This means that someone would have paid for L1 gas to post the transaction on the L1 chain. + +The estimated cost of posting a transaction on L1 is the product of the transaction's estimated size, and the current L1 Gas Basefee. This estimated cost is divided by the current L2 gas basefee to obtain the amount of L2 gas that corresponds to the L1 operation (more information about this can be found in [this article][two_dimensional_fees_medium_article_link]). + +The estimated size is measured in L1 gas and is calculated as follows: first, compress the transaction's data using the brotli-zero algorithm, then multiply the size of the result by 16. (16 is because L1 charges 16 gas per byte. L1 charges less for bytes that are zero, but that doesn't make sense here.) Brotli-zero is used in order to reward users for posting transactions that are compressible. Ideally we would like to reward for posting transactions that contribute to the compressibility (using the brotli compressor) of the entire batch, but that is a difficult notion to define and in any case would be too expensive to compute at L2. Brotli-zero is an approximation that is cheap enough to compute. + +L1 gas fee funds that are collected from transactions are transferred to a special [`L1PricerFundsPool`][l1pricerfundspool_link] account, so that account's balance represents the amount of funds that have been collected and are available to pay for costs. + +The L1 pricer also records the total number of "data units" (the sum of the estimated sizes, after multiplying by 16) that have been received. + +[l1pricerfundspool_link]: https://github.com/OffchainLabs/nitro/blob/3f4939df1990320310e7f39e8abb32d5c4d8045f/arbos/l1pricing/l1pricing.go#L46 +[two_dimensional_fees_medium_article_link]: https://medium.com/offchainlabs/understanding-arbitrum-2-dimensional-fees-fd1d582596c9 + +## L2 gas pricing + +The L2 gas price on a given Arbitrum chain has a set floor, which can be queried via [ArbGasInfo](/build-decentralized-apps/precompiles/02-reference.mdx#arbgasinfo)'s `getMinimumGasPrice` method (currently @arbOneGasFloorGwei@ gwei on Arbitrum One and @novaGasFloorGwei@ gwei on Nova). + +### Estimating L2 Gas + +Calling an Arbitrum Node's `eth_estimateGas` RPC gives a value sufficient to cover the full transaction fee at the given L2 gas price; i.e., the value returned from `eth_estimateGas` multiplied by the L2 gas price tells you how much total Ether is required for the transaction to succeed. Note that this means that for a given operation, the value returned by `eth_estimateGas` will change over time (as the L1 calldata price fluctuates.) (See [2-D fees](https://medium.com/offchainlabs/understanding-arbitrum-2-dimensional-fees-fd1d582596c9) and [How to estimate gas in Arbitrum](/build-decentralized-apps/02-how-to-estimate-gas.mdx) for more.) + +### L2 gas fees + +L2 gas fees work very similarly to gas on Ethereum. A transaction uses some amount of gas, and this is multiplied by the current basefee to get the L2 gas fee charged to the transaction. + +The L2 basefee is set by a version of the "exponential mechanism" which has been widely discussed in the Ethereum community, and which has been shown equivalent to Ethereum's EIP-1559 gas pricing mechanism. + +The algorithm compares gas usage against a parameter called the [speed limit](#the-speed-limit) which is the target amount of gas per second that the chain can handle sustainably over time. (Currently the Speed Limit on Arbitrum One is @arbOneGasSpeedLimitGasPerSec@ gas per second.) The algorithm tracks a gas backlog. Whenever a transaction consumes gas, that gas is added to the backlog. Whenever the clock ticks one second, the speed limit is subtracted from the backlog; but the backlog can never go below zero. + +Intuitively, if the backlog grows, the algorithm should increase the gas price, to slow gas usage, because usage is above the sustainable level. If the backlog shrinks, the price should decrease again because usage has been below the below the sustainable limit so more gas usage can be welcomed. + +To make this more precise, the basefee is an exponential function of the backlog, _F = exp(-a(B-b))_, where a and b are suitably chosen constants: _a_ controls how rapidly the price escalates with backlog, and _b_ allows a small backlog before the basefee escalation begins. + +### L2 Tips + +The sequencer prioritizes transactions on a first-come first-served basis. Because tips do not make sense in this model, they are ignored. Arbitrum users always just pay the basefee regardless of the tip they choose. + +### Gas Estimating Retryables + +When a transaction schedules another, the subsequent transaction's execution [will be included][estimation_inclusion_link] when estimating gas via the node's RPC. A transaction's gas estimate, then, can only be found if all the transactions succeed at a given gas limit. This is especially important when working with retryables and scheduling redeem attempts. + +Because a call to [`redeem`](/build-decentralized-apps/precompiles/02-reference.mdx#arbretryabletx) donates all of the call's gas, doing multiple requires limiting the amount of gas provided to each subcall. Otherwise the first will take all of the gas and force the second to necessarily fail irrespective of the estimation's gas limit. + +Gas estimation for Retryable submissions is possible via the [NodeInterface](/build-decentralized-apps/nodeinterface/02-reference.mdx) and similarly requires the auto-redeem attempt to succeed. + +[estimation_inclusion_link]: https://github.com/OffchainLabs/go-ethereum/blob/d52739e6d54f2ea06146fdc44947af3488b89082/internal/ethapi/api.go#L999 + +### The Speed Limit + +The security of Nitro chains depends on the assumption that when one Validator creates an RBlock, other validators will check it, and respond with a correct RBlock and a Challenge if it is wrong. This requires that the other validators have the time and resources to check each RBlock quickly enough to issue a timely challenge. The Arbitrum protocol takes this into account in setting deadlines for RBlocks. + +This sets an effective speed limit on execution of a Nitro chain: in the long run the chain cannot make progress faster than a validator can emulate its execution. If RBlocks are published at a rate faster than the speed limit, their deadlines will get farther and farther in the future. Due to the limit, enforced by the rollup protocol contracts, on how far in the future a deadline can be, this will eventually cause new RBlocks to be slowed down, thereby enforcing the effective speed limit. + +Being able to set the speed limit accurately depends on being able to estimate the time required to validate an RBlock, with some accuracy. Any uncertainty in estimating validation time will force us to set the speed limit lower, to be safe. And we do not want to set the speed limit lower, so we try to enable accurate estimation. + +## Total fee and gas estimation + +The total fee charged to a transaction is the L2 basefee, multiplied by the sum of the L2 gas used plus the L1 calldata charge. As on Ethereum, a transaction will fail if it fails to supply enough gas, or if it specifies a basefee limit that is below the current basefee. Ethereum also allows a "tip" but Nitro ignores this field and never collects any tips. + +### Allocating funds and paying what is owed + +When a batch posting report is processed at L2, the pricer allocates some of the collected funds to pay for costs incurred. To allocate funds, the pricer considers three timestamps: + +- `currentTime` is the current time, when the batch posting report message arrives at L2 +- `updateTime` is the time at which the reported batch was submitted (which will typically be around 20 minutes before currentTime) +- `lastUpdateTime` is the time at which the previous reported batch was submitted + +The pricer computes an allocation fraction `F = (updateTime-lastUpdateTime) / (currentTime-lastUpdateTime)` and allocates a fraction `F` of funds in the `L1PricerFundsPool` to the current report. The intuition is that the pricer knows how many funds have been collected between `lastUpdateTime` and `currentTime`, and we want to figure out how many of those funds to allocate to the interval between `lastUpdateTime` and `updateTime`. The given formula is the correct allocation, if we assume that funds arrived at a uniform rate during the interval between `lastUpdateTime` and `currentTime`. The pricer similarly allocates a portion of the total data units to the current report. + +Now the pricer pays out the allocated funds to cover the rewards due and the amounts due to batch posters, reducing the balance due to each party as a result. If the allocated funds aren't sufficient to cover everything that is due, some amount due will remain. If all of the amount due can be covered with the allocated funds, any remaining allocated funds are returned to the `L1PricerFundsPool`. + +### Getting L1 fee info + +The L1 gas basefee can be queried via [`ArbGasInfo.getL1BaseFeeEstimate`](/build-decentralized-apps/precompiles/02-reference.mdx#arbgasinfo). To estimate the L1 fee a transaction will use, the [NodeInterface.gasEstimateComponents()](/build-decentralized-apps/nodeinterface/02-reference.mdx) or [NodeInterface.gasEstimateL1Component()](/build-decentralized-apps/nodeinterface/02-reference.mdx) method can be used. + +Arbitrum transaction receipts include a `gasUsedForL1` field, showing the amount of gas used on L1 in units of L2 gas. + +### Adjusting the L1 gas basefee + +After allocating funds and paying what is owed, the L1 Pricer adjusts the L1 Gas Basefee. The goal of this process is to find a value that will cause the amount collected to equal the amount owed over time. + +The algorithm first computes the surplus (funds in the `L1PricerFundsPool`, minus total funds due), which might be negative. If the surplus is positive, the L1 Gas Basefee is reduced, so that the amount collected over a fixed future interval will be reduced by exactly the surplus. If the surplus is negative, the Basefee is increased so that the shortfall will be eliminated over the same fixed future interval. + +A second term is added to the L1 Gas Basefee, based on the derivative of the surplus (surplus at present, minus the surplus after the previous batch posting report was processed). This term, which is multiplied by a smoothing factor to reduce fluctuations, will reduce the Basefee if the surplus is increasing, and increase the Basefee if the surplus is shrinking. diff --git a/arbitrum-docs/how-arbitrum-works/arbos/l1-l2-messaging.md b/arbitrum-docs/how-arbitrum-works/10-l1-to-l2-messaging.mdx similarity index 73% rename from arbitrum-docs/how-arbitrum-works/arbos/l1-l2-messaging.md rename to arbitrum-docs/how-arbitrum-works/10-l1-to-l2-messaging.mdx index fa181a7d5..2362176e0 100644 --- a/arbitrum-docs/how-arbitrum-works/arbos/l1-l2-messaging.md +++ b/arbitrum-docs/how-arbitrum-works/10-l1-to-l2-messaging.mdx @@ -1,8 +1,10 @@ --- -title: 'L1 to L2 messaging' -description: This concept page provides information about how arbitrary messages are passed from L1 to L2 -target_audience: developers who want to build on Arbitrum -content_type: concept +title: L1 to L2 messaging +description: 'Learn the fundamentals of L1 to L2 messaging on Arbitrum.' +author: pete-vielhaber +sme: TucksonDev +user_story: As a current or prospective Arbitrum user, I need to learn more about messaging between L1 and L2 within Arbitrum. +content_type: get-started --- import { AddressAliasHelper } from '@site/src/components/AddressAliasHelper'; @@ -15,35 +17,39 @@ import { NodeDescription, } from '/src/components/MermaidWithHtml/MermaidWithHtml'; +In the [Transaction Lifecycle](/how-arbitrum-works/02-transaction-lifecycle.mdx) section, we covered how users interact with L2 contracts. They submit transactions by putting messages into the chain’s inbox or having a full node Sequencer or aggregator do so on their behalf. + +L1 and L2 chains run asynchronously from each other, so it is not possible to make a cross-chain call that produces a result within the same Transaction as the caller. Instead, cross-chain calls must be asynchronous, meaning that the caller submits the call at some point in time, and the call runs later. Consequently, a cross-chain contract-to-contract call can never produce a result available to the calling contract (except for acknowledgment of a successful call submitted for later execution). + +In this section, we will discuss how contracts interact between L1 and L2, how an L1 contract is called an L2 contract, and vice versa. + ## Retryable Tickets -Retryable tickets are Arbitrum's canonical method for creating L1 to L2 messages, i.e., L1 transactions that initiate a message to be executed on L2. A retryable can be submitted for a fixed cost (dependent only on its calldata size) paid at L1; its _submission_ on L1 is separable / asynchronous with its _execution_ on L2. Retryables provide atomicity between the cross chain operations; if the L1 transaction to request submission succeeds (i.e. does not revert) then the execution of the Retryable on L2 has a strong guarantee to ultimately succeed as well. +Retryable tickets are Arbitrum's canonical method for creating L1 to L2 messages, i.e., L1 transactions that initiate a message to be executed on L2. A retryable can be submitted for a fixed cost (dependent only on its calldata size) paid at L1; its _submission_ on L1 is separable / asynchronous with its _execution_ on L2. Retryables provide atomicity between the cross chain operations; if the L1 transaction to request submission succeeds (i.e. does not revert) then the execution of the Retryable on L2 has a strong guarantee to ultimately succeed as well. ## Retryable Tickets Lifecycle -Here we walk through the different stages of the lifecycle of a retryable ticket; (1) submission, (2) auto-redemption, and (3) manual redemption. +Here we walk through the different stages of the lifecycle of a Retryable Ticket; (1) submission, (2) auto-redemption, and (3) manual redemption. ### Submission -1. Creating a retryable ticket is initiated with a call (direct or internal) to the `createRetryableTicket` function of the [`inbox` contract][inbox_link]. A ticket is guaranteed to be created if this call succeeds. Here, we describe parameters that need to be carefully set. Note that, this function forces the sender to provide a _reasonable_ amount of funds (at least enough to submitting, and _attempting_ to executing the ticket), but that doesn't guarantee a successful auto-redemption. +1. Creating a retryable ticket is initiated with a call (direct or internal) to the `createRetryableTicket` function of the [`inbox` contract](https://github.com/OffchainLabs/nitro-contracts/blob/67127e2c2fd0943d9d87a05915d77b1f220906aa/src/bridge/Inbox.sol). A ticket is guaranteed to be created if this call succeeds. Here, we describe parameters that need to be carefully set. Note that, this function forces the sender to provide a _reasonable_ amount of funds (at least enough to submitting, and _attempting_ to executing the ticket), but that doesn't guarantee a successful auto-redemption. -| Parameter | Description | -| :------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `l1CallValue (also referred to as deposit)` | Not a real function parameter, it is rather the callValue that is sent along with the transaction | -| `address to` | The destination L2 address | -| `uint256 l2CallValue` | The callvalue for retryable L2 message that is supplied within the deposit (l1CallValue) | -| `uint256 maxSubmissionCost` | The maximum amount of ETH to be paid for submitting the ticket. This amount is (1) supplied within the deposit (l1CallValue) to be later deducted from sender's L2 balance and is (2) directly proportional to the size of the retryable’s data and L1 basefee | -| `address excessFeeRefundAddress` | The unused gas cost and submssion cost will deposit to this address, formula is: `(gasLimit x maxFeePerGas - execution cost) + (maxSubmission - (autoredeem ? 0 : submission cost))`. (Note: excess deposit will transfer to the alias address of the parent chain tx's `msg.sender` rather than this address) | -| `address callValueRefundAddress` | The L2 address to which the l2CallValue is credited if the ticket times out or gets cancelled (this is also called the `beneficiary`, who's got a critical permission to cancel the ticket) | -| `uint256 gasLimit` | Maximum amount of gas used to cover L2 execution of the ticket | -| `uint256 maxFeePerGas` | The gas price bid for L2 execution of the ticket that is supplied within the deposit (l1CallValue) | -| `bytes calldata data` | The calldata to the destination L2 address | +| Parameter | Description | +| :------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `l1CallValue (also referred to as deposit)` | Not a real function parameter, it is rather the callValue that is sent along with the transaction | +| `address to` | The destination L2 address | +| `uint256 l2CallValue` | The callvalue for retryable L2 message that is supplied within the deposit (l1CallValue) | +| `uint256 maxSubmissionCost` | The maximum amount of ETH to be paid for submitting the ticket. This amount is (1) supplied within the deposit (l1CallValue) to be later deducted from sender's L2 balance and is (2) directly proportional to the size of the retryable’s data and L1 basefee | +| `address excessFeeRefundAddress` | The unused gas cost and submssion cost will deposit to this address, formula is: `(gasLimit x maxFeePerGas - execution cost) + (maxSubmission - (autoredeem ? 0 : submission cost))`. (Note: excess deposit will transfer to the alias address of the Parent chain tx's `msg.sender` rather than this address) | +| `address callValueRefundAddress` | The L2 address to which the l2CallValue is credited if the ticket times out or gets cancelled (this is also called the `beneficiary`, who's got a critical permission to cancel the ticket) | +| `uint256 gasLimit` | Maximum amount of gas used to cover L2 execution of the ticket | +| `uint256 maxFeePerGas` | The gas price bid for L2 execution of the ticket that is supplied within the deposit (l1CallValue) | +| `bytes calldata data` | The calldata to the destination L2 address | 2. Sender's deposit must be enough to make the L1 submission succeed and for the L2 execution to be _attempted_. If provided correctly, a new ticket with a unique `TicketID` is created and added to retryable buffer. Also, funds (`submissionCost` + `l2CallValue`) are deducted from the sender and placed into the escrow for later use in redeeming the ticket. -3. Ticket creation causes the [`ArbRetryableTx`](/build-decentralized-apps/precompiles/02-reference.md#arbretryabletx) precompile to emit a `TicketCreated` event containing the `TicketID` on L2. - -[inbox_link]: https://github.com/OffchainLabs/nitro-contracts/blob/67127e2c2fd0943d9d87a05915d77b1f220906aa/src/bridge/Inbox.sol +3. Ticket creation causes the [`ArbRetryableTx`](/build-decentralized-apps/precompiles/02-reference.mdx#arbretryabletx) precompile to emit a `TicketCreated` event containing the `TicketID` on L2. @@ -85,7 +91,7 @@ Here we walk through the different stages of the lifecycle of a retryable ticket ### Automatic Redemption -4. It is very important to note that the submission of a ticket on L1 is separable / asynchronous from its execution on L2, i.e., a successful L1 ticket creation does not guarantee a successful redemption. Once the ticket is successfully created, the two following conditions are checked: (1) if the user's L2 balance is greater than (or equal to) `maxFeePerGas * gasLimit` **and** (2) if the `maxFeePerGas` (provided by the user in the ticket submission process) is greater than (or equal to) the `l2Basefee`. If these conditions are both met, ticket's submission is followed by an attempt to execute it on L2 (i.e., an **auto-redeem** using the supplied gas, as if the `redeem` method of the [ArbRetryableTx](/build-decentralized-apps/precompiles/02-reference.md#arbretryabletx) precompile had been called). Depending on how much gas the sender has provided in step 1, ticket's redemption can either (1) immediately succeed or (2) fail. We explain both situations here: +4. It is very important to note that the submission of a ticket on L1 is separable / asynchronous from its execution on L2, i.e., a successful L1 ticket creation does not guarantee a successful redemption. Once the ticket is successfully created, the two following conditions are checked: (1) if the user's L2 balance is greater than (or equal to) `maxFeePerGas * gasLimit` **and** (2) if the `maxFeePerGas` (provided by the user in the ticket submission process) is greater than (or equal to) the `l2Basefee`. If these conditions are both met, ticket's submission is followed by an attempt to execute it on L2 (i.e., an **auto-redeem** using the supplied gas, as if the `redeem` method of the [ArbRetryableTx](/build-decentralized-apps/precompiles/02-reference.mdx#arbretryabletx) precompile had been called). Depending on how much gas the sender has provided in step 1, ticket's redemption can either (1) immediately succeed or (2) fail. We explain both situations here: - If the ticket is successfully auto-redeemed, it will execute with the sender, destination, callvalue, and calldata of the original submission. The submission fee is refunded to the user on L2 (`excessFeeRefundAddress`). Note that to ensure successful auto-redeem of the ticket, one could use the Arbitrum SDK which provides a [convenience function](https://github.com/OffchainLabs/arbitrum-sdk/blob/4cedb1fcf1c7302a4c3d0f8e75fb33d82bc8338d/src/lib/message/L1ToL2MessageGasEstimator.ts#L215) that returns the desired gas parameters when sending L1-L2 messages. @@ -125,7 +131,7 @@ Here we walk through the different stages of the lifecycle of a retryable ticket ### Manual Redemption -5. At this point, _anyone_ can attempt to manually redeem the ticket again by calling [ArbRetryableTx](/build-decentralized-apps/precompiles/02-reference.md#arbretryabletx)'s `redeem` precompile method, which donates the call's gas to the next attempt. Note that the amount of gas is NOT limited by the original gasLimit set during the ticket creation. ArbOS will [enqueue the redeem][enqueue_link], which is its own special `ArbitrumRetryTx` type, to its list of redeems that ArbOS [guarantees to exhaust][exhaust_link] before moving on to the next non-redeem transaction in the block its forming. In this manner redeems are scheduled to happen as soon as possible, and will always be in the same block as the tx that scheduled it. Note that the redeem attempt's gas comes from the call to redeem, so there's no chance the block's gas limit is reached before execution. +5. At this point, _anyone_ can attempt to manually redeem the ticket again by calling [ArbRetryableTx](/build-decentralized-apps/precompiles/02-reference.mdx#arbretryabletx)'s `redeem` precompile method, which donates the call's gas to the next attempt. Note that the amount of gas is NOT limited by the original gasLimit set during the ticket creation. ArbOS will [enqueue the redeem][enqueue_link], which is its own special `ArbitrumRetryTx` type, to its list of redeems that ArbOS [guarantees to exhaust][exhaust_link] before moving on to the next non-redeem transaction in the block its forming. In this manner redeems are scheduled to happen as soon as possible, and will always be in the same block as the tx that scheduled it. Note that the redeem attempt's gas comes from the call to redeem, so there's no chance the block's gas limit is reached before execution. 6. If the fixed period (one week) elapses without a successful redeem, the ticket **expires** and will be [automatically **discarded**][discard_link], unless some party has paid a fee to [**keep the ticket alive**][renew_link] for another full period. A ticket can live indefinitely as long as it is renewed each time before it expires. @@ -180,7 +186,7 @@ If a ticket with a callvalue is eventually discarded (cancelled or expired), hav :::note Important Notes: -If a redeem is not done at submission or the submission's initial redeem fails, anyone can attempt to redeem the retryable again by calling [`ArbRetryableTx`](/build-decentralized-apps/precompiles/02-reference.md#arbretryabletx)'s `redeem` precompile method, which donates the call's gas to the next attempt. ArbOS will [enqueue the redeem][enqueue_link], which is its own special `ArbitrumRetryTx` type, to its list of redeems that ArbOS [guarantees to exhaust][exhaust_link] before moving on to the next non-redeem transaction in the block its forming. In this manner redeems are scheduled to happen as soon as possible, and will always be in the same block as the transaction that scheduled it. Note that the redeem attempt's gas comes from the call to `redeem`, so there's no chance the block's gas limit is reached before execution. +If a redeem is not done at submission or the submission's initial redeem fails, anyone can attempt to redeem the retryable again by calling [`ArbRetryableTx`](/build-decentralized-apps/precompiles/02-reference.mdx#arbretryabletx)'s `redeem` precompile method, which donates the call's gas to the next attempt. ArbOS will [enqueue the redeem][enqueue_link], which is its own special `ArbitrumRetryTx` type, to its list of redeems that ArbOS [guarantees to exhaust][exhaust_link] before moving on to the next non-redeem transaction in the block its forming. In this manner redeems are scheduled to happen as soon as possible, and will always be in the same block as the transaction that scheduled it. Note that the redeem attempt's gas comes from the call to `redeem`, so there's no chance the block's gas limit is reached before execution. - One can redeem live tickets using the [Arbitrum Retryables Transaction Panel][retryable_dashboard_link] - The calldata of a ticket is saved on L2 until it is redeemed or expired @@ -199,7 +205,7 @@ In the lifecycle of a retryable ticket, two types of L2 transaction receipts wil ### Alternative "unsafe" Retryable Ticket Creation -The `Inbox.createRetryableTicket` convenience method includes sanity checks to help minimize the risk of user error: the method will ensure that enough funds are provided directly from L1 to cover the current cost of ticket creation. It also will convert the provided `callValueRefundAddress` and `excessFeeRefundAddress` to their address alias (see below) if either is a contract (determined by if the address has code during the call), providing a path for the L1 contract to recover funds. A power-user may bypass these sanity-check measures via the `Inbox`'s `unsafeCreateRetryableTicket` method; as the method's name desperately attempts to warn you, it should only be accessed by a user who truly knows what they're doing. +The `Inbox.createRetryableTicket` convenience method includes sanity checks to help minimize the risk of user error: the method will ensure that enough funds are provided directly from L1 to cover the current cost of ticket creation. It also will convert the provided `callValueRefundAddress` and `excessFeeRefundAddress` to their Address Alias (see below) if either is a contract (determined by if the address has code during the call), providing a path for the L1 contract to recover funds. A power-user may bypass these sanity-check measures via the `Inbox`'s `unsafeCreateRetryableTicket` method; as the method's name desperately attempts to warn you, it should only be accessed by a user who truly knows what they're doing. ## Eth deposits @@ -211,7 +217,7 @@ In principle, retryable tickets can alternatively be used to deposit Ether; this ## Transacting via the Delayed Inbox -While retryables and Eth deposits _must_ be submitted through the delayed inbox, in principle, _any_ message can be included this way; this is a necessary recourse to ensure the Arbitrum chain preserves censorship resistance even if the Sequencer misbehaves (see [The Sequencer and Censorship Resistance](/how-arbitrum-works/sequencer.md)). However, under ordinary/happy circumstances, the expectation/recommendation is that clients use the delayed inbox only for Retryables and Eth deposits, and transact via the Sequencer for all other messages. +While retryables and Eth deposits _must_ be submitted through the Delayed Inbox, in principle, _any_ message can be included this way; this is a necessary recourse to ensure the Arbitrum chain preserves censorship resistance even if the Sequencer misbehaves (see [The Sequencer and Censorship Resistance](/how-arbitrum-works/03-sequencer.mdx)). However, under ordinary/happy circumstances, the expectation/recommendation is that clients use the delayed inbox only for Retryables and Eth deposits, and transact via the Sequencer for all other messages. ### Address Aliasing @@ -224,6 +230,7 @@ L2_Alias = L1_Contract_Address + 0x1111000000000000000000000000000000001111 :::tip Try it out + ::: The Arbitrum protocol's usage of L2 Aliases for L1-to-L2 messages prevents cross-chain exploits that would otherwise be possible if we simply reused the same L1 addresses as the L2 sender; i.e., tricking an L2 contract that expects a call from a given contract address by sending retryable ticket from the expected contract address on L1. @@ -239,6 +246,6 @@ modifier onlyFromMyL1Contract() override { ### Signed Messages -The delayed inbox can also accept messages that include a signature. In this case, the message will execute with the `msg.sender` address equal to the address that produced the included signature (i.e., _not_ its alias). Intuitively, the signature proves that the sender address is not a contract, and thus is safe from cross-chain exploit concerns described above. Thus, it can safely execute from signer's address, similar to a transaction included in a Sequencer's batch. For these messages, the address of the L1 sender is effectively ignored at L2. +The delayed inbox can also accept messages that include a signature. In this case, the message will execute with the `msg.sender` address equal to the address that produced the included signature (i.e., _not_ its alias). Intuitively, the signature proves that the sender address is not a contract, and thus is safe from cross-chain exploit concerns described above. Thus, it can safely execute from signer's address, similar to a transaction included in a Sequencer's Batch. For these messages, the address of the L1 sender is effectively ignored at L2. These signed messages submitted through the delayed inbox can be used to execute messages that bypass the Sequencer and require EOA authorization at L2, e.g., force-including an Ether withdrawal (see ["withdraw eth tutorial"](https://github.com/OffchainLabs/arbitrum-tutorials/blob/a1c3f64a5abdd0f0e728cb94d4ecc2700eab7579/packages/delayedInbox-l2msg/scripts/withdrawFunds.js#L61-L65)). diff --git a/arbitrum-docs/how-arbitrum-works/11-l2-to-l1-messaging.mdx b/arbitrum-docs/how-arbitrum-works/11-l2-to-l1-messaging.mdx new file mode 100644 index 000000000..91bf84bf6 --- /dev/null +++ b/arbitrum-docs/how-arbitrum-works/11-l2-to-l1-messaging.mdx @@ -0,0 +1,33 @@ +--- +title: L2 to L1 messaging +description: 'Learn the fundamentals of L2 to L1 messaging on Arbitrum.' +author: pete-vielhaber +sme: TucksonDev +user_story: As a current or prospective Arbitrum user, I need to learn more about messaging between L2 and L1 on Arbitrum. +content_type: get-started +--- + +Arbitrum's Outbox system +allows for arbitrary L2 to L1 contract calls; i.e., messages initiated from L2 which eventually +resolve in execution on L1. L2-to-L1 messages (aka "outgoing" messages) bear many things in common +with Arbitrum's [L1-to-L2 messages](/how-arbitrum-works/10-l1-to-l2-messaging.mdx) (Retryables), "in +reverse" though with a few differences. + +### Protocol Flow + +Part of the L2 state of an Arbitrum chain — and consequently, part of what's asserted in every RBlock — is a Merkle root of all L2-to-L1 messages in the chain's history. Upon an asserted RBlock being confirmed (typically ~1 week after its asserted), this Merkle root is posted on L1 in the `Outbox` contract. The Outbox contract then lets users execute their messages — validating Merkle proofs of inclusion, and tracking which L2 to L1 messages have already been spent. + +### Client Flow + +From a Client perspective, an L2 to L1 message begins with a call to the L2 [`ArbSys`](/build-decentralized-apps/precompiles/02-reference.mdx#arbsys) precompile contract's `sendTxToL1` method. Once the message is included in an Assertion (typically within ~1 hour) and the assertion is confirmed (typically about ~ 1 week), any client can execute the message. To do this, the client first retrieves the proof data via a call to the Arbitrum chain's "virtual"/precompile-esque\*\* `NodeInterface` contract's `constructOutboxProof` method. The data returned can then be used in the `Outbox`'s `executeTransaction` method to perform the L1 execution. + +### Protocol Design Details + +An important feature in the design of the Outbox system is that calls to `confirmNode` have constant overhead. Requiring that `confirmNode` only update the constant-sized outgoing message root hash, and that users themselves carry out the final step of execution, achieves this goal; i.e., no matter the number of outgoing messages in the root, or the gas cost of executing them on L1, the cost of confirming nodes remains constant; this ensures that the RBlock Confirmation processed can't be griefed. + +Unlike Retryables, which have an option to provide Ether for automatic L2 execution, outgoing messages can't provide in-protocol automatic L1 execution, for the simple reason that Ethereum itself doesn't offer scheduled execution affordances. However, application-layer contracts that interact with the Outbox could in principle be built to provide somewhat-analogous "execution market" functionality for outsourcing the final L1 execution step. + +Another difference between outgoing messages and Retryables is that Retryables have a limited lifetime before which they must be redeemed (or have their lifetime explicitly extended), whereas L2 to L1 messages are stored in L1 state, and thus persist permanently / have no deadline before which they must be executed. +The week long delay period before outgoing messages can be executed is inherent and fundamental to the nature of Arbitrum Rollup, or any Optimistic Rollup style L2; the moment a Transaction is published on-chain, any observer can anticipate its result; however, for Ethereum itself to accept its result, the protocol must give time for Arbitrum validators to detect and prove fault if need-be. For a protocol overview, see [Inside Arbitrum](/how-arbitrum-works/01-a-gentle-introduction.mdx) + +\*\* We refer to `NodeInterface` as a "virtual" contract; its methods are accessible via calls `0x00000000000000000000000000000000000000C8`, but it doesn't really live on chain. It isn't really a precompile, but behaves a lot like a precompile that can't receive calls from other contracts. This is a cute trick that let's us provide Arbitrum-specific data without having to implement a custom RPC. diff --git a/arbitrum-docs/how-arbitrum-works/arbos/geth.md b/arbitrum-docs/how-arbitrum-works/arbos/geth.md deleted file mode 100644 index d59714649..000000000 --- a/arbitrum-docs/how-arbitrum-works/arbos/geth.md +++ /dev/null @@ -1,292 +0,0 @@ ---- -author: dzgoldman ---- - -# Geth - -Nitro makes minimal modifications to Geth in hopes of not violating its assumptions. This document will explore the relationship between Geth and ArbOS, which consists of a series of hooks, interface implementations, and strategic re-appropriations of Geth's basic types. - -We store ArbOS's state at an address inside a Geth `statedb`. In doing so, ArbOS inherits the `statedb`'s statefulness and lifetime properties. For example, a transaction's direct state changes to ArbOS are discarded upon a revert. - -**0xA4B05FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF**
-The fictional account representing ArbOS - -:::info - -Please note any links on this page may be referencing old releases of Nitro or our fork of Geth. While we try to keep this up to date and most of this should be stable, please check against latest releases for [Nitro](https://github.com/OffchainLabs/nitro/releases) and [Geth](https://github.com/OffchainLabs/go-ethereum/releases) for most recent changes. - -::: - -## Hooks - -Arbitrum uses various hooks to modify Geth's behavior when processing transactions. Each provides an opportunity for ArbOS to update its state and make decisions about the transaction during its lifetime. Transactions are applied using Geth's [`ApplyTransaction`][applytransaction_link] function. - -Below is [`ApplyTransaction`][applytransaction_link]'s callgraph, with additional info on where the various Arbitrum-specific hooks are inserted. Click on any to go to their section. By default, these hooks do nothing so as to leave Geth's default behavior unchanged, but for chains configured with [`EnableArbOS`](#EnableArbOS) set to true, [`ReadyEVMForL2`](#ReadyEVMForL2) installs the alternative L2 hooks. - -- `core.ApplyTransaction` ⮕ `core.applyTransaction` ⮕ `core.ApplyMessage` - - `core.NewStateTransition` - - [`ReadyEVMForL2`](#ReadyEVMForL2) - - `core.TransitionDb` - - [`StartTxHook`](#StartTxHook) - - `core.transitionDbImpl` - - if `IsArbitrum()` remove tip - - [`GasChargingHook`](#GasChargingHook) - - `evm.Call` - - `core.vm.EVMInterpreter.Run` - - [`PushCaller`](#PushCaller) - - [`PopCaller`](#PopCaller) - - `core.StateTransition.refundGas` - - [`ForceRefundGas`](#ForceRefundGas) - - [`NonrefundableGas`](#NonrefundableGas) - - [`EndTxHook`](#EndTxHook) - - added return parameter: `transactionResult` - -What follows is an overview of each hook, in chronological order. - -### [`ReadyEVMForL2`][readyevmforl2_link]{#ReadyEVMForL2} - -A call to [`ReadyEVMForL2`][readyevmforl2_link] installs the other transaction-specific hooks into each Geth [`EVM`][evm_link] right before it performs a state transition. Without this call, the state transition will instead use the default [`DefaultTxProcessor`][defaulttxprocessor_link] and get exactly the same results as vanilla Geth. A [`TxProcessor`][txprocessor_link] object is what carries these hooks and the associated Arbitrum-specific state during the transaction's lifetime. - -### [`StartTxHook`][starttxhook_link]{#StartTxHook} - -The [`StartTxHook`][starttxhook_link] is called by Geth before a transaction starts executing. This allows ArbOS to handle two Arbitrum-specific transaction types. - -If the transaction is `ArbitrumDepositTx`, ArbOS adds balance to the destination account. This is safe because the L1 bridge submits such a transaction only after collecting the same amount of funds on L1. - -If the transaction is an `ArbitrumSubmitRetryableTx`, ArbOS creates a retryable based on the transaction's fields. If the transaction includes sufficient gas, ArbOS schedules a retry of the new retryable. - -The hook returns `true` for both of these transaction types, signifying that the state transition is complete. - -### [`GasChargingHook`][gascharginghook_link]{#GasChargingHook} - -This fallible hook ensures the user has enough funds to pay their poster's L1 calldata costs. If not, the transaction is reverted and the [`EVM`][evm_link] does not start. In the common case that the user can pay, the amount paid for calldata is set aside for later reimbursement of the poster. All other fees go to the network account, as they represent the transaction's burden on validators and nodes more generally. - -If the user attempts to purchase compute gas in excess of ArbOS's per-block gas limit, the difference is [set aside][difference_set_aside_link] and [refunded later][refunded_later_link] via [`ForceRefundGas`](#ForceRefundGas) so that only the gas limit is used. Note that the limit observed may not be the same as that seen [at the start of the block][that_seen_link] if ArbOS's larger gas pool falls below the [`MaxPerBlockGasLimit`][max_perblock_limit_link] while processing the block's previous transactions. - -[difference_set_aside_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L407 -[refunded_later_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/state_transition.go#L419 -[that_seen_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/block_processor.go#L176 -[max_perblock_limit_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/l2pricing/l2pricing.go#L86 - -### [`PushCaller`][pushcaller_link]{#PushCaller} - -These hooks track the callers within the EVM callstack, pushing and popping as calls are made and complete. This provides [`ArbSys`](/build-decentralized-apps/precompiles/02-reference.md#arbsys) with info about the callstack, which it uses to implement the methods `WasMyCallersAddressAliased` and `MyCallersAddressWithoutAliasing`. - -### [`L1BlockHash`][l1blockhash_link] - -In Arbitrum, the BlockHash and Number operations return data that relies on underlying L1 blocks instead of L2 blocks, to accommodate the normal use-case of these opcodes, which often assume Ethereum-like time passes between different blocks. The L1BlockHash and L1BlockNumber hooks have the required data for these operations. - -### [`ForceRefundGas`][forcerefundgas_link]{#ForceRefundGas} - -This hook allows ArbOS to add additional refunds to the user's tx. This is currently only used to refund any compute gas purchased in excess of ArbOS's per-block gas limit during the [`GasChargingHook`](#GasChargingHook). - -### [`NonrefundableGas`][nonrefundablegas_link]{#NonrefundableGas} - -Because poster costs come at the expense of L1 aggregators and not the network more broadly, the amounts paid for L1 calldata should not be refunded. This hook provides Geth access to the equivalent amount of L2 gas the poster's cost equals, ensuring this amount is not reimbursed for network-incentivized behaviors like freeing storage slots. - -### [`EndTxHook`][endtxhook_link]{#EndTxHook} - -The [`EndTxHook`][endtxhook_link] is called after the [`EVM`][evm_link] has returned a transaction's result, allowing one last opportunity for ArbOS to intervene before the state transition is finalized. Final gas amounts are known at this point, enabling ArbOS to credit the network and poster each's share of the user's gas expenditures as well as adjust the pools. The hook returns from the [`TxProcessor`][txprocessor_link] a final time, in effect discarding its state as the system moves on to the next transaction where the hook's contents will be set afresh. - -[applytransaction_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/state_processor.go#L152 -[evm_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/vm/evm.go#L101 -[defaulttxprocessor_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/vm/evm_arbitrum.go#L42 -[txprocessor_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L38 -[starttxhook_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L100 -[readyevmforl2_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbstate/geth-hook.go#L47 -[gascharginghook_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L354 -[pushcaller_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L76 -[popcaller_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L80 -[forcerefundgas_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L425 -[nonrefundablegas_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L418 -[endtxhook_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L429 -[l1blockhash_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L617 -[l1blocknumber_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/tx_processor.go#L600 - -## Interfaces and components - -### [`APIBackend`][apibackend_link] - -APIBackend implements the [`ethapi.Backend`][ethapi.backend_link] interface, which allows simple integration of the Arbitrum chain to existing Geth API. Most calls are answered using the Backend member. - -[apibackend_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/apibackend.go#L34 -[ethapi.backend_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/internal/ethapi/backend.go#L42 - -### [`Backend`][backend_link] - -This struct was created as an Arbitrum equivalent to the [`Ethereum`][ethereum_link] struct. It is mostly glue logic, including a pointer to the ArbInterface interface. - -[backend_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/backend.go#L15 -[ethereum_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/eth/backend.go#L68 - -### [`ArbInterface`][arbinterface_link] - -This interface is the main interaction-point between geth-standard APIs and the Arbitrum chain. Geth APIs mostly either check status by working on the Blockchain struct retrieved from the [`Blockchain`][blockchain_link] call, or send transactions to Arbitrum using the [`PublishTransactions`][publishtransactions_link] call. - -[arbinterface_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/arbos_interface.go#L10 -[blockchain_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/arbos_interface.go#L12 -[publishtransactions_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/arbos_interface.go#L11 - -### [`RecordingKV`][recordingkv_link] - -RecordingKV is a read-only key-value store, which retrieves values from an internal trie database. All values accessed by a RecordingKV are also recorded internally. This is used to record all preimages accessed during block creation, which will be needed to prove execution of this particular block. -A [`RecordingChainContext`][recordingchaincontext_link] should also be used, to record which block headers the block execution reads (another option would be to always assume the last 256 block headers were accessed). -The process is simplified using two functions: [`PrepareRecording`][preparerecording_link] creates a stateDB and chaincontext objects, running block creation process using these objects records the required preimages, and [`PreimagesFromRecording`][preimagesfromrecording_link] function extracts the preimages recorded. - -[recordingkv_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/recordingdb.go#L22 -[recordingchaincontext_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/recordingdb.go#L123 -[preparerecording_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/recordingdb.go#L152 -[preimagesfromrecording_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/arbitrum/recordingdb.go#L174 - -## Transaction Types - -Nitro Geth includes a few L2-specific transaction types. Click on any to jump to their section. - -| Tx Type | Represents | Last Hook Reached   | Source | -| :------------------------------------------------ | :----------------------------------- | :------------------------- | ------ | -| [`ArbitrumUnsignedTx`][arbtxunsigned] | An L1 to L2 message | [`EndTxHook`][he] | Bridge | -| [`ArbitrumContractTx`][arbtxcontract] | A nonce-less L1 to L2 message   | [`EndTxHook`][he] | Bridge | -| [`ArbitrumDepositTx`][arbtxdeposit] | A user deposit | [`StartTxHook`][hs] | Bridge | -| [`ArbitrumSubmitRetryableTx`][arbtxsubmit]   | Creating a retryable | [`StartTxHook`][hs]   | Bridge | -| [`ArbitrumRetryTx`][arbtxretry] | A retryable redeem attempt | [`EndTxHook`][he] | L2 | -| [`ArbitrumInternalTx`][arbtxinternal] | ArbOS state update | [`StartTxHook`][hs] | ArbOS | - -[arbtxunsigned]: #ArbitrumUnsignedTx -[arbtxcontract]: #ArbitrumContractTx -[arbtxsubmit]: #ArbitrumSubmitRetryableTx -[arbtxretry]: #ArbitrumRetryTx -[arbtxdeposit]: #ArbitrumDepositTx -[arbtxinternal]: #ArbitrumInternalTx -[hs]: #StartTxHook -[he]: #EndTxHook - -The following reference documents each type. - -### [`ArbitrumUnsignedTx`][arbitrumunsignedtx_link]{#ArbitrumUnsignedTx} - -Provides a mechanism for a user on L1 to message a contract on L2. This uses the bridge for authentication rather than requiring the user's signature. Note, the user's acting address will be remapped on L2 to distinguish them from a normal L2 caller. - -### [`ArbitrumContractTx`][arbitrumcontracttx_link]{#ArbitrumContractTx} - -These are like an [`ArbitrumUnsignedTx`][arbitrumunsignedtx_link] but are intended for smart contracts. These use the bridge's unique, sequential nonce rather than requiring the caller specify their own. An L1 contract may still use an [`ArbitrumUnsignedTx`][arbitrumunsignedtx_link], but doing so may necessitate tracking the nonce in L1 state. - -### [`ArbitrumDepositTx`][arbitrumdeposittx_link]{#ArbitrumDepositTx} - -Represents a user deposit from L1 to L2. This increases the user's balance by the amount deposited on L1. - -### [`ArbitrumSubmitRetryableTx`][arbitrumsubmitretryabletx_link]{#ArbitrumSubmitRetryableTx} - -Represents a retryable submission and may schedule an [`ArbitrumRetryTx`](#ArbitrumRetryTx) if provided enough gas. Please see the [retryables documentation](/how-arbitrum-works/arbos/introduction.md#Retryables) for more info. - -### [`ArbitrumRetryTx`][arbitrumretrytx_link]{#ArbitrumRetryTx} - -These are scheduled by calls to the `redeem` method of the [ArbRetryableTx](/build-decentralized-apps/precompiles/02-reference.md#arbretryabletx) precompile and via retryable auto-redemption. Please see the [retryables documentation](/how-arbitrum-works/arbos/introduction.md#Retryables) for more info. - -### [`ArbitrumInternalTx`][arbitruminternaltx_link]{#ArbitrumInternalTx} - -Because tracing support requires ArbOS's state-changes happen inside a transaction, ArbOS may create a transaction of this type to update its state in-between user-generated transactions. Such a transaction has a [`Type`][internaltype_link] field signifying the state it will update, though currently this is just future-proofing as there's only one value it may have. Below are the internal transaction types. - -#### [`InternalTxStartBlock`][arbinternaltxstartblock_link] - -Updates the L1 block number and L1 base fee. This transaction [is generated][block_generated_link] whenever a new block is created. They are [guaranteed to be the first][block_first_link] in their L2 block. - -[arbitrumunsignedtx_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L43 -[arbitrumcontracttx_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L104 -[arbitrumsubmitretryabletx_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L232 -[arbitrumretrytx_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L161 -[arbitrumdeposittx_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L338 -[arbitruminternaltx_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/internal_tx.go -[internaltype_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arb_types.go#L387 -[arbinternaltxstartblock_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/internal_tx.go#L22 -[block_generated_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/block_processor.go#L181 -[block_first_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/block_processor.go#L182 - -## Transaction Run Modes and Underlying Transactions - -A [geth message][geth_message_link] may be processed for various purposes. For example, a message may be used to estimate the gas of a contract call, whereas another may perform the corresponding state transition. Nitro Geth denotes the intent behind a message by means of its [`TxRunMode`][txrunmode_link], [which it sets][set_run_mode_link] before processing it. ArbOS uses this info to make decisions about the transaction the message ultimately constructs. - -A message [derived from a transaction][asmessage_link] will carry that transaction in a field accessible via its [`UnderlyingTransaction`][underlying_link] method. While this is related to the way a given message is used, they are not one-to-one. The table below shows the various run modes and whether each could have an underlying transaction. - -| Run Mode | Scope | Carries an Underlying Tx? | -| :--------------------------------------- | :---------------------- | :----------------------------------------------------------------------------------------------------------- | -| [`MessageCommitMode`][mc0] | state transition   | always | -| [`MessageGasEstimationMode`][mc1]   | gas estimation | when created via [NodeInterface](/build-decentralized-apps/nodeinterface/02-reference.mdx) or when scheduled | -| [`MessageEthcallMode`][mc2] | eth_calls | never | - -[mc0]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L654 -[mc1]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L655 -[mc2]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L656 -[geth_message_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L634 -[txrunmode_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L701 -[set_run_mode_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/internal/ethapi/api.go#L955 -[asmessage_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L676 -[underlying_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go#L700 - -## Arbitrum Chain Parameters - -Nitro's Geth may be configured with the following [l2-specific chain parameters][chain_params_link]. These allow the rollup creator to customize their rollup at genesis. - -### `EnableArbos` - -Introduces [ArbOS](/how-arbitrum-works/arbos/introduction.md), converting what would otherwise be a vanilla L1 chain into an L2 Arbitrum rollup. - -### `AllowDebugPrecompiles` - -Allows access to debug precompiles. Not enabled for Arbitrum One. When false, calls to debug precompiles will always revert. - -### `DataAvailabilityCommittee` - -Currently does nothing besides indicate that the rollup will access a data availability service for preimage resolution in the future. This is not enabled for Arbitrum One, which is a strict state-function of its L1 inbox messages. - -[chain_params_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/params/config_arbitrum.go#L25 - -## Miscellaneous Geth Changes - -### ABI Gas Margin - -Vanilla Geth's abi library submits txes with the exact estimate the node returns, employing no padding. This means a transaction may revert should another arriving just before even slightly change the transaction's codepath. To account for this, we've added a `GasMargin` field to `bind.TransactOpts` that [pads estimates][pad_estimates_link] by the number of basis points set. - -### Conservation of L2 ETH - -The total amount of L2 ether in the system should not change except in controlled cases, such as when bridging. As a safety precaution, ArbOS checks Geth's [balance delta][conservation_link] each time a block is created, [alerting or panicking][alert_link] should conservation be violated. - -### MixDigest and ExtraData - -To aid with [outbox proof construction][proof_link], the root hash and leaf count of ArbOS's [send merkle accumulator][merkle_link] are stored in the `MixDigest` and `ExtraData` fields of each L2 block. The yellow paper specifies that the `ExtraData` field may be no larger than 32 bytes, so we use the first 8 bytes of the `MixDigest`, which has no meaning in a system without miners/stakers, to store the send count. - -### Retryable Support - -Retryables are mostly implemented in [ArbOS](/how-arbitrum-works/arbos/introduction.md#retryables). Some modifications were required in Geth to support them. - -- Added ScheduledTxes field to ExecutionResult. This lists transactions scheduled during the execution. To enable using this field, we also pass the ExecutionResult to callers of ApplyTransaction. -- Added gasEstimation param to DoCall. When enabled, DoCall will also also executing any retryable activated by the original call. This allows estimating gas to enable retryables. - -### Added accessors - -Added [`UnderlyingTransaction`][underlyingtransaction_link] to Message interface -Added [`GetCurrentTxLogs`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/state/statedb_arbitrum.go) to StateDB -We created the AdvancedPrecompile interface, which executes and charges gas with the same function call. This is used by [Arbitrum's precompiles](/build-decentralized-apps/precompiles/01-overview.md), and also wraps Geth's standard precompiles. - -### WASM build support - -The WASM Arbitrum executable does not support file operations. We created [`fileutil.go`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/rawdb/fileutil.go) to wrap fileutil calls, stubbing them out when building WASM. [`fake_leveldb.go`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/ethdb/leveldb/fake_leveldb.go) is a similar WASM-mock for leveldb. These are not required for the WASM block-replayer. - -### Types - -Arbitrum introduces a new [`signer`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/arbitrum_signer.go), and multiple new [`transaction types`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/types/transaction.go). - -### ReorgToOldBlock - -Geth natively only allows reorgs to a fork of the currently-known network. In nitro, reorgs can sometimes be detected before computing the forked block. We added the [`ReorgToOldBlock`](https://github.com/OffchainLabs/go-ethereum/tree/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/blockchain_arbitrum.go#L38) function to support reorging to a block that's an ancestor of current head. - -### Genesis block creation - -Genesis block in nitro is not necessarily block #0. Nitro supports importing blocks that take place before genesis. We split out [`WriteHeadBlock`][writeheadblock_link] from genesis.Commit and use it to commit non-zero genesis blocks. - -[pad_estimates_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/accounts/abi/bind/base.go#L355 -[conservation_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/state/statedb.go#L42 -[alert_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/block_processor.go#L424 -[proof_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/system_tests/outbox_test.go#L26 -[merkle_link]: https://github.com/OffchainLabs/nitro/blob/8e786ec6d1ac3862be85e0c9b5ac79cbd883791c/arbos/merkleAccumulator/merkleAccumulator.go#L13 -[underlyingtransaction_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/state_transition.go#L69 -[writeheadblock_link]: https://github.com/OffchainLabs/go-ethereum/blob/7503143fd13f73e46a966ea2c42a058af96f7fcf/core/genesis.go#L415 diff --git a/arbitrum-docs/how-arbitrum-works/arbos/l2-l1-messaging.md b/arbitrum-docs/how-arbitrum-works/arbos/l2-l1-messaging.md deleted file mode 100644 index 11d173767..000000000 --- a/arbitrum-docs/how-arbitrum-works/arbos/l2-l1-messaging.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: 'L2 to L1 messaging and the outbox' -description: This concept page provides information about how arbitrary messages are passed from L2 to L1 -target_audience: developers who want to build on Arbitrum -content_type: concept ---- - -Arbitrum's Outbox system allows for arbitrary L2 to L1 contract calls; i.e., messages initiated from L2 which eventually resolve in execution on L1. L2-to-L1 messages (aka "outgoing" messages) bear many things in common with Arbitrum's [L1-to-L2 messages](/how-arbitrum-works/arbos/l1-l2-messaging.md) (Retryables), "in reverse" though with a few differences. - -### Protocol Flow - -Part of the L2 state of an Arbitrum chain — and consequently, part of what's asserted in every RBlock — is a Merkle root of all L2-to-L1 messages in the chain's history. Upon an asserted RBlock being confirmed (typically ~1 week after its asserted), this Merkle root is posted on L1 in the `Outbox` contract. The Outbox contract then lets users execute their messages — validating Merkle proofs of inclusion, and tracking which L2 to L1 messages have already been spent. - -### Client Flow - -From a client perspective, an L2 to L1 message begins with a call to the L2 [`ArbSys`](/build-decentralized-apps/precompiles/02-reference.md#arbsys) precompile contract's `sendTxToL1` method. Once the message is included in an assertion (typically within ~1 hour) and the assertion is confirmed (typically about ~ 1 week), any client can execute the message. To do this, the client first retrieves the proof data via a call to the Arbitrum chain's "virtual"/precompile-esque\*\* `NodeInterface` contract's `constructOutboxProof` method. The data returned can then be used in the `Outbox`'s `executeTransaction` method to perform the L1 execution. - -### Protocol Design Details - -An important feature in the design of the Outbox system is that calls to `confirmNode` have constant overhead. Requiring that `confirmNode` only update the constant-sized outgoing message root hash, and that users themselves carry out the final step of execution, achieves this goal; i.e., no matter the number of outgoing messages in the root, or the gas cost of executing them on L1, the cost of confirming nodes remains constant; this ensures that the RBlock confirmation processed can't be griefed. - -Unlike Retryables, which have an option to provide Ether for automatic L2 execution, outgoing messages can't provide in-protocol automatic L1 execution, for the simple reason that Ethereum itself doesn't offer scheduled execution affordances. However, application-layer contracts that interact with the Outbox could in principle be built to provide somewhat-analogous "execution market" functionality for outsourcing the final L1 execution step. - -Another difference between outgoing messages and Retryables is that Retryables have a limited lifetime before which they must be redeemed (or have their lifetime explicitly extended), whereas L2 to L1 messages are stored in L1 state, and thus persist permanently / have no deadline before which they must be executed. -The week long delay period before outgoing messages can be executed is inherent and fundamental to the nature of Arbitrum Rollup, or any Optimistic Rollup style L2; the moment a transaction is published on-chain, any observer can anticipate its result; however, for Ethereum itself to accept its result, the protocol must give time for Arbitrum validators to detect and prove fault if need-be. For a protocol overview, see [Inside Arbitrum](/how-arbitrum-works/inside-arbitrum-nitro.md) - -\*\* We refer to `NodeInterface` as a "virtual" contract; its methods are accessible via calls `0x00000000000000000000000000000000000000C8`, but it doesn't really live on chain. It isn't really a precompile, but behaves a lot like a precompile that can't receive calls from other contracts. This is a cute trick that let's us provide Arbitrum-specific data without having to implement a custom RPC. diff --git a/arbitrum-docs/how-arbitrum-works/bold/bold-economics-of-disputes.md b/arbitrum-docs/how-arbitrum-works/bold/bold-economics-of-disputes.mdx similarity index 100% rename from arbitrum-docs/how-arbitrum-works/bold/bold-economics-of-disputes.md rename to arbitrum-docs/how-arbitrum-works/bold/bold-economics-of-disputes.mdx diff --git a/arbitrum-docs/how-arbitrum-works/bold/gentle-introduction.md b/arbitrum-docs/how-arbitrum-works/bold/gentle-introduction.mdx similarity index 97% rename from arbitrum-docs/how-arbitrum-works/bold/gentle-introduction.md rename to arbitrum-docs/how-arbitrum-works/bold/gentle-introduction.mdx index 140c1e6da..5488e22ef 100644 --- a/arbitrum-docs/how-arbitrum-works/bold/gentle-introduction.md +++ b/arbitrum-docs/how-arbitrum-works/bold/gentle-introduction.mdx @@ -8,10 +8,6 @@ author: leeederek sme: leeederek --- -import PublicPreviewBannerPartial from './partials/_bold-public-preview-banner-partial.md'; - - - This introduction is for those who want to learn about BoLD: a new dispute protocol for Optimistic Rollups that can enable **permissionless validation for Arbitrum chains**. BoLD stands for Bounded Liquidity Delay and is currently deployed on a public testnet for anyone to join and test how challenges will work. This next-generation dispute protocol technology will soon be available for any Arbitrum chain, and pending a governance vote, will eventually be made available on Arbitrum Sepolia, Arbitrum One, and Arbitrum Nova. @@ -21,7 +17,7 @@ BoLD will eventually replace the current, permissioned fraud proof mechanism tha ## In a nutshell: - Validation for Arbitrum One and Arbitrum Nova is a privileged action currently limited to an [allow-listed set of parties, maintained by the Arbitrum DAO](https://docs.arbitrum.foundation/state-of-progressive-decentralization#allowlisted-validators) to reduce the risks of _[delay attacks](https://medium.com/offchainlabs/solutions-to-delay-attacks-on-rollups-434f9d05a07a)_. _Delay attacks_ are a class of attacks where malicious entities can open as many disputes as they are willing to forfeit bonds during the challenge period to delay confirmations of assertions (equal to the time needed to resolve those disputes one by one). -- BoLD, an acronym for Bounded Liquidity Delay, is a new challenge resolution protocol for Arbitrum chains that enables permissionless validation by mitigating the risks of delay attacks against [optimistic rollups like Arbitrum](/how-arbitrum-works/inside-arbitrum-nitro.md#arbitrum-rollup-protocol). This is possible because BoLD's design ensures disputes will be resolved within a fixed time window, currently set to equal 1 challenge period (~6.4 days) for Arbitrum One and Arbitrum Nova. If there is a dispute, BoLD guarantees the maximum total time to be equal to 2 challenge periods (1 for raising disputes, 1 for resolving disputes), a 2 day grace period for the Security Council to intervene if necessary, and a small delta for computing challenges. +- BoLD, an acronym for Bounded Liquidity Delay, is a new challenge resolution protocol for Arbitrum chains that enables permissionless validation by mitigating the risks of delay attacks against [optimistic rollups like Arbitrum](/how-arbitrum-works/06-optimistic-rollup.mdx). This is possible because BoLD's design ensures disputes will be resolved within a fixed time window, currently set to equal 1 challenge period (~6.4 days) for Arbitrum One and Arbitrum Nova. If there is a dispute, BoLD guarantees the maximum total time to be equal to 2 challenge periods (1 for raising disputes, 1 for resolving disputes), a 2 day grace period for the Security Council to intervene if necessary, and a small delta for computing challenges. - Enabling permissionless validation is key milestone on [Arbitrum’s journey to becoming a Stage 2 Rollup](https://docs.arbitrum.foundation/state-of-progressive-decentralization) - the most advanced and mature rollup technology categorization, according to [L2Beat](https://medium.com/l2beat/introducing-stages-a-framework-to-evaluate-rollups-maturity-d290bb22befe). With BoLD, **any honest party can validate and bond their funds to post a correct L2 state assertions to win disputes against malicious entities.** - BoLD is currently considered to be in `alpha` release and is deployed on a public testnet. [Follow this guide](https://github.com/OffchainLabs/BoLD-validator-starter-kit) to deploy a BoLD validator to test and explore, first hand, how BoLD works to secure Arbitrum chains. To learn more about BoLD, please check out the [BoLD whitepaper](https://arxiv.org/abs/2404.10491) and [BoLD's code and specifications on Github](https://github.com/OffchainLabs/BoLD). @@ -74,9 +70,9 @@ The BoLD protocol provides the guardrails and rules for how validators challenge Let’s dive in to an overview of how BoLD actually works. -1. **An assertion is made:** Validators begin by taking the most recent confirmed [RBlock](/how-arbitrum-works/inside-arbitrum-nitro.md#the-rollup-chain), called `Block A`, and assert that some number of transactions afterwards, using Nitro’s deterministic State Transition Function (STF), will result in an end state, `Block Z`. If a validator claims that the end state represented by `Block Z` is correct, they will bond their funds to `Block Z` and propose that state to be posted to Ethereum. If nobody disagrees after a certain amount of time, known as the challenge period, then the state represented by the RBlock `Block Z` is confirmed as the correct state of an Arbitrum chain. However, if someone disagrees with the end state `Block Z`, they can submit a challenge. This is where BoLD comes into play. +1. **An assertion is made:** Validators begin by taking the most recent confirmed [RBlock](/how-arbitrum-works/06-optimistic-rollup.mdx#the-rollup-chain), called `Block A`, and assert that some number of transactions afterwards, using Nitro’s deterministic State Transition Function (STF), will result in an end state, `Block Z`. If a validator claims that the end state represented by `Block Z` is correct, they will bond their funds to `Block Z` and propose that state to be posted to Ethereum. If nobody disagrees after a certain amount of time, known as the challenge period, then the state represented by the RBlock `Block Z` is confirmed as the correct state of an Arbitrum chain. However, if someone disagrees with the end state `Block Z`, they can submit a challenge. This is where BoLD comes into play. 2. **A challenge is opened:** When another validator observes and disagrees with the end state represented by `Block Z`, they can permissionlessly open a challenge by asserting and bonding capital to a claim on a different end state, represented by an RBlock `Block Y`. At this point in time, there are now 2 asserted states: `Block A → Block Z` and `Block A → Block Y`. Each of these asserted states, at this point in time now that there's a challenge, are referred to _edges_ while a Merkle tree of asserted states from some start to end point (e.g. `Block A → Block Z`) is more formally known as a _history commitment._ It is important to note that Ethereum at this point in time has no notion of which edge(s) is correct or incorrect - edges are simply a portion of a claim made by a validator about the history of the chain from some end state all the way back to some initial state. Also note that because a bond put up by a validator is tied to an assertion rather than the party who put up that bond, there can be any number of honest, anonymous parties that can open challenges against incorrect claims. It is important to note that the bonds put up to open challenges are held in a Gnosis Safe multi-sig wallet controlled by the Arbitrum Foundation. -3. **Multi-level, interactive dissection begins:** To resolve the dispute, the disagreeing entities will need to come to an agreement on what the _actual, correct_ asserted state should be. [It would be tremendously expensive to re-execute](/how-arbitrum-works/inside-arbitrum-nitro.md#why-interactive-proving-is-better) and compare everything from `Block A → Block Z` and `Block A → Block Y`, especially since there could be potentially millions of transactions in between `A`, `Z`, and `Y`. Instead, entities take turns bisecting their respective _history commitments_ until they arrive at a single step of instruction where an arbiter, like Ethereum, can declare a winner. Note that [this system is very similar to how challenges are resolved on Arbitrum chains today](/how-arbitrum-works/inside-arbitrum-nitro.md#challenges) - BoLD only changes some minor, but important, details in the resolution process. Let’s dive into what happens next: +3. **Multi-level, interactive dissection begins:** To resolve the dispute, the disagreeing entities will need to come to an agreement on what the _actual, correct_ asserted state should be. [It would be tremendously expensive to re-execute](/how-arbitrum-works/06-optimistic-rollup.mdx#why-interactive-proving-is-better) and compare everything from `Block A → Block Z` and `Block A → Block Y`, especially since there could be potentially millions of transactions in between `A`, `Z`, and `Y`. Instead, entities take turns bisecting their respective _history commitments_ until they arrive at a single step of instruction where an arbiter, like Ethereum, can declare a winner. Note that [this system is very similar to how challenges are resolved on Arbitrum chains today](/how-arbitrum-works/07-interactive-fraud-proofs.mdx) - BoLD only changes some minor, but important, details in the resolution process. Let’s dive into what happens next: 1. **Block challenges**: when a challenge is opened, the edges are called _level-zero edges_ since they are at the granularity of Arbitrum blocks. The disputing parties take turns bisecting their history commitments until they identify the specific block that they disagree on. 2. **Big-step challenge:** now that the parties have narrowed down their dispute to a single block, that we call `Block B`, the back-and-forth bisection exercise continues within that block. Note that `Block B` is claimed by all parties to be some state after the initial state `Block A` but before the final states `Block Z` and `Block Y`. This time, however, the parties will narrow down on a specific _range_ of instructions for the state transition function within the block - essentially working towards identifying a set of instructions within which their disagreement lies. This range is currently defined as 2^20 steps of WASM instructions, which is the assembly of choice for validating Arbitrum chains. 3. **One-step challenge:** within that range of 2^20 instructions, the back and forth bisecting continues until all parties arrive at a single step of instruction that they disagree on. At this point in time, parties agree on the initial state of Arbitrum before the step but disagree on the end state 1 step immediately after. Remember that since Arbitrum’s state is entirely deterministic, there is only 1 correct end state. diff --git a/arbitrum-docs/how-arbitrum-works/bold/partials/_bold-public-preview-banner-partial.md b/arbitrum-docs/how-arbitrum-works/bold/partials/_bold-public-preview-banner-partial.mdx similarity index 100% rename from arbitrum-docs/how-arbitrum-works/bold/partials/_bold-public-preview-banner-partial.md rename to arbitrum-docs/how-arbitrum-works/bold/partials/_bold-public-preview-banner-partial.mdx diff --git a/arbitrum-docs/how-arbitrum-works/bold/public-preview-expectations.md b/arbitrum-docs/how-arbitrum-works/bold/public-preview-expectations.mdx similarity index 96% rename from arbitrum-docs/how-arbitrum-works/bold/public-preview-expectations.md rename to arbitrum-docs/how-arbitrum-works/bold/public-preview-expectations.mdx index 3ad01f435..85791cdf7 100644 --- a/arbitrum-docs/how-arbitrum-works/bold/public-preview-expectations.md +++ b/arbitrum-docs/how-arbitrum-works/bold/public-preview-expectations.mdx @@ -14,10 +14,6 @@ Offchain Labs builds products in a way that aligns loosely with the spirit of "b To do this, some of our product offerings are documented with **public preview** disclaimers that look like this: -import PublicPreviewBannerPartial from './partials/_bold-public-preview-banner-partial.md'; - - - This banner's purpose is to set expectations while inviting readers like you to express your needs so that we can incorporate them into the way that we iterate on product. ### What to expect when using public preview offerings diff --git a/arbitrum-docs/how-arbitrum-works/fraud-proofs/challenge-manager.md b/arbitrum-docs/how-arbitrum-works/fraud-proofs/challenge-manager.md deleted file mode 100644 index 407347853..000000000 --- a/arbitrum-docs/how-arbitrum-works/fraud-proofs/challenge-manager.md +++ /dev/null @@ -1,64 +0,0 @@ -import ChallengeManagerDiagram from '../../diagrams/_challenge-manager.mdx'; - -# ChallengeManager - -The `ChallengeManager` arbitrates challenge games. Here's a diagram of the challenge state machine: - - - -## Block challenge - -The challenge begins by bisecting over global states (including block hashes). -Before actual machine execution is disputed, the dispute is narrowed down to an individual block. -Once the challenge has been bisected down to an individual block, -`challengeExecution` can be called by the current responder. -This operates similarly to a bisection in that the responder must provide a competing global state and machine state, -but it uses that information to transition to the execution challenge phase. - -## Execution challenge - -Once narrowed down to an individual block, the actual machine execution can be bisected. -Once the execution has been bisected down to an individual step, -`oneStepProveExecution` can be called by the current responder. -The current responder must provide proof data to execute a step of the machine. -If executing that step ends in a different state than was previously asserted, -the current responder wins the challenge. - -## General bisection protocol - -_**Note:** the term bisection in this document is used for clarity but refers to a dissection of any degree._ - -The `ChallengeLib` helper library contains a `hashChallengeState` method which hashes a list of segment hashes, -a start position, and a total segments length, which generates the `ChallengeLib.Challenge`'s `challengeStateHash`. -This is enough information to infer the position of each segment hash. -The challenge "degree" refers to the number of segment hashes minus one. -The distance (in steps) between one segment and the next is `floor(segmentsLength / degree)`, except for the -last pair of segments, where `segmentsLength % degree` is added to the normal distance, so that -the total distance is `segmentsLength`. - -A challenge begins with only two segments (a degree of one), which is the asserter's initial assertion. -Then, the bisection game begins on the challenger's turn. -In each round of the game, the current responder must choose an adjacent pair of segments to challenge. -By doing so, they are disputing their opponent's claim that starting with the first segment and executing -for the specified distance (number of steps) will result in the second segment. At this point the two parties -agree on the correctness of the first segment but disagree about the correctness of the second segment. -The responder must provide a bisection with a start segment equal to the first segment, but an end segment -different from the second segment. -In doing so, they break the challenge down into smaller distances, and it becomes their opponent's turn. -Each bisection must have degree `min(40, numStepsInChallengedSegment)`, ensuring the challenge makes progress. - -In addition, a segment with a length of only one step cannot be bisected. -What happens there is specific to the phase of the challenge, as either a `challengeExecution` or `oneStepProveExecution`. - -Note that unlike in a traditional bisection protocol, where one party proposes segments and the other decides which to challenge, -this protocol is symmetric in that both players take turns deciding where to challenge and proposing bisections -when challenging. - -## Winning the challenge - -Note that for the time being, winning the challenge isn't instant. -Instead, it simply makes the current responder the winner's opponent, -and sets the state hash to 0. In that state the party does not have any -valid moves, so it will eventually lose by timeout. -This is done as a precaution, so that if a challenge is resolved incorrectly, -there is time to diagnose and fix the error with a contract upgrade. diff --git a/arbitrum-docs/how-arbitrum-works/fraud-proofs/osp-assumptions.md b/arbitrum-docs/how-arbitrum-works/fraud-proofs/osp-assumptions.md deleted file mode 100644 index 93e04a2d1..000000000 --- a/arbitrum-docs/how-arbitrum-works/fraud-proofs/osp-assumptions.md +++ /dev/null @@ -1,75 +0,0 @@ -# One Step Proof Assumptions - -The One Step Proof (OSP) implementation makes certain assumptions about the cases that can arise -in a correct execution. This documents those assumptions about what's being executed. - -If a case is "unreachable", that is, the case is assumed to never arise in correct execution, -then the OSP can implement any instruction semantics in that case. - -- In a challenge between malicious parties, any case can arise. The challenge protocol must do - something safe in every case. But the instruction semantics can be weird in such cases because - if both parties to a challenge are malicious, the protocol doesn't care who wins the challenge. -- In a challenge with one honest party, the honest party will never need to one-step prove an - unreachable case. The honest party will only assert correct executions, so it will only have to - prove reachable cases. -- In a challenge with one honest party, the dishonest party could assert an execution that transitions - into an unreachable case, but such an execution must include an invalid execution of a reachable case - earlier in the assertion. Because a challenge involving an honest party will eventually require an OSP - over the first instruction where the parties disagree, the eventual OSP will be over the earlier point - of divergence, and not over the later execution from an unreachable case. - -In general, some unreachable cases will be detectable by the OSP checker and some will not. For safety, the -detectable unreachable cases should be defined by transition the machine into an error state, allowing -governance to eventually push an upgrade to recover from the error. An undetectable unreachable case, if -such a case were reached in correct execution, could lead to a security failure. - -The following assumptions, together, must prevent an unreachable case from arising in correct execution. - -## The WAVM code is generated by Arbitrator from valid WASM - -WAVM is the name of the custom instruction set similar to WASM used for proving. -Arbitrator transpiles WASM code into WAVM. -It also invokes wasm-validate from [wabt](https://github.com/WebAssembly/wabt) -(the WebAssembly Binary Toolkit) to ensure the input WASM is valid. -WAVM produced otherwise may not be executable, as it may try to close a non-existent block, -mismatch types, or do any other number of invalid things which are prevented by WASM validation. - -WAVM code generated from by Arbitrator from valid WASM is assumed to never encounter an unreachable case. - -## Inbox messages must not be too large - -The current method of inbox hashing requires the full inbox message be available for proving. -That message must not be too large as to prevent it from being supplied for proving, -which is enforced by the inboxes. - -The current length limit is 117,964 bytes, which is 90% of the -[max transaction size Geth will accept](https://github.com/ethereum/go-ethereum/blob/356bbe343a30789e77bb38f25983c8f2f2bfbb47/core/tx_pool.go#L53), -leaving 13,108 bytes for other proving data. - -## Requested preimages must be known and not too large - -WAVM has an opcode which resolves the preimage of a Keccak-256 hash. -This can only be executed if the preimage is already known to all nodes, -and can only be proven if the preimage isn't too long. Violations of this assumption are -undetectable by the OSP checker. - -The current length limit is 117,964 bytes for the reasons mentioned above. -Here's a list of which preimages may be requested by Nitro, and why they're known to all parties, -and not too large: - -### Block headers - -Nitro may request up to the last 256 L2 block headers. -The last block header is required to determine the current state, -and blocks before it are required to implement the `BLOCKHASH` evm instruction. - -This is safe as previous block headers are a fixed size, and are known to all nodes. - -### State trie access - -To resolve state, Nitro traverses the state trie by resolving preimages. - -This is safe as validators retain archive state of unconfirmed blocks, -each trie branch is of a fixed size, -and the only variable sized entry in the trie is contract code, -which is limited by EIP-170 to about 24KB. diff --git a/arbitrum-docs/how-arbitrum-works/fraud-proofs/wasm-wavm.md b/arbitrum-docs/how-arbitrum-works/fraud-proofs/wasm-wavm.md deleted file mode 100644 index 8e5d1bb01..000000000 --- a/arbitrum-docs/how-arbitrum-works/fraud-proofs/wasm-wavm.md +++ /dev/null @@ -1,61 +0,0 @@ -# WASM to WAVM - -Not all WASM instructions are 1:1 with WAVM opcodes. -This document lists those which are not, and explains how they're expressed in WAVM. -Many of the WAVM representations use opcodes not in WASM, -which are documented in [`wavm-custom-opcodes.md`](/how-arbitrum-works/fraud-proofs/wavm-custom-opcodes.md). - -## `block` and `loop` - -In WASM, a block contains instructions. -Branch instructions exit a fixed number of blocks, jumping to their destination. -A normal `block`'s destination is the end of the block, whereas a `loop`'s destination is the start of the loop. - -In WAVM, instructions are flat. -At transpilation time, any branch instructions are replaced with jumps to the corresponding block's destination. -This means that WAVM interpreters don't need to track blocks, and thus block instructions are unnecessary. - -## `if` and `else` - -These are translated to a block with an `ArbitraryJumpIf` as follows: - -``` -begin block with endpoint end - conditional jump to else - [instructions inside if statement] - branch - else: [instructions inside else statement] -end -``` - -## `br` and `br_if` - -`br` and `br_if` are translated into `ArbitraryJump` and `ArbitraryJumpIf` respectively. -The jump locations can be known at transpilation time, making blocks obsolete. - -## `br_table` - -`br_table` is translated to a check for each possible branch in the table, -and then if none of the checks hit, a branch of the default level. - -Each of the non-default branches has a conditional jump to a section afterwards, -containing a `drop` for the selector, and then a jump to the target branch. - -## `local.tee` - -`local.tee` is translated to a WAVM `Dup` and then a `LocalSet`. - -## `return` - -To translate a return, the number of return values must be known from the function signature. -A WAVM `MoveFromStackToInternal` is added for each return value. -Then, a loop checks `IsStackBoundary` (which implicitly pops a value) until it's true and the stack boundary has been popped. -Next, a `MoveFromInternalToStack` is added for each return value to put the return values back on the stack. -Finally, a WAVM `Return` is added, returning control flow to the caller. - -## Floating point instructions - -A floating point library module must be present to translate floating point instructions. -They are translated by bitcasting `f32` and `f64` arguments to `i32`s and `i64`s, -then a cross module call to the floating point library, -and finally bitcasts of any return values from `i32`s and `i64`s to `f32`s and `f64`s. diff --git a/arbitrum-docs/how-arbitrum-works/fraud-proofs/wavm-custom-opcodes.md b/arbitrum-docs/how-arbitrum-works/fraud-proofs/wavm-custom-opcodes.md deleted file mode 100644 index 66fc8c405..000000000 --- a/arbitrum-docs/how-arbitrum-works/fraud-proofs/wavm-custom-opcodes.md +++ /dev/null @@ -1,74 +0,0 @@ -# WAVM Custom opcodes not in WASM - -In addition to the MVP WASM specification, -WAVM implements the multi value and sign extension ops WASM proposals. - -WAVM also implements the following unique opcodes, -which are not part of WASM nor any WASM proposal. - -## Invariants - -Many of these opcodes have implicit invariants about what's on the stack, -e.g. "Pops an i32 from the stack" assumes that the top of the stack has an i32. -If these conditions are not satisfied, execution is generally not possible. -These invariants are maintained by WASM validation and Arbitrator codegen. (See [One Step Proof Assumptions](/how-arbitrum-works/fraud-proofs/osp-assumptions.md).) - -## Codegen internal - -These are generated when breaking down a WASM instruction that does many things into many WAVM instructions which each do one thing. -For instance, a WASM `local.tee` is implemented in WAVM with `dup` and then `local.set`, the former of which doesn't exist in WASM. - -Other times, these opcodes help out an existing WASM opcode by splitting out functionality. -For instance, the WAVM `return` opcode by itself does not clean up the stack, -but its WASM->WAVM codegen includes a loop that utilizes `IsStackBoundary` to perform the stack cleanup -specified for WASM's `return`. - -| Opcode | Name | Description | -| ------ | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 0x8000 | EndBlock | Pops an item from the block stack. | -| 0x8001 | EndBlockIf | Peeks the top value on the stack, assumed an i32. If non-zero, pops an item from the block stack. | -| 0x8002 | InitFrame | Pops a caller module index i32, then a caller module internals offset i32, and finally a return InternalRef from the stack. Creates a stack frame with the popped info and the locals merkle root in proving argument data. | -| 0x8003 | ArbitraryJumpIf | Pops an i32 from the stack. If non-zero, jumps to the program counter in the argument data. | -| 0x8004 | PushStackBoundary | Pushes a stack boundary to the stack. | -| 0x8005 | MoveFromStackToInternal | Pops an item from the stack and pushes it to the internal stack. | -| 0x8006 | MoveFromInternalToStack | Pops an item from the internal stack and pushes it to the stack. | -| 0x8007 | IsStackBoundary | Pops an item from the stack. If a stack boundary, pushes an i32 with value 1. Otherwise, pushes an i32 with value 0. | -| 0x8008 | Dup | Peeks an item from the stack and pushes another copy of that item to the stack. | - -The above opcodes eliminate the need for the following WASM opcodes (which are transpiled into other WAVM opcodes): - -- loop -- if/else -- br_table -- local.tee - -## Linking - -This is only generated to link modules together. -Each import is replaced with a local function consisting primarily of this opcode, -which handles the actual work needed to change modules. - -| Opcode | Name | Description | -| ------ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 0x8009 | CrossModuleCall | Pushes the current program counter, module number, and module's internals offset to the stack. Then splits its argument data into the lower 32 bits being a function index, and the upper 32 bits being a module index, and jumps to the beginning of that function. | - -## Host calls - -These are only used in the implementation of "host calls". -Each of these has an equivalent host call method, which can be invoked from libraries. -The exception is `CallerModuleInternalCall`, -which is used for the implementation of all of the `wavm_caller_*` host calls. -Those calls are documented in `wavm-modules.md`. - -For these instruction descriptions, all pointers and offsets are represented as WASM i32s. - -| Opcode | Name | Description | -| ------ | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 0x800A | CallerModuleInternalCall | Pushes the current program counter, module number, and module's internals offset (all i32s) to the stack. Then, it retrieves the caller module internals offset from the current stack frame. If 0, errors, otherwise, jumps to the caller module at function (internals offset + opcode argument data) and instruction 0. | -| 0x8010 | GetGlobalStateBytes32 | Pops a pointer and then an index from the stack. If the index is greater than or equal to the number of global state bytes32s, errors. If the pointer mod 32 is not zero, errors. If the pointer + 32 is outside the programs memory, errors. Otherwise, writes the global state bytes32 value of the specified index to the specified pointer in memory. | -| 0x8011 | SetGlobalStateBytes32 | Pops a pointer and then an index from the stack. If the index is greater than or equal to the number of global state bytes32s, errors. If the pointer mod 32 is not zero, errors. If the pointer + 32 is outside the programs memory, errors. Otherwise, reads a bytes32 from the specified pointer in memory and sets the global state bytes32 value of the specified index to it. | -| 0x8012 | GetGlobalStateU64 | Pops a pointer and then an index from the stack. If the index is greater than or equal to the number of global state u64s, errors. If the pointer mod 32 is not zero, errors. If the pointer + 8 is outside the programs memory, errors. Otherwise, writes the global state u32 value of the specified index to the specified pointer in memory. | -| 0x8013 | SetGlobalStateU64 | Pops a pointer and then an index from the stack. If the index is greater than or equal to the number of global state u64s, errors. If the pointer mod 32 is not zero, errors. If the pointer + 8 is outside the programs memory, errors. Otherwise, reads a u64 from the specified pointer in memory and sets the global state u64 value of the specified index to it. | -| 0x8020 | ReadPreImage | Pops an offset and then a pointer from the stack. If the pointer mod 32 is not zero, errors. If the pointer + 32 is outside the programs memory, errors. Reads a 32 byte Keccak-256 hash from the specified pointer in memory. Writes up to 32 bytes of the preimage to that hash, beginning with the `offset` byte of the preimage. If `offset` is greater than or equal to the number of bytes in the preimage, writes nothing. Pushes the number of bytes written to the stack as an i32. | -| 0x8021 | ReadInboxMessage | Pops an offset, then a pointer, and then an i64 message number from the stack. If the pointer mod 32 is not zero, errors. If the pointer + 32 is outside the programs memory, errors. Attempts to read an inbox message from the inbox identifier contained in the argument data (0 for the sequencer inbox, 1 for the delayed inbox) at the specified message number. If this exceeds the machine's inbox limit, enters the "too far" state. Otherwise, writes up to 32 bytes of the specified inbox message, beginning with the `offset` byte of the message. If `offset` is greater than or equal to the number of bytes in the preimage, writes nothing. Pushes the number of bytes written to the stack as an i32. | -| 0x8022 | HaltAndSetFinished | Sets the machine status to finished, halting execution and marking it as a success. | diff --git a/arbitrum-docs/how-arbitrum-works/fraud-proofs/wavm-floats.md b/arbitrum-docs/how-arbitrum-works/fraud-proofs/wavm-floats.md deleted file mode 100644 index 1431c5b06..000000000 --- a/arbitrum-docs/how-arbitrum-works/fraud-proofs/wavm-floats.md +++ /dev/null @@ -1,32 +0,0 @@ -# WAVM Floating point implementation - -Implementing correct, consistent, and deterministic floating point operations directly in WAVM -(meaning both a Rust Arbitrator implementation and Solidity OSP implementation) -would be an extremely tricky endeavor. -WASM specifies floating point operations as being compliant to IEEE 754-2019, -which is not deterministic, and full of edge cases. - -Instead, floating point operations (apart from trivial bit-casts like i32 \<-\> f32) -are implemented using the C Berkeley SoftFloat-3e library running inside WAVM. -Arbitrator links other WAVM guests against this, -by replacing float point operations with cross module calls to the library. - -Berkeley SoftFloat does not implement all necessary floating point operations, however. -Most importantly, it does not provide a min function, despite IEEE 754-2019 specifying one. -The implementation of these operations, -along with the export of convenient APIs for WASM opcode implementations, -are contained in bindings32.c for 32 bit integers and bindings64.c for 64 bit integers. - -This ensures that floating point operations are deterministic and consistent between Arbitrator and the OSP, -as they are implemented exclusively using operations already known to be deterministic and consistent. -However, it does not ensure that the floating point operations are perfectly compliant to the WASM specification. -Go uses floating points in its JS\<-\>Go WASM interface, -and floating points may be used outside core state transition code for imprecise computations, -but the former is well exercised as used in Nitro, -and the latter generally doesn't rely on details like the minimum of NaN and infinity. - -## Known divergences from the WASM specification - -Floating point to integer truncation will saturate on overflow, instead of erroring. -This is generally safer, because on x86, overflowing simply produces an undefined result. -A WASM proposal exists to add new opcodes which are defined to saturate, but it's not widely adopted. diff --git a/arbitrum-docs/how-arbitrum-works/fraud-proofs/wavm-modules.md b/arbitrum-docs/how-arbitrum-works/fraud-proofs/wavm-modules.md deleted file mode 100644 index 1bace30e4..000000000 --- a/arbitrum-docs/how-arbitrum-works/fraud-proofs/wavm-modules.md +++ /dev/null @@ -1,57 +0,0 @@ -# WAVM Modules - -WASM natively has a notion of modules. -Normally, in WASM, a module is the entire program. -A `.wasm` file represents one module, and generally they aren't combined. -An exception to this is C compiled via Clang, where wasm files are also used as object files, -but [its linking scheme](https://github.com/WebAssembly/tool-conventions/blob/main/Linking.mdx) is not supported in other languages. - -In WAVM this is extended to make the executing program composed of multiple modules. -These may call each other, and library modules may write to their caller's memory to return results. - -## The entrypoint module - -The entrypoint module is where execution begins. -It calls modules' `start` functions if specified, -and then calls the main module's main function, which is language specific. -For Go it sets argv to `["js"]` to match the JS environment, and calls `run`. -For Rust it calls `main` with no arguments. - -## Library exports - -Libraries may export functions with the name pattern `module__name`, -which future libraries or the main module can import as `"module" "name"`. - -For instance, this is used for wasi-stub to provide functions rust imports according -to the WebAssembly System Interface. - -## Floating point operations - -To provide floating point operations for future libraries, -the soft float library exports functions which perform floating point ops. -These have the same name as the WASM instruction names, except `.` is replaced with `_`. -Their type signature is also the same, except all `f32`s and `f64`s are bitcasted to `i32`s and `i64`s. - -Future modules can implicitly use these by using WASM floating point operations, -which are replaced at the WASM->WAVM level with bitcasts and cross module calls to these functions. - -## WAVM guest calls - -Libraries may call the main module's exports via `"env" "wavm_guest_call__*"`. - -For instance, go-stub calls Go's resume function when queueing async events -via `wavm_guest_call_resume()`, and then retrieves the new stack pointer with -`wavm_guest_call_getsp()`. - -## Caller module internals call - -Every stack frame retains its caller module and its caller module's "internals offset", -which is the first internal function index. -WAVM appends 4 "internal" functions to each module, which perform a memory load or store of 1 or 4 bytes. - -Via `wavm_caller_{load,store}{8,32}`, a library may access its caller's memory, -which is implemented by calling these internal functions of the caller's module. -Only libraries can access their caller's memory; the main module cannot. - -For instance, this is used to read arguments from and write return values to the Go stack, -when Go calls into go-stub. diff --git a/arbitrum-docs/how-arbitrum-works/gas-fees.md b/arbitrum-docs/how-arbitrum-works/gas-fees.md deleted file mode 100644 index f29dd590b..000000000 --- a/arbitrum-docs/how-arbitrum-works/gas-fees.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -author: dzgoldman ---- - -# Gas and Fees - -There are two parties a user pays when submitting a tx: - -- the poster, if reimbursable, for L1 resources such as the L1 calldata needed to post the tx -- the network fee account for L2 resources, which include the computation, storage, and other burdens L2 nodes must bear to service the tx - -The L1 component is the product of the transaction's estimated contribution to its batch's size — computed using Brotli on the transaction by itself — and the L2's view of the L1 data price, a value which dynamically adjusts over time to ensure the batch-poster is ultimately fairly compensated. For details, see [L1 Pricing](/how-arbitrum-works/l1-gas-pricing.md). - -The L2 component consists of the traditional fees Geth would pay to stakers in a vanilla L1 chain, such as the computation and storage charges applying the state transition function entails. ArbOS charges additional fees for executing its L2-specific [precompiles](/build-decentralized-apps/precompiles/01-overview.md), whose fees are dynamically priced according to the specific resources used while executing the call. - -## Gas Price Floor - -The L2 gas price on a given Arbitrum chain has a set floor, which can be queried via [ArbGasInfo](/build-decentralized-apps/precompiles/02-reference.md#arbgasinfo)'s `getMinimumGasPrice` method (currently @arbOneGasFloorGwei@ gwei on Arbitrum One and @novaGasFloorGwei@ gwei on Nova). - -## Estimating Gas - -Calling an Arbitrum Node's `eth_estimateGas` RPC gives a value sufficient to cover the full transaction fee at the given L2 gas price; i.e., the value returned from `eth_estimateGas` multiplied by the L2 gas price tells you how much total Ether is required for the transaction to succeed. Note that this means that for a given operation, the value returned by `eth_estimateGas` will change over time (as the L1 calldata price fluctuates.) (See [2-D fees](https://medium.com/offchainlabs/understanding-arbitrum-2-dimensional-fees-fd1d582596c9) and [How to estimate gas in Arbitrum](/build-decentralized-apps/02-how-to-estimate-gas.md) for more.) - -## Tips in L2 - -The sequencer prioritizes transactions on a first-come first-served basis. Because tips do not make sense in this model, they are ignored. Arbitrum users always just pay the basefee regardless of the tip they choose. - -## Gas Estimating Retryables - -When a transaction schedules another, the subsequent transaction's execution [will be included][estimation_inclusion_link] when estimating gas via the node's RPC. A transaction's gas estimate, then, can only be found if all the transactions succeed at a given gas limit. This is especially important when working with retryables and scheduling redeem attempts. - -Because a call to [`redeem`](/build-decentralized-apps/precompiles/02-reference.md#arbretryabletx) donates all of the call's gas, doing multiple requires limiting the amount of gas provided to each subcall. Otherwise the first will take all of the gas and force the second to necessarily fail irrespective of the estimation's gas limit. - -Gas estimation for Retryable submissions is possible via the [NodeInterface](/build-decentralized-apps/nodeinterface/02-reference.mdx) and similarly requires the auto-redeem attempt to succeed. - -[estimation_inclusion_link]: https://github.com/OffchainLabs/go-ethereum/blob/d52739e6d54f2ea06146fdc44947af3488b89082/internal/ethapi/api.go#L999 diff --git a/arbitrum-docs/how-arbitrum-works/l1-gas-pricing.md b/arbitrum-docs/how-arbitrum-works/l1-gas-pricing.md deleted file mode 100644 index a89111b56..000000000 --- a/arbitrum-docs/how-arbitrum-works/l1-gas-pricing.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -author: dzgoldman ---- - -# L1 gas pricing - -ArbOS dynamically prices L1 gas, with the price adjusting to ensure that the amount collected in L1 gas fees is as close as possible to the costs that must be covered, over time. - -## L1 fee collection - -A transaction is charged for L1 gas if and only if it arrived as part of a sequencer batch. This means that someone would have paid for L1 gas to post the transaction on the L1 chain. - -The estimated cost of posting a transaction on L1 is the product of the transaction's estimated size, and the current L1 Gas Basefee. This estimated cost is divided by the current L2 gas basefee to obtain the amount of L2 gas that corresponds to the L1 operation (more information about this can be found in [this article][two_dimensional_fees_medium_article_link]). - -The estimated size is measured in L1 gas and is calculated as follows: first, compress the transaction's data using the brotli-zero algorithm, then multiply the size of the result by 16. (16 is because L1 charges 16 gas per byte. L1 charges less for bytes that are zero, but that doesn't make sense here.) Brotli-zero is used in order to reward users for posting transactions that are compressible. Ideally we would like to reward for posting transactions that contribute to the compressibility (using the brotli compressor) of the entire batch, but that is a difficult notion to define and in any case would be too expensive to compute at L2. Brotli-zero is an approximation that is cheap enough to compute. - -L1 gas fee funds that are collected from transactions are transferred to a special [`L1PricerFundsPool`][l1pricerfundspool_link] account, so that account's balance represents the amount of funds that have been collected and are available to pay for costs. - -The L1 pricer also records the total number of "data units" (the sum of the estimated sizes, after multiplying by 16) that have been received. - -[l1pricerfundspool_link]: https://github.com/OffchainLabs/nitro/blob/3f4939df1990320310e7f39e8abb32d5c4d8045f/arbos/l1pricing/l1pricing.go#L46 -[two_dimensional_fees_medium_article_link]: https://medium.com/offchainlabs/understanding-arbitrum-2-dimensional-fees-fd1d582596c9 - -## L1 costs - -There are two types of L1 costs: batch posting costs, and rewards. - -Batch posting costs reflect the actual cost a batch poster pays to post batch data on L1. Whenever a batch is posted, the L1 contract that records the batch will send a special "batch posting report" message to L2 ArbOS, reporting who paid for the batch and what the L1 basefee was at the time. This message is placed in the chain's delayed inbox, so it will be delivered to L2 ArbOS after some delay. - -When a batch posting report message arrives at L2, ArbOS computes the cost of the referenced batch by multiplying the reported basefee by the batch's data cost. (ArbOS retrieves the batch's data from its inbox state, and computes the L1 gas that the batch would have used by counting the number of zero bytes and non-zero bytes in the batch.) The resulting cost is recorded by the pricer as funds due to the party who is reported to have submitted the batch. - -The second type of L1 cost is an optional (per chain) per-unit reward for handling transaction calldata. In general the reward might be paid to the sequencer, or to members of the Data Availability Committee in an AnyTrust chain, or to anyone else who incurs per-calldata-byte costs on behalf of the chain. The reward is a fixed number of wei per data unit, and is paid to a single address. - -The L1 pricer keeps track of the funds due to the reward address, based on the number of data units handled so far. This amount is updated whenever a batch posting report arrives at L2. - -## Allocating funds and paying what is owed - -When a batch posting report is processed at L2, the pricer allocates some of the collected funds to pay for costs incurred. To allocate funds, the pricer considers three timestamps: - -- `currentTime` is the current time, when the batch posting report message arrives at L2 -- `updateTime` is the time at which the reported batch was submitted (which will typically be around 20 minutes before currentTime) -- `lastUpdateTime` is the time at which the previous reported batch was submitted - -The pricer computes an allocation fraction `F = (updateTime-lastUpdateTime) / (currentTime-lastUpdateTime)` and allocates a fraction `F` of funds in the `L1PricerFundsPool` to the current report. The intuition is that the pricer knows how many funds have been collected between `lastUpdateTime` and `currentTime`, and we want to figure out how many of those funds to allocate to the interval between `lastUpdateTime` and `updateTime`. The given formula is the correct allocation, if we assume that funds arrived at a uniform rate during the interval between `lastUpdateTime` and `currentTime`. The pricer similarly allocates a portion of the total data units to the current report. - -Now the pricer pays out the allocated funds to cover the rewards due and the amounts due to batch posters, reducing the balance due to each party as a result. If the allocated funds aren't sufficient to cover everything that is due, some amount due will remain. If all of the amount due can be covered with the allocated funds, any remaining allocated funds are returned to the `L1PricerFundsPool`. - -## Adjusting the L1 gas basefee - -After allocating funds and paying what is owed, the L1 Pricer adjusts the L1 Gas Basefee. The goal of this process is to find a value that will cause the amount collected to equal the amount owed over time. - -The algorithm first computes the surplus (funds in the `L1PricerFundsPool`, minus total funds due), which might be negative. If the surplus is positive, the L1 Gas Basefee is reduced, so that the amount collected over a fixed future interval will be reduced by exactly the surplus. If the surplus is negative, the Basefee is increased so that the shortfall will be eliminated over the same fixed future interval. - -A second term is added to the L1 Gas Basefee, based on the derivative of the surplus (surplus at present, minus the surplus after the previous batch posting report was processed). This term, which is multiplied by a smoothing factor to reduce fluctuations, will reduce the Basefee if the surplus is increasing, and increase the Basefee if the surplus is shrinking. - -## Getting L1 fee info - -The L1 gas basefee can be queried via [`ArbGasInfo.getL1BaseFeeEstimate`](/build-decentralized-apps/precompiles/02-reference.md#arbgasinfo). To estimate the L1 fee a transaction will use, the [NodeInterface.gasEstimateComponents()](/build-decentralized-apps/nodeinterface/02-reference.mdx) or [NodeInterface.gasEstimateL1Component()](/build-decentralized-apps/nodeinterface/02-reference.mdx) method can be used. - -Arbitrum transaction receipts include a `gasUsedForL1` field, showing the amount of gas used on L1 in units of L2 gas. diff --git a/arbitrum-docs/how-arbitrum-works/sequencer.md b/arbitrum-docs/how-arbitrum-works/sequencer.md deleted file mode 100644 index 61e0df99a..000000000 --- a/arbitrum-docs/how-arbitrum-works/sequencer.md +++ /dev/null @@ -1,34 +0,0 @@ -# The Sequencer and Censorship Resistance - -The Sequencer is a specially designated Arbitrum full node which, under normal conditions, is responsible for submitting users’ transactions onto L1. In principle, a chain’s Sequencer can take different forms; as [Arbitrum One currently stands](https://docs.arbitrum.foundation/state-of-progressive-decentralization), the Sequencer is a single, centralized entity; eventually, sequencing affordances could be given to a distributed committee of sequencers which come to consensus on ordering. However, regardless of its form, the Sequencer has a fundamental limitation that doesn’t apply to any other part of the system: it must operate under its own security assumptions; i.e., it can’t, in principle, derive security directly from layer 1. This brings up the question of how Arbitrum Rollup maintains its claim to censorship resistance when-and-if the Sequencer misbehaves. - -Here we will describe the mechanics of how the Sequencer typically operates, and how any user can bypass the Sequencer entirely to submit any Arbitrum transaction (including one that, say, initiates an L2 to L1 message to withdraw funds) directly from layer 1. Thus mechanism thereby preserves censorship resistance even if the Sequencer is being completely unresponsive or even malicious. - -## The Core Inbox - -When we talk about “submitting a transaction into an Arbitrum chain,” we’re talking about getting it included into the chain’s core Inbox, represented by the `sequencerInboxAccs` byte array in `Bridge`. Once transactions are included in the core Inbox, their ordering is fixed, execution is fully deterministic, and we can trustlessly treat the resultant state as having L1-level finality (see “Transaction Lifecycle”). The Sequencer’s role (or lack thereof) concerns strictly what happens prior; i.e., how a transaction makes its way into the core Inbox. We’ll break down the possible routes a transaction can take into two scenarios: a well-behaved Sequencer, and a faulty Sequencer. - -## Happy/Common Case: Sequencer Is Live and Well-behaved - -Here, we start by assuming that the Sequencer is fully operational, and is running with the intent of processing users’ transactions in as safe and timely a manner as possible. The Sequencer can receive a user’s transaction two ways — either directly via an RPC request, or via the underlying L1. - -If a user is posting a “standard” Arbitrum transaction (i.e., interacting with an L2 native dapp), the user will submit the signed transaction directly to the Sequencer, much like how a user submits a transaction to an Ethereum node when interacting with L1. Upon receiving it, the Sequencer will execute it and nearly instantaneously deliver the user a receipt. Some short time later — [usually no more than a few minutes](https://arbiscan.io/batches) — the Sequencer will include the user’s transaction in a batch and post it on L1 by calling one of the `SequencerInbox`’s `addSequencerL2Batch` methods. Note that only the Sequencer has the authority to call these methods; this assurance that no other party can include a message directly is, in fact, the very thing that gives the Sequencer the unique ability to provide instant, "soft-confirmation" receipts. -Once posted in a batch, the transactions have L1-level finality. - -Alternatively, a user can submit their L2 message to the Sequencer by posting it on the underlying L1. This path is necessary if the user wishes to perform some [L1 operation along with the L2](/how-arbitrum-works/arbos/l1-l2-messaging.md) message and to preserve atomicity between the two — the textbook example here being a token deposit via a [bridge](/build-decentralized-apps/token-bridging/01-overview.md) (escrow on L1, mint on L2). The user does this by publishing an L1 transaction (i.e., sending a normal transaction to an L1 node) that calls one of the relevant methods on the `Inbox` contract; i.e., `sendUnsignedTransaction`. This adds a message onto what we’ll call “the delayed Inbox”, (represented by the `delayedInboxAccs` in the `Bridge` contract), which is effectively a queue that messages wait in before being moved over to the core `Inbox`. The Sequencer will emit an L2 receipt about ~10 minutes after the transaction has been included in the delayed Inbox (the reason for this delay is to minimize the risk of short term L1 reorgs which could in turn cause an L2 reorg and invalidate the Sequencer’s L2 receipts.) Again, the last step is for the Sequencer to include the L2 message in a batch — when calling the batch submission methods, the Sequencer specifies how many messages in the delayed inbox to include — finalizing the transaction. - -In sum — in either happy case, the user first delivers their message to the Sequencer, who in turn ensures that it arrives in the core Inbox. - -## Unhappy/Uncommon Case: Sequencer Isn’t Doing Its Job - -Now let’s suppose the Sequencer, for whatever reason, is entirely failing to carry out its task of submitting messages. A user can still get their transaction included in two steps: - -First, they submit their L2 message via L1 into the delayed Inbox as described above: note that although atomic cross-chain messages are the common case for using the delayed Inbox, it can in principle be used to submit _any_ L2 message. - -Once in the delayed Inbox, we obviously can’t rely on the Sequencer to include the transaction in a batch. Instead, we can use `SequencerInbox`’s `forceInclusion` method. Once a message has been in the delayed Inbox for a sufficient amount of time, `forceInclusion` can be called to move it from the delayed Inbox into the core Inbox, at which point it’s finalized. Crucially, any account can call `forceInclusion`. - -Currently, on Arbitrum One, this delay time between submission and force inclusion is roughly @arbOneForceIncludePeriodHours@ hours, as specified by `maxTimeVariation.delayBlocks` / `maxTimeVariation.delaySeconds`. A force inclusion from L1 would directly affect the state for any unconfirmed L2 transactions; keeping conservatively high delay value ensures it should only be used under extraordinary circumstances. - -On top of the delay itself, the `forceInclusion` path has the downside of uncertainty around transaction ordering; i.e., while waiting for a message's max delay to pass, a malicious Sequencer could, in principle, directly post messages in front of it. However, there’s ultimately nothing the Sequencer can do to stop it from being included in the core Inbox, at which point its ordering is finalized. - -While the slow, “unhappy” path isn’t optimal, and should rarely, if ever, be necessary, its availability as an option ensures Arbitrum Rollup always preserves its trustless security model, even if the permissioned parts of the system act faulty. diff --git a/arbitrum-docs/how-arbitrum-works/timeboost/gentle-introduction.mdx b/arbitrum-docs/how-arbitrum-works/timeboost/gentle-introduction.mdx new file mode 100644 index 000000000..aaf7cffaa --- /dev/null +++ b/arbitrum-docs/how-arbitrum-works/timeboost/gentle-introduction.mdx @@ -0,0 +1,142 @@ +--- +title: 'A gentle Introduction: Timeboost' +sidebar_label: 'A gentle introduction' +description: 'Learn how Timeboost works and how it can benefit your Arbitrum-based project.' +author: leeederek +sme: leeederek +user_story: As a current or prospective Arbitrum user, I want to understand how Timeboost works and how to use it. +content_type: gentle-introduction +--- + +import ImageWithCaption from '@site/src/components/ImageCaptions/'; + +This introduction will walk you through Arbitrum Timeboost: a novel transaction ordering policy for Arbitrum chains that allows chain owners to capture the Maximal Extractable Value (MEV) on their chain and reduce spam, all while preserving fast block times and protecting users from harmful types of MEV, such as sandwich attacks and front-running. + +Timeboost is the culmination of over a year of research and development by the team at Offchain Labs and will soon be available for any Arbitrum chain, including Arbitrum One and Arbitrum Nova (should the Arbitrum DAO choose to adopt it). Like all features and upgrades to the Arbitrum technology stack, Timeboost will be rolled out on Arbitrum Sepolia first for testing, and chain owners will have the option of adopting Timeboost at any time or customizing Timeboost in any way they choose. + +### In a nutshell + +- The current "First-Come, First-Serve (FCFS)" ordering policy has many benefits, including a great UX and protection from harmful types of MEV. However, nearly all MEV on the chain is extracted by searchers who invest wastefully in hardware and spamming to win latency races (which negatively strains the network and leads to congestion). Timeboost is a new transaction ordering policy that preserves many of the great benefits of FCFS while unlocking a path for chain owners to capture some of the available MEV on their network and introducing an auction to reduce latency, racing, and, ultimately, spam. +- Timeboost introduces a few new components to an Arbitrum chain’s infrastructure: a sealed-bid second-price auction and a new "express lane" at an Arbitrum chain’s sequencer. Valid transactions submitted to the express lane will be sequenced immediately with no delay, while all other transactions submitted to the chain’s sequencer will experience a nominal delay (default: 200ms). The auction winner is granted the sole right to control the express lane for pre-defined, temporary intervals. The default block time for Arbitrum chains will continue to be industry-leading at 250ms, even with Timeboost enabled. What will change with Timeboost is that some transactions not in the express lane will be delayed to the next block. +- Timeboost is an optional feature for Arbitrum chains aimed at two types of groups of entities: (1) chain owners and their ecosystems and (2) sophisticated on-chain actors and searchers. Chain owners can use Timeboost to capture additional revenue from the MEV their chain generates already, and sophisticated on-chain actors and searchers will spend their resources on buying rights for the express lane (instead of spending those resources on winning latency races, which otherwise leads to spam and congestion on the network). +- Timeboost will work with both centralized and [decentralized sequencer setups](https://medium.com/@espressosys/espresso-systems-and-offchain-labs-publish-decentralized-timeboost-specification-b29ff20c5db8). The specification for a centralized sequencer is public ([here](https://github.com/OffchainLabs/timeboost-design)) and the [proposal before the Arbitrum DAO](https://forum.arbitrum.foundation/t/constitutional-aip-proposal-to-adopt-timeboost-a-new-transaction-ordering-policy/25167/1) allows us to deliver Timeboost to market sooner, rather than waiting until the design with a decentralized sequencer set up and its implementation are complete. + +## Why do Arbitrum chains need Timeboost? + +Today, Arbitrum chains order incoming transactions on a "First-Come, First-Serve (FCFS)" basis. This ordering policy was chosen as the default for Arbitrum chains because it is simple to understand and implement, enables fast block times (starting at 250ms and down to 100ms if desired), and protects users from harmful types of MEV like front-running & sandwich attacks. + +However, there are a few downsides to an FCFS ordering policy. Under FCFS, searchers are incentivized to participate in and try to win latency races through investments in off-chain hardware. This means that for searchers on Arbitrum chains, generating a profit from arbitrage and liquidation opportunities involves a lot of spam, placing stress on chain infrastructure and contributing to congestion. Additionally, all of the captured MEV on an Arbitrum chain today under FCFS goes to searchers - returning none of the available MEV to the chain owner or the applications on the chain. + +Timeboost retains most FCFS benefits while addressing FCFS limitations. + +#### Timeboost preserves the great UX that Arbitrum chains are known for + +- The default block time for Arbitrum chains will continue to be industry-leading at 250ms, even after Timeboost. What will change with Timeboost is that some transactions not in the express lane will be delayed to the next block. + +#### With Timeboost, Arbitrum chains will continue to protect users from harmful types of MEV + +- Timeboost only grants the auction winner a _temporary time advantage_ - not the power to view or reorder incoming transactions or be the first in every block. Furthermore, the transactions mempool will continue to be private, which means users with Timeboost enabled will continue to be protected from harmful MEV-like front-running and sandwich attacks. + +#### Timeboost unlocks a new value accrual path for chain owners + +- Chain owners may use Timeboost to capture a portion of the available MEV on their chain that would have otherwise gone entirely to searchers. There are many flavors of this, too - including custom gas tokens and/or redistribution of these proceeds back to the applications and users on the chain. + +#### Timeboost may help reduce spam and congestion on a network + +- By introducing the ability to “purchase a time advantage” through the Timeboost auction, it is expected that rational, profit-seeking actors will spend on auctions _instead of_ investing in hardware or infrastructure to win latency races. This diversion of resources by these actors is expected to reduce FCFS MEV-driven spam on the network. + +## What is Timeboost, and how does it work? + +Timeboost is a _transaction ordering policy_. It's a set of rules that the sequencer of an Arbitrum chain is trusted to follow when ordering transactions submitted by users. In the near future, multiple sequencers will be able to enforce those rules with decentralized Timeboost. + +For Arbitrum chains, the sequencer’s sole job is to take arriving, valid transactions from users, place them into an order dictated by the transaction ordering policy, and then publish the final sequence to a real-time feed and in compressed batches to the chain’s data availability layer. The current transaction ordering policy is FCFS, and Timeboost is a modified FCFS ordering policy. + +Timeboost is implemented using three separate components that work together: + +- **A special “express lane”** which allows valid transactions to be sequenced as soon as the sequencer receives them for a given round. +- **An off-chain auction** to determine the controller of the express lane for a given round. This auction is managed by an autonomous auctioneer. +- **An auction contract** deployed on the target chain to serve as the canonical source of truth for the auction results and handling of auction proceeds. + +To start, the default duration of a round is 60 seconds. Transactions not in the express lane will be subject to a default 200-millisecond artificial delay to their arrival timestamp before their transaction is sequenced, which means that some non-express lane transactions may get delayed to the next block. It’s important to note that the default Arbitrum block time will remain at 250 milliseconds (which can be adjusted to 100 milliseconds if desired). Let’s dive into how each of these components works. + +### The express lane + +![using the express lane](./images/centralized-timeboost-express-lane-workflow.jpg) +The express lane is implemented using a special endpoint on the sequencer, formally titled `timeboost_sendExpressLaneTransaction`. This endpoint is special because transactions submitted to it will be sequenced immediately by the sequencer, hence the name, express lane. The sequencer will only accept valid transaction payloads to this endpoint if they are correctly signed by the current round’s express lane controller. Other transactions can still be submitted to the sequencer as normal, but these will be considered non-express lane transactions and will, therefore, have their arrival timestamp delayed by 200 milliseconds. It is important to note that transactions from both the express and non-express lanes are eventually sequenced into a single, ordered stream of transactions for node operators to produce an assertion and later post the data to a data availability layer. The express lane controller does _not_: + +- Have the right to re-order transactions. +- Have a guarantee that their transactions will always be first at the “top-of-the-block.” +- Guarantee a profit at all. + +The value of the express lane will be the sum of how much MEV the express lane controller predicts they can extract during the upcoming round (i.e., MEV opportunity estimates made before the auction closes) _plus_ the amount of MEV extracted by the express lane controller while they are in control (that they otherwise did not predict). Understanding how the value of the express lane is determined can be useful for chain owners when adjusting to the artificial delay and the time before the auction closes. + +### The Timeboost auction + +Control of the express lane in each round (default: 60 seconds) is determined by a per-round auction, which is a sealed-bid, second-price auction. This auction is held to determine the express lane controller for the next round. In other words, the express lane controller was determined at any point in time in the previous auction round. Bids for the auction can be made with any ERC20 token, in any amount, and be collected by any address - at the full discretion of the chain owner. + +![timeboost auction workflow](./images/centralized-timeboost-auction-workflow.jpg) + +The auction for a round has a closing time that is `auctionClosingSeconds` (default: 15) seconds before the beginning of the round. This means that, in the default parameters, parties have 45 seconds to submit bids before the auction will no longer accept bids. In the 15 seconds between when bids are no longer accepted and when the new round begins, the autonomous auctioneer will verify all bids, determine the winner, and make a call to the on-chain auction contract to formally resolve the auction. + +### Auction contract + +Before placing a bid in the auction, a party must deposit funds into the Auction Contract. Deposits can be made, or funds can be added to an existing deposit at any time. These deposits are fully withdrawable, with some nominal delay (2 rounds, or 2 minutes by default), so as not to impact the outcome of an existing round. There is no minimum deposit amount, but there is a starting minimum bid of 0.001 ETH (default amount and token) called the "minimum reserve price". The minimum reserve price is set by the chain owner and can be updated at any time up to 30 seconds (default) before the start of the next round to ensure the auction participants will always know the reserve price at least 30 seconds before they must submit their bids. A reserve price can also be set by the chain owner (or by an address designated by the chain owner) as a way to raise the minimum bid as the Auction Contract enforces that the reserve price is never less than the minimum reserve price. + +![timeboost transferring and withdrawing](./images/centralized-timeboost-transfering-and-withdrawing.jpg) + +Once the autonomous auctioneer determines an auction winner, the auction contract will deduct the second-highest bid amount from the account of the highest bidder and transfer those funds to a `beneficiary` account designated by the chain owner by default. The `expressLaneControllerAddress` specified in the highest bid will become the express lane controller for the round. + +The auction contract also has functions that enable the express lane controller to update the address they wish to use for the express lane, which allows unique express lane control reselling use cases. + +### Default parameters + +Below are a few of the default Timeboost parameters mentioned earlier. All these parameters and more are configurable by the chain owner. + +| Parameter name | Description | Recommended default value | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------ | +| `roundDurationSeconds` | Duration of time that the sequencer will honor the express lane privileges for transactions signed by the current round’s express lane controller. | 60 seconds | +| `auctionClosingSeconds` | Time before the start of the next round. The autonomous auctioneer will not accept bids during this time interval. | 15 seconds | +| `beneficiary` | Address where proceeds from the Timeboost auction are sent to when `flushBeneficiaryBalance()` gets called on the auction contract. | An address controlled by the chain's owner | +| `_biddingToken` | Address of the token used to make bids in the Timeboost auction. It can be any ERC20 token (assuming the token address chosen does not have fee-on-transfer, rebasing, transfer hooks, or otherwise non-standard ERC20 logic). | WETH | +| `nonExpressDelayMsec` | The artificial delay applied to the arrival timestamp of non-express lane transactions _before_ the non-express lane transactions are sequenced. | 0.2 seconds, or 200 milliseconds | +| `reservePrice` | The minimum bid amount accepted by the auction contract for Timeboost auctions, denominated in `_biddingToken`. | None | +| `_minReservePrice` | A value that must be equal to or below the `reservePrice` to act as a "floor minimum" for Timeboost bids. Enforced by the auction contract. | 0.001 `WETH` | + +## Who is Timeboost for, and how do I use it? + +Timeboost is an optional addition to an Arbitrum chain’s infrastructure, meaning that enabling Timeboost is at the discretion of the chain owner and that an Arbitrum chain can fully function normally without Timeboost. + +When enabled, Timeboost is meant to serve different groups of parties with varying degrees of impact and benefits. Let’s go through them below: + +#### For regular users: + +Timeboost will have a minimal impact. Non-express lane transactions will be delayed by a nominal 200ms, which means to the average user, their transactions will take approximately 450ms to be sequenced and included into a block (up from approximately 200ms). All users will remain protected from harmful MEV activity, such as sandwich attacks and front-running, through the continued use of a private mempool. + +#### For chain owners: + +Timeboost represents a unique way to accrue value to their token and generate revenue for the chain. Explicitly, chain owners can set up their Timeboost auction to collect bid proceeds in the same token used for gas on their network and then choose what to do with these proceeds afterward. + +#### For searchers/arbitrageurs: + +Timeboost adds a unique twist to your existing or prospective MEV strategies that may become more profitable than before. For instance, purchasing the time advantage offered by Timeboost’s auction may end up costing _less_ than the costs to invest in hardware and win latency races. Another example is the potential new business model of reselling express lane rights to other parties in time slots or on a granular, per-transaction basis. + +### Special note on Timeboost for chain owners + +As with many new features and upgrades to Arbitrum Nitro, Timeboost is an optional feature that chain owners may choose to deploy and customize however they see fit. Deploying and enabling/disabling Timeboost on a live Arbitrum chain will not halt or impact the chain but will instead influence the chain's transaction ordering policy. An Arbitrum chain will, by default, fall back to FCFS if Timeboost is deployed but disabled or if there is no express lane controller for a given round. + +It is recommended that Arbitrum teams holistically assess the applicability and use cases of Timeboost for their chain before deploying and enabling Timeboost. This is because some Arbitrum chains may not have that much MEV (e.g., arbitrage) to begin with. Furthermore, we recommend that Arbitrum chains start with the default parameters recommended by Offchain Labs and closely monitor the results and impacts on your chain’s ecosystem over time before considering adjusting any of the parameters. + +### Wen mainnet? + +Timeboost’s auction contract has completed a third-party audit and is rapidly approaching production readiness. Specifically for Arbitrum One and Arbitrum Nova, a [temperature check vote on Snapshot](https://snapshot.box/#/s:arbitrumfoundation.eth/proposal/0xffe9bb38228fdaf3d121140856fd2d51c2ca7f8e0d1021c07e791cebb541129a) has already passed and the AIP will move towards an on-chain Tally vote next hopefully before the end of Q1 2025. + +In the meantime, please read the following resources to learn more about Timeboost: + +- [Arbitrum DAO Forum Post on Timeboost](https://forum.arbitrum.foundation/t/constitutional-aip-proposal-to-adopt-timeboost-a-new-transaction-ordering-policy/25167/86) +- [Timeboost FAQ](https://www.notion.so/bba234acf92e476b8ca5db6855d7da45?pvs=21) +- [Debunking common misconceptions about Timeboost](https://medium.com/offchainlabs/debunking-common-misconceptions-about-timeboost-92d937568494) +- [Technical specification for Timeboost with a centralized sequencer](https://github.com/OffchainLabs/timeboost-design/blob/main/research_spec.md) +- [Engineering design of Timeboost with a centralized sequencer](https://github.com/OffchainLabs/timeboost-design/blob/main/implementation_design.md) +- [Implementation of Timeboost with a centralized sequencer](https://github.com/OffchainLabs/nitro/pull/2561) +- [Technical specification for Timeboost with a decentralized sequencer](https://github.com/OffchainLabs/decentralized-timeboost-spec) +- [Audit report for Timeboost auction contracts](https://github.com/trailofbits/publications/blob/master/reviews/2024-08-offchainlabs-timeboost-auction-contracts-securityreview.pdf) diff --git a/arbitrum-docs/how-arbitrum-works/timeboost/images/centralized-timeboost-auction-workflow.jpg b/arbitrum-docs/how-arbitrum-works/timeboost/images/centralized-timeboost-auction-workflow.jpg new file mode 100644 index 000000000..5dc6457bc Binary files /dev/null and b/arbitrum-docs/how-arbitrum-works/timeboost/images/centralized-timeboost-auction-workflow.jpg differ diff --git a/arbitrum-docs/how-arbitrum-works/timeboost/images/centralized-timeboost-express-lane-workflow.jpg b/arbitrum-docs/how-arbitrum-works/timeboost/images/centralized-timeboost-express-lane-workflow.jpg new file mode 100644 index 000000000..20fdd6d45 Binary files /dev/null and b/arbitrum-docs/how-arbitrum-works/timeboost/images/centralized-timeboost-express-lane-workflow.jpg differ diff --git a/arbitrum-docs/how-arbitrum-works/timeboost/images/centralized-timeboost-transfering-and-withdrawing.jpg b/arbitrum-docs/how-arbitrum-works/timeboost/images/centralized-timeboost-transfering-and-withdrawing.jpg new file mode 100644 index 000000000..fc914dfb3 Binary files /dev/null and b/arbitrum-docs/how-arbitrum-works/timeboost/images/centralized-timeboost-transfering-and-withdrawing.jpg differ diff --git a/arbitrum-docs/how-arbitrum-works/tx-lifecycle.md b/arbitrum-docs/how-arbitrum-works/tx-lifecycle.md deleted file mode 100644 index 722b58a77..000000000 --- a/arbitrum-docs/how-arbitrum-works/tx-lifecycle.md +++ /dev/null @@ -1,139 +0,0 @@ -# Overview: The Lifecycle of an Arbitrum Transaction - -As an introduction to the various components that compose the Arbitrum protocol, we'll go step-by-step over the phases an Arbitrum transaction goes through, starting with a client creating a signed transaction, to it ultimately being confirmed back on layer 1. - -We'll also intersperse it with "finality checks," explaining what guarantees the client has over their transaction's finality (i.e., assurances that their transaction's result is guaranteed and won't later be altered) over the course of a transaction's various stages. - -This overview will be focused on the Arbitrum Rollup protocol; see [Inside AnyTrust](/how-arbitrum-works/inside-anytrust.md) for differences in the Arbitrum AnyTrust protocol. Also, for convenience/simplicity, we'll be describing the security properties of the core system itself; see ["State of Progressive Decentralization"](https://docs.arbitrum.foundation/state-of-progressive-decentralization) for current decentralization status. - -For clarity on any terminology that may be unfamiliar, see our [glossary](/intro/glossary.mdx). - -### 1. Sequencer receives transaction - -Typically, a transaction's lifecycle starts with the Sequencer, the entity designated with transaction ordering, receiving a transaction from a client. The Sequencer can receive a transaction one of two ways: - -##### 1a. Directly / Offchain - -For typical transacting within the L2 environment (i.e., using an L2 native dapp), a client will connect their wallet to an L2 node and directly deliver a signed transaction. - -##### 1b. ... or from L1 (via the Delayed Inbox). - -Alternatively, a client can send a message to the Sequencer by signing and publishing an L1 transaction in the Arbitrum chain's Delayed Inbox. This functionality is most commonly used for depositing ETH or tokens via a bridge. - -**See**: - -- [Retryables](/how-arbitrum-works/arbos/l1-l2-messaging.md) -- [The Sequencer](/how-arbitrum-works/sequencer.md) -- [Token Bridge](/build-decentralized-apps/token-bridging/01-overview.md) - -### 2. Sequencer orders transaction (off-chain) - -Upon receiving a transaction, the Sequencer will: - -- Order it in its off-chain Inbox -- Locally execute it using the Arbitrum Nitro VM (including collecting/allocating L1 and L2 fees, etc.) -- "Instantly" give a transaction receipt to the client ("instant" in that it doesn't require any additional on-chain confirmations, and typically takes less than a second - with the average user experiencing ~260ms). - -**See**: - -- [ArbOS](/how-arbitrum-works/arbos/introduction.md) -- [Geth](/how-arbitrum-works/arbos/geth.md) -- [L1 pricing](/how-arbitrum-works/l1-gas-pricing.md) / [L2 Gas](/how-arbitrum-works/gas-fees.md) - -#### ~ ~ ~ FINALITY CHECK: Trusted / Soft Confirmation ~ ~ ~ - -At this phase, the client's acceptance of finality relies on trusting the Sequencer. I.e., a malicious/faulty Sequencer could deviate between what it promised in the transaction receipt and what is ultimately published in a batch (see phase 3). - -:::note - -Even a malicious/faulty Sequencer can only, at worst, reorder or temporarily delay transactions; it cannot, e.g., forge a client's transaction or propose an invalid state update. Given the degree of trust in the Sequencer at phase 2, we sometimes refer to the "instant" receipt that the Sequencer provides as a "soft confirmation." - -::: - -### 3. Sequencer posts transaction in a batch (on-chain) - -The Sequencer will eventually post a batch of L2 transactions which includes our client's transaction onto the underlying L1 (as calldata); under normal conditions, the Sequencer will post batches [every few minutes](https://arbiscan.io/batches). - -##### 3a. What if the Sequencer never includes our transaction? - -Even if the Sequencer never includes our transaction in a batch, the client can include it in the L2 by posting in the delayed inbox and then "force including" it after some delay period (currently ~ @arbOneForceIncludePeriodHours@ hours on Arbitrum One). - -:::note - -The Sequencer is forced to include messages from the delayed Inbox in the queued order that they appear on chain, i.e. it processes messages using the "first in, first out" method. Thus, it can't selectively delay particular messages while including others; i.e., delaying the message at the front of the queue means delaying all messages behind it as well. - -::: - -**See:** - -- ["The Sequencer / Censorship Resistance."](/how-arbitrum-works/sequencer.md) - -#### ~ ~ ~ FINALITY CHECK: Ethereum-Equivalent Finality! ~ ~ ~ - -At this stage, assuming that a client believes there to be at least one well behaved active Arbitrum validator. Currently, the process of validation on the Arbitrum protocol is permissioned, but it's important to be aware that our latest dispute protocol, [BoLD (Bounded Liquidity Delay)](https://medium.com/offchainlabs/bold-permissionless-validation-for-arbitrum-chains-9934eb5328cc), has the potential to allow validation on Arbitrum chains without requiring permission, thereby potentially eliminating the necessity for restricted validation. The client can treat their transaction's finality as equivalent to an ordinary Ethereum transaction. In other words, their L2 transaction has the same finality as the L1 transaction that recorded it in a batch. This means the client should use whatever finality heuristic they use for regular Ethereum transactions (i.e., waiting on L1 block confirmations, etc.), applied to the L1 batch-posting transaction. This also means that a client uncomfortable with the trust model of the Sequencer's soft confirmations (phase 2) can simply wait for the Sequencer to post their transaction in a batch (phase 3). - -How are we able to make such bold a claim? A few (related) things: - -- Once the Sequencer posts a batch, its transactions' ordering is entirely determined by the L1; the Sequencer effectively has no more say in our transaction's lifecycle at all. -- The Inbox contract on L1 ensures that when the Sequencer posts a batch, it posts data sufficient for any Arbitrum Node to reconstruct and validate the state of the L2 chain; i.e., the availability of this "input" data is guaranteed by Ethereum itself. -- Execution on Arbitrum is fully deterministic; i.e., a current chain state along with new input data is sufficient to compute the new chain state; thus, the moment this input data is available (i.e., when the Sequencer posts a batch), the L2 chain's state can be computed. -- Arbitrum's fault-proof system is sound; i.e., if any validator (later) tries to deviate from the valid L2 state, an honest validator will ultimately be able to challenge this and win. Since we already know that valid state will ultimately win out, we can treat our transaction as L1-finalized now. - -### 4. Validator asserts RBlock that includes transaction - -A staked, active validator will then run the Arbitrum VM over the inputs in the Inbox (just like the Sequencer did earlier, except now only over transactions posted on L1) and make an on-chain assertion about the chain's latest state, i.e., a rollup block or "RBlock." RBlocks typically get asserted every 30-60 minutes. - -**See**: - -- [ArbOS](/how-arbitrum-works/arbos/introduction.md) -- [Geth](/how-arbitrum-works/arbos/geth.md) -- [L1 pricing](/how-arbitrum-works/l1-gas-pricing.md) / [L2 Gas](/how-arbitrum-works/gas-fees.md) - -:::note - -RBlock assertions include claims about the state of the Outbox; if our transaction triggered any L2 to L1 messages, a RBlock will include an update to the Outbox to reflect its inclusion. - -::: - -**See**: - -- [The Outbox](/how-arbitrum-works/arbos/l2-l1-messaging.md) - -#### 4a. RBlock is valid / goes unchallenged - -In the happy / common case, the validator asserted a valid RBlock, and over the course of the dispute window — 1 week on Arbitrum One — no other validators challenge it. - -#### 4b. Assertion is challenged! - -If two validators assert different RBlocks, only (at most) one of them can be valid, so they are put into a dispute. - -A dispute consists of two staked validators dissecting their disagreement down to a single L2 block, and then dissecting the sequence of VM instructions within this block down to a single OPCODE, then finally, executing this single operation. The underlying VM the Arbitrum uses is [WebAssembly (Wasm)](https://webassembly.org), or, more precisely, "WAVM." This is all refereed by contracts on L1. - -**See:** - -- [Challenges](/how-arbitrum-works/fraud-proofs/challenge-manager.md) -- [Wasm/WAVM](/how-arbitrum-works/fraud-proofs/wasm-wavm.md) - -L1 contracts also keep track of the tree of all assertions; i.e., how many stakers are in disagreement, who is currently disputing with whom, etc. We refer to this level of Arbitrum's design architecture as its "assertion tree protocol." - -**See:** - -- [Assertion Tree Protocol](/how-arbitrum-works/assertion-tree.md) - -#### ~ ~ ~ FINALITY CHECK: STILL THE SAME Ethereum-Equivalent Finality! ~ ~ ~ - -Remember in phase 3 when said that once the L1 has committed to inputs, we can guarantee the L2 output? We meant it! Even during a dispute, Arbitrum nodes continue to execute and active validators continue to make assertions on the valid leaf in the state-tree; nothing that can happen in phase 4 has any effect on the L1-level finality we've already locked in at phase 3. - -### 5. RBlock is confirmed on L1 - -Once any and all disputes have been resolved and sufficient time has passed, our RBlock can be confirmed on L1 (any Ethereum account on L1 can confirm it). Upon confirmation, the Outbox root on L1 gets updated. - -#### ~ ~ ~ FINALITY CHECK: L2-to-L1 Messages Executable on L1 ~ ~ ~ - -If our client's transaction didn't include any L2-to-L1 messages (e.g., withdrawals), phase 5 has no material effect on their transaction. If it did include an L2-to-L1 transaction, it is only after confirmation that the message can be executed in the Outbox on L1. - -:::note - -Even before phase 5, the client has L1 finality on the _result_ of their L2-to-L1 message, they just can't execute it yet; i.e., they have a guarantee that they'll eventually be able to, e.g., finalize their withdrawal, they just can't claim their funds on L1 until the RBlock is confirmed. - -::: diff --git a/arbitrum-docs/intro/intro.md b/arbitrum-docs/intro/intro.mdx similarity index 78% rename from arbitrum-docs/intro/intro.md rename to arbitrum-docs/intro/intro.mdx index dce800113..fe45dc3dd 100644 --- a/arbitrum-docs/intro/intro.md +++ b/arbitrum-docs/intro/intro.mdx @@ -4,10 +4,6 @@ description: 'Arbitrum is a suite of Ethereum Layer-2 scaling solutions that you author: dzgoldman --- -import PublicPreviewBannerPartial from '../partials/_public-preview-banner-partial.mdx'; - - - import GentleIntroPartial from '../partials/_gentle-intro-partial.mdx'; diff --git a/arbitrum-docs/launch-orbit-chain/aep-fee-router-introduction.mdx b/arbitrum-docs/launch-orbit-chain/aep-fee-router-introduction.mdx index e2c53f1ab..737394af6 100644 --- a/arbitrum-docs/launch-orbit-chain/aep-fee-router-introduction.mdx +++ b/arbitrum-docs/launch-orbit-chain/aep-fee-router-introduction.mdx @@ -10,7 +10,7 @@ content_type: get-started ## What is the Arbitrum expansion program? -The [Arbitrum Expansion Program](https://forum.arbitrum.foundation/t/the-arbitrum-expansion-program-and-developer-guild/20722) (AEP) allows Orbit chains to deploy on _any chain_ permissionlessly. As part of the [AEP license](https://docs.arbitrum.foundation/assets/files/Arbitrum%20Expansion%20Program%20Jan182024-4f08b0c2cb476a55dc153380fa3e64b0.pdf), Orbit chains deployed outside of Arbitrum One and Arbitrum Nova must pay 10% of their **Net Protocol Revenue** to the Arbitrum DAO. +The [Arbitrum Expansion Program](https://forum.arbitrum.foundation/t/the-arbitrum-expansion-program-and-developer-guild/20722) (AEP) allows Orbit chains to deploy on _any chain_ permissionlessly. As part of the [AEP license](https://docs.arbitrum.foundation/aep/ArbitrumExpansionProgramTerms.pdf), Orbit chains deployed outside of Arbitrum One and Arbitrum Nova must pay 10% of their **Net Protocol Revenue** to the Arbitrum DAO. The Arbitrum Expansion Program and Developer Guild are initiatives launched in collaboration with Offchain Labs to promote the development of customized Arbitrum chains using the Orbit framework. The Expansion Program simplifies the process for teams to create Layer 2 (L2) and Layer 3 (L3) chains, offering self-service tools and customization options. Projects benefit from features like: diff --git a/arbitrum-docs/launch-orbit-chain/aep-license.mdx b/arbitrum-docs/launch-orbit-chain/aep-license.mdx new file mode 100644 index 000000000..6871fe7b4 --- /dev/null +++ b/arbitrum-docs/launch-orbit-chain/aep-license.mdx @@ -0,0 +1,23 @@ +--- +title: 'Orbit licensing' +sidebar_label: 'Orbit licensing' +description: 'Learn about the Orbit license and AEP.' +author: SHughes +sme: SHughes +user_story: As a prospective Orbit chain owner, I need to understand the Orbit license. +content_type: get-started +--- + +## What do I need to know about the Orbit license? + +Nitro is currently licensed under a [Business Source License](https://github.com/OffchainLabs/nitro/blob/master/LICENSE.md), similar to DeFi protocols like Uniswap and Aave, among others, with an “Additional Use Grant” to ensure that everyone can have full comfort using and running nodes on all public Arbitrum chains. + +The Additional Use Grant also permits deployment of the Nitro software in a permissionless, zero-cost fashion, as a new blockchain provided that the chain settles to either Arbitrum One or Arbitrum Nova. L3s that settle to Arbitrum One or Nova have no obligation to share revenue with the Arbitrum DAO and remain first class members of the Arbitrum ecosystem. +As an expansion of this license, the [Arbitrum Expansion Program](https://docs.arbitrum.foundation/aep/ArbitrumExpansionProgramTerms.pdf) (AEP) is a self-service licensing model that makes it easy for developers to build and customize L2s/L3s using Arbitrum’s technology alongside different parent chains. + +Benefits: + +- Leverage battle-tested technology to permissionlessly deploy L2s/L3s that settle to any supported parent chain. +- Governance freedom - Orbit chains are not required to be governed by the Arbitrum DAO. +- Flexible licensing allows developers to modify chain configurations. Orbit chains are free to modify any part of the stack, including implementation of custom gas tokens, alternative DA integrations, novel sequencing mechanisms, account abstraction, altVMs, etc. +- L3s that settle to parent chains other than Arb1 and Nova must contribute [net chain revenue](https://docs.arbitrum.io/launch-orbit-chain/how-tos/calculate-aep-fees#calculating-aep-fees), where 8% flows to the DAO and 2% to the developer guild. diff --git a/arbitrum-docs/launch-orbit-chain/assets/bold-orbit-permissionless-vs-permissioned.png b/arbitrum-docs/launch-orbit-chain/assets/bold-orbit-permissionless-vs-permissioned.png new file mode 100644 index 000000000..d13245e44 Binary files /dev/null and b/arbitrum-docs/launch-orbit-chain/assets/bold-orbit-permissionless-vs-permissioned.png differ diff --git a/arbitrum-docs/launch-orbit-chain/bold-adoption-for-orbit-chains.mdx b/arbitrum-docs/launch-orbit-chain/bold-adoption-for-orbit-chains.mdx new file mode 100644 index 000000000..8da2da0c4 --- /dev/null +++ b/arbitrum-docs/launch-orbit-chain/bold-adoption-for-orbit-chains.mdx @@ -0,0 +1,107 @@ +--- +title: 'BoLD for Orbit chains' +description: 'Learn how to integrate BoLD with your Orbit chain' +user_story: 'As a developer or researcher of the Arbitrum product suite, I want to learn about BoLD, a next-generation dispute protocol that enables permissionless validation.' +content_type: release announcement +author: leeederek +sme: leeederek +target_audience: 'Developers who want to build on Arbitrum using popular programming languages, like Rust' +sidebar_position: 1 +--- + +:::info PUBLIC PREVIEW DOCUMENT + +This document is currently in **public preview** and may change significantly as feedback is captured from readers like you. Click the _Request an update_ button at the top of this document or [join the Arbitrum Discord](https://discord.gg/arbitrum) to share your feedback. + +::: + +## Launch details and key dates + +- **Status:** Alpha - continued testing and evaluation of performance of BoLD with Stylus +- **Arbitrum Sepolia** Q4 2024 +- **Arbitrum One** Q1 2025 +- **Arbitrum Nova** Q1 2025 + +### tldr; + +Arbitrum BoLD is an upgrade to the dispute protocol on Arbitrum chains +that delivers both permissionless validation and core security benefits. As with all features on the +Arbitrum stack, Orbit chains can adopt BoLD at their own discretion and on their own timeline. To upgrade +to BoLD, it is required to upgrade both the Nitro node software and the rollup's smart contracts on its +parent chain.{' '} + +### Recommended Adoption Path + +BoLD brings new security benefits to Orbit chains, regardless of whether their validators are permissioned or permissionless. These new security benefits include improved resistance to delay attacks and increased censorship resistance for `L3s`. We strongly recommend Orbit chains adopt Arbitrum BoLD to register these security benefits while **keeping validation permissioned**. + +:::warning + +It is strongly recommended that existing and prospective Orbit chains upgrade to use Arbitrum BoLD but **keep validation permissioned** because of the increased risks associated with allowing any entity to advance and challenge the state of your chain. The risks are summarized below. Rigorous testing and research has been poured into the parameters chosen for Arbitrum One and so we cannot formally support or endorse use of permissionless Arbitrum BoLD in other configurations. + +::: + +Below is a quick breakdown of the benefits of permissioned BoLD vs. permissionless BoLD for your Orbit chain: + +![Alt Text](./assets/bold-orbit-permissionless-vs-permissioned.png) + +### Benefits of adopting Arbitrum BoLD + +Arbitrum BoLD enables an Arbitrum chain to be permissionlessly validated thanks to several key improvements to the existing dispute protocol. These key improvements benefit an Arbitrum Orbit chain even if validation is kept permissioned on a BoLD-enabled Orbit chain. + +Below are some benefits for an Orbit chain that come with adopting Arbitrum BoLD - **regardless of whether validation is kept permissioned or not**: + +#### Improved resistance to delay attacks + +Disputes on a BoLD-enabled chain are resolved in a round-robin style format where disputes can be concurrently resolved. This is an evolution from the current dispute protocol, where challenges are resolved one-by-one. This evolution means that an upper time bound can be placed on all disputes such that a malicious actor cannot delay the chain indefinitely like they can today. Even when validation is kept permissioned, this upper time bound is critical to mitigating the risk of [delay attacks](https://medium.com/offchainlabs/solutions-to-delay-attacks-on-rollups-434f9d05a07a) by parties on the validator allowlist for an Orbit chain. + +#### Being on the latest version of Arbitrum technology + +Adopting Arbitrum BoLD for your Orbit chain will require upgrading the Nitro node software and deploying a new set of contracts on your parent chain. While not specifically related to Arbitrum BoLD, it is always strongly recommended that Orbit chain owners upgrade and keep their chain on the latest stable releases of both Nitro node software and the relevant on-chain contracts. This is critical to ensure your Orbit chain benefits from the latest security improvements and features that the Offchain Labs team is constantly churning out. + +#### Secured by interactive fraud-proofs + +Arbitrum BoLD is not an upgrade to a different type of proving architecture and will continue to be secured with an interactive proving game between validators using fraud proofs. The same single-honest party assumption applies but now with strict improvements to security to the point where chains, like Arbitrum One, can be permissionlessly validated and have their state assertions be permissionlesly challenged. + +#### Use of your project's native token as the bonding asset to secure the chain + +Arbitrum BoLD enables the chain owner to use any `ERC-20` token on the parent chain as the bond for validators to participate in securing the network. By default, this token will be `WETH` for Arbitrum One and we do not recommend teams to use alternative tokens as the bonding asset. For more information on the rationale, we recommend teams consult our documentation to understand [why `WETH` was selected for Arbitrum One](https://docs.arbitrum.io/how-arbitrum-works/bold/gentle-introduction#q-why-is-arb-not-the-bonding-token-used-in-bold-on-arbitrum-one) (and not `ARB`). + +#### Increased censorship resistance for `L3` Orbit chains + +Today, the force inclusion window is a fixed 24 hours. This force inclusion window exists to enable both users and validators to force-include their transactions and assertions on the parent chain, with a 24-hour delay, if the sequencer is offline or censoring transactions. Arbitrum BoLD's release will come with the _Censorship Timeout_ feature that will automatically reduce the force inclusion time window if the parent chain or sequencer is maliciously censoring user transactions/assertions or the sequencer goes offline. This massively benefits Orbit `L3` chains (that settle to a BoLD-enabled parent chain) as it ensures the chain can advance with minimal UX degradation during periods of censorship. You can read more about how this feature works in the [gentle introduction to BoLD](https://docs.arbitrum.io/how-arbitrum-works/bold/gentle-introduction#q-how-do-bold-based-l3s-challenge-periods-operate-considering-the-worst-case-scenario). + +### Caveats that come with adopting Arbitrum BoLD for permissionless validation + +Arbitrum BoLD's implementation and specification have been thoroughly tested and audited. The upgrade to Arbitrum BoLD is not the subject of this section, but rather the caveats and nuances that come with whether to enable permissionless validation. + +:::warning + +It is strongly recommended that existing and prospective Orbit chains upgrade to use Arbitrum BoLD but **keep validation permissioned** because of the increased risks associated with allowing any entity to advance and challenge the state of your chain. The risks are summarized below. Rigorous testing and research has been poured into the parameters chosen for Arbitrum One and so we cannot formally support or endorse use of permissionless Arbitrum BoLD in other configurations. + +::: + +Enabling permissionless validation means that any entity can spin up a validator and open challenges to dispute invalid claims made by other validators on the network. This opens up an Orbit chain to the risk of spam and attacks by unknown and malicious entities. To mitigate this risk for Arbitrum One, a considerable amount of research and testing has been done to optimize the trade-offs between deterring attacks and managing the costs of defending Arbitrum for honest parties. This research includes carefully calculating all relevant bond sizes, challenge period durations, and relevant plans for operating the infrastructure. More information on this research can be found in the [BoLD whitepaper](https://arxiv.org/abs/2404.10491). Below are a few examples of various risks that an Orbit chain will hold should they pursue permissionless BoLD: + +#### Risk of resource exhaustion attacks + +Where malicious entities can acquire and utilize more resources than honest parties can put together during a challenge. Such an attack can take many forms and includes both on-chain and off-chain computational/infra costs. For example, a well-coordinated attack on an Orbit chain could overwhelm honest parties if the malicious actors can spend more gas and computational power and acquire more of the bonding asset than the defenders can. This risk can be mitigated by a combination of high bond sizes, use of a price-independent bonding asset, use of a bonding asset with high liquidity, strong economic guarantees that attackers will lose most of their resources, sufficiently long challenge periods, and robust infrastructure operations and resources that can respond and scale up when necessary. More information on resource exhaustion attacks and how Arbitrum BoLD's design accounts for this risk can be found in [Section 6.1.4 of the BoLD whitepaper](https://arxiv.org/abs/2404.10491). We recommend teams consider a resource exhaustion ratio greater than 5 assuming very high L1 gas costs (like 100gwei/gas). + +#### Increased infrastructure costs and overhead + +Related to, and expanding on, the above point about resource exhaustion attacks, the honest parties operating active validators and proposers for a BoLD-enabled chain will need to be ready to vertically scale their infrastructure, and cover the off-chain costs of doing so, in the event of an attack. This is because a malicious actor may choose to spam and overwhelm the honest defenders with multiple challenges. Making moves, honest or malicious, costs resources to perform bisections on history committments down to a single step of execution. If this happens, each malicious challenge must be met with an honest counter-challenge during the interactive fraud proof game. Orbit chains who decide to adopt Arbitrum BoLD in permissionless mode are strongly encouraged to work with their Rollup-as-a-Service (RaaS) team to: deploy robust monitoring for challenges, set aside a budget to vertically scale up infrastructure and fund counter-challenges, and have an incident response plan drafted and rehearsed to ensure prompt and decisive reactionary steps in the event of an attack. + +#### Risks to liveness or delays of the chain + +If the bond sizes are set too low, an adversary can cheaply create a challenge and delay confirmation of an assertion for up to an entire extra challenge period if they can censor honest BoLD moves. Remember that challenges, while time-bound, still take time to complete. Delaying the confirmation of assertions for a chain could negatively impact the chain in many ways that an attacker could benefit from (e.g., profiting from price volatility and price impacts on the Orbit chain's token may make delaying the chain worthwhile for an attacker). We recommend teams set bond sizes to be much greater than the opportunity cost of a week of delay, based on your chain's TVL (e.g. if your chain's TVL is $1B, then the opportunity cost of $1B should be used as a _floor_ for the block level bond amount size). We further recommend that the bonding token used is highly liquid on the parent chain and relatively non-volatile. + +### Conclusion for Orbit chains considering BoLD Permissionless Validation + +Due to the uniquely different tokenomics, sizes, and varying types of Arbitrum Orbit chains deployed (or in active development) today, Offchain Labs does not provide a "one-size-fits-all" recommendation for how best to safely set up and enable permissionless validation for Orbit chains. Instead, we recommend teams adopt Arbitrum BoLD but keep validation permissioned. + +Should Orbit teams strongly desire to adopt Arbitrum BoLD in permissionless mode, we do not endorse using configurations that differ from those on [Arbitrum One](https://github.com/OffchainLabs/nitro-contracts/blob/bold-merge/scripts/files/configs/arb1.ts). We especially do not recommend teams use custom ERC20 tokens as the bonding asset and/or with low bond minimums. If your team would like to have permissionless validation for your Orbit chain, please reach out to us [via this form](https://docs.google.com/forms/d/e/1FAIpQLSe5YWxFbJ8DgWcDNbIW2YYuTRmegtx2FHObym00_sOt0kq4wA/viewform) so that we can schedule some time to understand your needs better. + +### How to adopt Arbitrum BoLD + +As mentioned earlier, the upgrade to the dispute protocol involves both a Nitro node software upgrade and the deployment/upgrade of new smart contracts on your Orbit's parent chain. + +More details on deploying Arbitrum BoLD for your Orbit chain will be added here when they are available. diff --git a/arbitrum-docs/launch-orbit-chain/concepts/chain-ownership.md b/arbitrum-docs/launch-orbit-chain/concepts/chain-ownership.md index 74ec5545e..6af288ef0 100644 --- a/arbitrum-docs/launch-orbit-chain/concepts/chain-ownership.md +++ b/arbitrum-docs/launch-orbit-chain/concepts/chain-ownership.md @@ -13,10 +13,6 @@ An Orbit chain's initial chain owner is set by the chain's creator when the chai The chain-ownership architecture is designed to give Orbit chain creators flexibility in deciding how upgrades to their chain occur. -import PublicPreviewBannerPartial from '../partials/_orbit-public-preview-banner-partial.md'; - - - ### Architecture Chain ownership affordance is handled via [**Upgrade Executor**](https://github.com/OffchainLabs/upgrade-executor) contracts. diff --git a/arbitrum-docs/launch-orbit-chain/concepts/custom-gas-token-sdk.md b/arbitrum-docs/launch-orbit-chain/concepts/custom-gas-token-sdk.md index 04f4fa094..3783368bd 100644 --- a/arbitrum-docs/launch-orbit-chain/concepts/custom-gas-token-sdk.md +++ b/arbitrum-docs/launch-orbit-chain/concepts/custom-gas-token-sdk.md @@ -9,10 +9,6 @@ sidebar_position: 2 Arbitrum SDK is a TypeScript library for client-side interactions with Arbitrum. It provides common helper functionality as well as access to the underlying smart contract interfaces. -import PublicPreviewBannerPartial from '../partials/_orbit-public-preview-banner-partial.md'; - - - ### Custom gas token APIs Custom gas token support in the Arbitrum SDK introduces a suite of APIs designed for the specific purpose of facilitating **bridging** operations. These APIs are tailored for use cases where there is a need to transfer a native token or an ERC-20 token from the parent chain to an orbit chain utilizing a `custom gas token`. The process involves an initial step of authorizing the native token on the parent chain. To streamline this, our APIs provide functionalities for token approval and offer a mechanism to verify the current status of this approval. Detailed below is a guide to how each of these APIs can be effectively utilized for distinct purposes: @@ -25,7 +21,7 @@ Custom gas token support in the Arbitrum SDK introduces a suite of APIs designed 2. **Erc20Bridger Context:** - **APIs:** `getApproveGasTokenRequest` and `approveGasToken`. - - **Purpose:** In the scenario of bridging ERC20 assets to an Orbit chain, these APIs play a crucial role. Token Bridging on Arbitrum Nitro stack uses Retryable tickets and needs specific amount of fees to be paid for creation and redemption of the ticket. For more information about retryable tickets please take a look at [this](/how-arbitrum-works/arbos/l1-l2-messaging.md#retryable-tickets) part of our docs. The Orbit chain operates as a custom gas token network, necessitating the payment of fees in native tokens for the creation of retryable tickets and their redemption on the Orbit chain. To cover the submission and execution fees associated with retryable tickets on the Orbit chain, an adequate amount of native tokens must be approved and allocated on the parent chain to cover the fees. + - **Purpose:** In the scenario of bridging ERC20 assets to an Orbit chain, these APIs play a crucial role. Token Bridging on Arbitrum Nitro stack uses retryable tickets and needs a specific fee to be paid for the creation and redemption of the ticket. For more information about retryable tickets, please take a look at [our chapter about retryable tickets](/how-arbitrum-works/10-l1-to-l2-messaging.mdx#retryable-tickets) part of our docs. The Orbit chain operates as a custom gas token network, necessitating the payment of fees in native tokens for the creation of retryable tickets and their redemption on the Orbit chain. To cover the submission and execution fees associated with retryable tickets on the Orbit chain, an adequate number of native tokens must be approved and allocated to the parent chain to cover the fees. - **Note** that you should use `Erc20Bridger` when bridging an ERC-20 token between the parent chain and the orbit chain. **Note** that these APIs are just needed for `custom gas token` orbit chains and for ETH-powered rollup and anytrust orbit chains, you don't need to use them. @@ -36,7 +32,7 @@ Custom gas token support in the Arbitrum SDK introduces a suite of APIs designed ### Registering a custom token in the Token Bridge -When [registering a custom token in the Token Bridge](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md#setting-up-your-token-with-the-generic-custom-gateway) of a custom-gas-token Orbit chain, there's an additional step to perform before calling `registerTokenToL2`. +When [registering a custom token in the Token Bridge](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx#setting-up-your-token-with-the-generic-custom-gateway) of a custom-gas-token Orbit chain, there's an additional step to perform before calling `registerTokenToL2`. Since the Token Bridge [router](https://github.com/OffchainLabs/token-bridge-contracts/blob/main/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol#L142-L144) and the [generic-custom gateway](https://github.com/OffchainLabs/token-bridge-contracts/blob/main/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol#L203-L210) expect to have allowance to transfer the native token from the `msg.sender()` to the inbox contract, it's usually the token in the parent chain who handles those approvals. In the [TestCustomTokenL1](https://github.com/OffchainLabs/token-bridge-contracts/blob/main/contracts/tokenbridge/test/TestCustomTokenL1.sol#L158-L168), we offer as an example of implementation. We see that the contract transfers the native tokens to itself and then approves the router and gateway contracts. If we follow that implementation, we only need to send an approval transaction to the native token to allow the TestCustomTokenL1 to transfer the native token from the caller of the `registerTokenToL2` function to itself. diff --git a/arbitrum-docs/launch-orbit-chain/concepts/public-preview-expectations.md b/arbitrum-docs/launch-orbit-chain/concepts/public-preview-expectations.md index 300139ad1..6d1030d2b 100644 --- a/arbitrum-docs/launch-orbit-chain/concepts/public-preview-expectations.md +++ b/arbitrum-docs/launch-orbit-chain/concepts/public-preview-expectations.md @@ -23,10 +23,6 @@ Offchain Labs builds products in a way that aligns loosely with the spirit of "b To do this, some of our product offerings are documented with **public preview** disclaimers that look like this: -import PublicPreviewBannerPartial from '../partials/_orbit-public-preview-banner-partial.md'; - - - This banner's purpose is to set expectations while inviting readers like you to express your needs so that we can incorporate them into the way that we iterate on product. ### What to expect when using public preview offerings diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/add-orbit-chain-to-bridge-ui.md b/arbitrum-docs/launch-orbit-chain/how-tos/add-orbit-chain-to-bridge-ui.md index ffb28a254..f919b7dc5 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/add-orbit-chain-to-bridge-ui.md +++ b/arbitrum-docs/launch-orbit-chain/how-tos/add-orbit-chain-to-bridge-ui.md @@ -6,15 +6,11 @@ sme: jose-franco sidebar_position: 2 --- -import PublicPreviewBannerPartial from '../partials/_orbit-public-preview-banner-partial.md'; - - - This how-to will walk you through the process of adding your Orbit chain to the [Arbitrum bridge](https://bridge.arbitrum.io/). There's one section for mainnet Orbit chains, and another for local testnet Orbit chains. You can access either section using the links on the right column. ## Request adding a mainnet Orbit chain to the Arbitrum bridge -Mainnet Orbit chains can be added to the Arbitrum Bridge by filling out [this form](https://forms.gle/LrVskEd3DTtXSPwx7). +Mainnet Orbit chains can be added to the Arbitrum Bridge by filling out [this form](https://github.com/OffchainLabs/arbitrum-token-bridge/issues/new/choose). Once receiving your request, our team will review and apply internal criteria to include your chain in the bridge. Here are some of the criteria that a chain must follow to be added to the bridge: @@ -29,7 +25,7 @@ Currently, adding a testnet Orbit chain to the Arbitrum bridge must be done loca ### Prerequisites - A local testnet Orbit chain's configuration. See the [Orbit quickstart](/launch-orbit-chain/orbit-quickstart.md) to deploy a local Orbit chain, or use an existing JSON configuration. -- A browser-based Ethereum wallet (like [MetaMask](https://metamask.io/)) +- A browser-based Ethereum wallet (i.e., [MetaMask](https://metamask.io/) or [OKX Wallet](https://www.okx.com/web3)) ### Procedure diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/arbos-upgrade.md b/arbitrum-docs/launch-orbit-chain/how-tos/arbos-upgrade.md index 7f707b3de..a75c83eaf 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/arbos-upgrade.md +++ b/arbitrum-docs/launch-orbit-chain/how-tos/arbos-upgrade.md @@ -10,15 +10,11 @@ sidebar_position: 3 This how-to provides step-by-step instructions for Orbit chain operators who want to upgrade ArbOS on their Orbit chain(s). Familiarity with ArbOS, Orbit, and [chain ownership](../concepts/chain-ownership.md) is expected. Note that Orbit chain owners have full discretion over when and whether to upgrade their ArbOS version. -The specific upgrade requirements for each ArbOS release are located under each reference page for that specific [ArbOS release](/run-arbitrum-node/arbos-releases/01-overview.md#list-of-available-arbos-releases). - -import PublicPreviewBannerPartial from '../../node-running/partials/_upgrade-cadence-recommendations-partial.mdx'; - - +The specific upgrade requirements for each ArbOS release are located under each reference page for that specific [ArbOS release](/run-arbitrum-node/arbos-releases/01-overview.mdx#list-of-available-arbos-releases). #### Step 1: Update Nitro on nodes and validators -Refer to the [requirements for the targeted ArbOS release](/run-arbitrum-node/arbos-releases/01-overview.md) to identify the specific [Nitro release](https://github.com/OffchainLabs/nitro/releases/) that supports the ArbOS version that you're upgrading to. For example, if your upgrade targets ArbOS 20, you'd use Nitro `v2.3.1` (Docker image: `offchainlabs/nitro-node:v2.3.1-26fad6f`) or higher. This is the version of the Nitro stack that needs to be running on each of your Orbit chain's nodes. A list of [all Nitro releases can be found on Github](https://github.com/OffchainLabs/nitro/releases). +Refer to the [requirements for the targeted ArbOS release](/run-arbitrum-node/arbos-releases/01-overview.mdx) to identify the specific [Nitro release](https://github.com/OffchainLabs/nitro/releases/) that supports the ArbOS version that you're upgrading to. For example, if your upgrade targets ArbOS 20, you'd use Nitro `v2.3.1` (Docker image: `offchainlabs/nitro-node:v2.3.1-26fad6f`) or higher. This is the version of the Nitro stack that needs to be running on each of your Orbit chain's nodes. A list of [all Nitro releases can be found on Github](https://github.com/OffchainLabs/nitro/releases). Begin by upgrading your validator node(s) to the specified Nitro version, then update each remaining Orbit node to match this version. @@ -28,9 +24,9 @@ Note that upgrading your node version _must occur_ before the deadline establish While every ArbOS upgrade will require an update to the Wasm module root, not every ArbOS upgrade will require an upgrade to the chain's `nitro-contracts` version. -If necessary, as defined in the release notes for each ArbOS release ([example of ArbOS 20](../../run-arbitrum-node/arbos-releases/arbos20.md)), you may need to deploy new versions of some (or all) of the Nitro contracts to the parent chain of your Orbit chain. These contracts include the rollup logic, bridging logic, fraud-proof contracts, and interfaces for interacting with Nitro precompiles. To verify the current version of your Nitro contracts, follow [these instructions](https://github.com/OffchainLabs/orbit-actions/blob/main/README.md#check-version-and-upgrade-path) while replacing the inbox contract address and network name with that of your Orbit chain. This information will allow you to find the correct upgrade path for your Nitro contracts. +If necessary, as defined in the release notes for each ArbOS release ([example of ArbOS 20](../../run-arbitrum-node/arbos-releases/arbos20.mdx)), you may need to deploy new versions of some (or all) of the Nitro contracts to the parent chain of your Orbit chain. These contracts include the rollup logic, bridging logic, fraud-proof contracts, and interfaces for interacting with Nitro precompiles. To verify the current version of your Nitro contracts, follow [these instructions](https://github.com/OffchainLabs/orbit-actions/blob/main/README.md#check-version-and-upgrade-path) while replacing the inbox contract address and network name with that of your Orbit chain. This information will allow you to find the correct upgrade path for your Nitro contracts. -To update the Wasm module root and deploy your chain's Nitro contracts to the parent chain for the most recent ArbOS release, you will need the following inputs (obtained from the [requirements for the targeted ArbOS release](/run-arbitrum-node/arbos-releases/01-overview.md)): +To update the Wasm module root and deploy your chain's Nitro contracts to the parent chain for the most recent ArbOS release, you will need the following inputs (obtained from the [requirements for the targeted ArbOS release](/run-arbitrum-node/arbos-releases/01-overview.mdx)): - The WASM module root, and if necessary, - The required `nitro-contracts` version @@ -72,8 +68,8 @@ When scheduling the ArbOS upgrade through `ArbOwner.scheduleArbOSUpgrade` you mu #### Step 4: Enable ArbOS specific configurations or feature flags (not always required) -For some ArbOS upgrades, such as [ArbOS 20 Atlas](/run-arbitrum-node/arbos-releases/arbos20.md), there may be additional requirements or steps that need to be satisfied to ensure your Orbit chain can use all of the new features and improvements made available in that particular ArbOS release. +For some ArbOS upgrades, such as [ArbOS 20 Atlas](/run-arbitrum-node/arbos-releases/arbos20.mdx), there may be additional requirements or steps that need to be satisfied to ensure your Orbit chain can use all of the new features and improvements made available in that particular ArbOS release. -If there are additional requirements for the targeted ArbOS release you're attempting to upgrade to; the additional requirements will be listed on the reference pages for [the targeted ArbOS release](/run-arbitrum-node/arbos-releases/01-overview.md#list-of-available-arbos-releases). For example, the additional requirements for Orbit chains upgrading to ArbOS 20 can be found [here on the ArbOS 20 docs](/run-arbitrum-node/arbos-releases/arbos20.md). +If there are additional requirements for the targeted ArbOS release you're attempting to upgrade to; the additional requirements will be listed on the reference pages for [the targeted ArbOS release](/run-arbitrum-node/arbos-releases/01-overview.mdx#list-of-available-arbos-releases). For example, the additional requirements for Orbit chains upgrading to ArbOS 20 can be found [here on the ArbOS 20 docs](/run-arbitrum-node/arbos-releases/arbos20.mdx). Congratulations! You've upgraded your Orbit chain(s) to the specified ArbOS version. diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/calculate-aep-fees.mdx b/arbitrum-docs/launch-orbit-chain/how-tos/calculate-aep-fees.mdx index 43e5769c0..027853d87 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/calculate-aep-fees.mdx +++ b/arbitrum-docs/launch-orbit-chain/how-tos/calculate-aep-fees.mdx @@ -10,7 +10,7 @@ content_type: how-to This document will help you calculate your Orbit chain’s _Protocol Net Revenue_ and AEP license fees. -Before we define “Protocol Net Revenue,” let's explain how fees work in a standard Orbit chain. From there, we can connect how each fee equates to a revenue or a cost. +Before we define “Protocol Net Revenue”, let's explain how fees work in a standard Orbit chain. From there, we can connect how each fee equates to a revenue or a cost. ### Sequencing revenue @@ -21,11 +21,11 @@ In a vanilla Orbit chain (a chain without customizations, transaction ordering p - `l1BaseFee`: fees paid to cover the cost of an Orbit chain posting its settlement transaction to the parent chain. - `l1SurplusFee`: an additional surplus fee that can be configured to award extra fees to the batch poster. -Based on the above, we interpret that an Orbit chain’s revenue sources include all fee components: `l2BaseFee`, `l2SurplusFee`, `l1BaseFee`, and `l1SurplusFee`. However, one of these fee components is also a cost: `l1BaseFee`, as it is used to pay for parent chain settlement. +Based on the above, we interpret that an Orbit chain’s revenue sources include all fee components: `l2BaseFee`, `l2SurplusFee`, `l1BaseFee`, and `l1SurplusFee`. However, one of these fee components is also a cost, `l1BaseFee`, as it is used to pay for parent chain settlement. ### Assertion costs -The above fee system applies to an Orbit chain’s Sequencer and Batch Poster, but there is another important actor that is considered essential to the chain. These are the [\*\*validators](https://docs.arbitrum.io/how-arbitrum-works/inside-arbitrum-nitro#validators).\*\* +The above fee system applies to an Orbit chain’s Sequencer and Batch Poster, but there is another important actor that is considered essential to the chain. These are the [validators](/how-arbitrum-works/06-optimistic-rollup.mdx#validators). Validators are responsible for posting assertions on the parent chain, which are disputable claims about the new state of the Rollup. Posting an assertion is what progressed chain state on the parent chain. Validators are also responsible for securing the chain by creating disputes on false assertions. @@ -41,7 +41,7 @@ As the Orbit license allows chain owners to customize their Rollup, the AEP lice - Revenue earned through fees on top of the bridge. - Broadly, any revenue earned in connection with your use of Arbitrum Nitro. -You can read the relevant legal terminology in Section 2 of the [AEP Terms](https://docs.arbitrum.foundation/assets/files/Arbitrum%20Expansion%20Program%20Jan182024-4f08b0c2cb476a55dc153380fa3e64b0.pdf). +You can read the relevant legal terminology in Section 2 of the [AEP Terms](https://docs.arbitrum.foundation/aep/ArbitrumExpansionProgramTerms.pdf). ## Calculating AEP fees @@ -81,7 +81,7 @@ If a team elects to deduct their assertion posting costs from eligible validator - Communicate to the Arbitrum Foundation that they intend to deduct on-chain assertion costs - Align on a cadence of disbursal and accounting these costs with the Arbitrum Foundation (e.g., quarterly, annually) - - At this cadence, Provide on-chain accounting to the Arbitrum Foundation to substantiate deducted costs from the AEP Fee Router stream. + - At this cadence, provide on-chain accounting to the Arbitrum Foundation to substantiate deducted costs from the AEP Fee Router stream. To implement the deduction, the team should do the following: @@ -94,15 +94,15 @@ To implement the deduction, the team should do the following: Certain Orbit configurations and customizations require special handling of AEP fees. The following is a non-exhaustive list of applicable scenarios and how to ensure AEP compliance. If any of the following cases apply, the recommended approach for fee handling will require manual handling of a portion of or all AEP Fees. -### L2-Based Custom Gas Tokens +### L2-based custom gas tokens -If you are an L3 or higher chain with a custom gas token, your custom gas token contract might be deployed on L2. If this L2 is not Arbitrum One, then the L2 token can be transferred via the AEP Fee Router, as this would first require bridging down to Ethereum (impossible for L2-based tokens). In this instance, we recommend your chain pay fees in ETH by manually sending fees to an ETH-configured routing system. +If you are an L3 or higher chain with a custom gas token, your custom gas token contract might be deployed on L2. If this L2 is not an Arbitrum chain, then the L2 token can't be transferred via the AEP Fee Router, as this would first require bridging down to Ethereum (impossible for L2-based tokens). In this instance, we recommend your chain pay fees in ETH by manually sending fees to an ETH-configured routing system. ### Non-Ethereum L1 If your Orbit chain is deployed on a non-Ethereum L1 (e.g., Solana, BNB Chain), your fees must be manually transferred to a Foundation-controlled address. -### Novel Fee-Earning Customizations +### Novel fee-earning customizations As discussed above in Additional revenue sources, if you have customized your Orbit chain to earn revenue through any enshrined component, this revenue must be calculated as part of the AEP fees. In such cases, we recommend engaging with the AF to agree on a revenue model and reporting cadence and then manually send additional fees into the routing system as required. diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/customize-arbos.mdx b/arbitrum-docs/launch-orbit-chain/how-tos/customize-arbos.mdx index b9cd1eac5..1982278b8 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/customize-arbos.mdx +++ b/arbitrum-docs/launch-orbit-chain/how-tos/customize-arbos.mdx @@ -6,16 +6,13 @@ sidebar_position: 7 content_type: how-to --- -import PublicPreviewBannerPartial from '../partials/_orbit-public-preview-banner-partial.md'; import CustomizeCautionBannerPartial from '../partials/_orbit-customize-caution-banner-partial.md'; - - ## Cases where you may want to consider customizing your own ArbOS upgrade -1. When you want to make changes to your Nitro code that affect the State Transition Function, or STF (you may refer to the [Customize STF docs](./customize-stf.mdx#Preface)), and +1. When you want to make changes to your Nitro code that affect the State Transition Function, or STF (you may refer to the [Customize STF docs](./customize-stf.mdx#introduction)), and 2. If your desired changes need to be made to a live and operational Orbit chain @@ -29,7 +26,7 @@ Below, you will find 4 examples of ArbOS-related code changes and, generally, ho ### 1. Add a new method to exsiting precompile on a specific ArbOS version: -After you add `sayHi()` to `ArbSys.go` according to the guide in [customize precompile option 1](./customize-precompile.mdx#option-1-Add-new-methods-to-an-existing-precompile), +After you add `sayHi()` to `ArbSys.go` according to the guide in [customize precompile option 1](./customize-precompile.mdx#option-1-add-new-methods-to-an-existing-precompile), you need continue to modify [precompile.go][precompile_main_file_link]. For example, the original code is: diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/customize-deployment-configuration.md b/arbitrum-docs/launch-orbit-chain/how-tos/customize-deployment-configuration.md index 201fb2baf..e7c275b79 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/customize-deployment-configuration.md +++ b/arbitrum-docs/launch-orbit-chain/how-tos/customize-deployment-configuration.md @@ -5,10 +5,6 @@ author: symbolpunk sidebar_position: 1 --- -import PublicPreviewBannerPartial from '../partials/_orbit-public-preview-banner-partial.md'; - - - When you visit the [Orbit chain deployment portal](https://orbit.arbitrum.io/) to launch your Orbit chain, you'll be prompted to complete a form that looks like this: import { PlaceholderForm } from '/src/components/PlaceholderForm/PlaceholderForm'; @@ -21,7 +17,7 @@ Let's briefly review each of the deployment configuration parameters, the ration ### Chain ID -Don't worry about this; it's inconsequential for devnets. In production scenarios (which aren't yet supported), you'll want to use a unique integer identifier that represents your chain's network on chain indexes like [Chainlist.org](http://chainlist.org). +Don't worry about this; it's inconsequential for devnets. In production scenarios, you'll want to use a unique integer identifier that represents your chain's network on chain indexes like [Chainlist.org](http://chainlist.org). ### Chain name diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/customize-precompile.mdx b/arbitrum-docs/launch-orbit-chain/how-tos/customize-precompile.mdx index 43cd468d1..622972e88 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/customize-precompile.mdx +++ b/arbitrum-docs/launch-orbit-chain/how-tos/customize-precompile.mdx @@ -6,11 +6,8 @@ sidebar_position: 5 content_type: how-to --- -import PublicPreviewBannerPartial from '../partials/_orbit-public-preview-banner-partial.md'; import CustomizeCautionBannerPartial from '../partials/_orbit-customize-caution-banner-partial.md'; - - :::caution @@ -59,7 +56,7 @@ Next, follow the steps in [How to customize your Orbit chain's behavior](./custo :::info -Note that the instructions provided in [How to run a full node](/run-arbitrum-node/03-run-full-node.md) **will not** work with your Orbit node. See [Optional parameters (Orbit)](/node-running/how-tos/running-an-orbit-node.mdx#optional-parameters) for Orbit-specific CLI flags. +Note that the instructions provided in [How to run a full node](/run-arbitrum-node/03-run-full-node.mdx) **will not** work with your Orbit node. See [Optional parameters (Orbit)](/node-running/how-tos/running-an-orbit-node.mdx#optional-parameters) for Orbit-specific CLI flags. ::: @@ -134,7 +131,7 @@ Next, follow the steps in [How to customize your Orbit chain's behavior](./custo :::info -Note that the instructions provided in [How to run a full node](/run-arbitrum-node/03-run-full-node.md) **will not** work with your Orbit node. See [Optional parameters (Orbit)](/node-running/how-tos/running-an-orbit-node.mdx#optional-parameters) for Orbit-specific CLI flags. +Note that the instructions provided in [How to run a full node](/run-arbitrum-node/03-run-full-node.mdx) **will not** work with your Orbit node. See [Optional parameters (Orbit)](/node-running/how-tos/running-an-orbit-node.mdx#optional-parameters) for Orbit-specific CLI flags. ::: @@ -221,7 +218,7 @@ Our function now emits an event, which means that when calling it, the state wil function sayHi() external returns(string memory); ``` -Next, build Nitro by following the instructions in [How to build Nitro locally](/run-arbitrum-node/nitro/01-build-nitro-locally.md). Note that if you've already built the Docker image, you still need run the last step to rebuild. +Next, build Nitro by following the instructions in [How to build Nitro locally](/run-arbitrum-node/nitro/01-build-nitro-locally.mdx). Note that if you've already built the Docker image, you still need run the last step to rebuild. Run Nitro with the following command: @@ -231,7 +228,7 @@ docker run --rm -it -v /some/local/dir/arbitrum:/home/user/.arbitrum -p 0.0.0.0 :::info -Note that the instructions provided in [How to run a full node](/run-arbitrum-node/03-run-full-node.md) **will not** work with your Orbit node. See [Optional parameters (Orbit)](/node-running/how-tos/running-an-orbit-node.mdx#optional-parameters) for Orbit-specific CLI flags. +Note that the instructions provided in [How to run a full node](/run-arbitrum-node/03-run-full-node.mdx) **will not** work with your Orbit node. See [Optional parameters (Orbit)](/node-running/how-tos/running-an-orbit-node.mdx#optional-parameters) for Orbit-specific CLI flags. ::: @@ -305,7 +302,7 @@ func (con ArbInfo) GetBalanceCustom(c ctx, evm mech, account addr) (huge, error) To register this new precompile method, refer to Option 1 above. -Next, build Nitro by following the instructions in [How to build Nitro locally](/run-arbitrum-node/nitro/01-build-nitro-locally.md). Note that if you've already built the Docker image, you still need run the last step to rebuild. +Next, build Nitro by following the instructions in [How to build Nitro locally](/run-arbitrum-node/nitro/01-build-nitro-locally.mdx). Note that if you've already built the Docker image, you still need run the last step to rebuild. Run Nitro with the following command: @@ -315,7 +312,7 @@ docker run --rm -it -v /some/local/dir/arbitrum:/home/user/.arbitrum -p 0.0.0.0 :::info -Note that the instructions provided in [How to run a full node](/run-arbitrum-node/03-run-full-node.md) **will not** work with your Orbit node. See [Optional parameters (Orbit)](/node-running/how-tos/running-an-orbit-node.mdx#optional-parameters) for Orbit-specific CLI flags. +Note that the instructions provided in [How to run a full node](/run-arbitrum-node/03-run-full-node.mdx) **will not** work with your Orbit node. See [Optional parameters (Orbit)](/node-running/how-tos/running-an-orbit-node.mdx#optional-parameters) for Orbit-specific CLI flags. ::: @@ -396,7 +393,7 @@ Result 2: Here we can see that the gas cost incurred by the execution of the first transaction is `gasUsed - gasUsedForL1 = 22938`. Similarly, the gas cost incurred by the execution of the second transaction is `22538`. If you subtract the two, the result is `400`, as expected. -To learn more about the gas cost model, see [how to estimate gas](/build-decentralized-apps/02-how-to-estimate-gas.md). +To learn more about the gas cost model, see [how to estimate gas](/build-decentralized-apps/02-how-to-estimate-gas.mdx). ## Option 5: Call and modify state diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/customize-stf.mdx b/arbitrum-docs/launch-orbit-chain/how-tos/customize-stf.mdx index 102ff05ad..46daafcb4 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/customize-stf.mdx +++ b/arbitrum-docs/launch-orbit-chain/how-tos/customize-stf.mdx @@ -6,11 +6,8 @@ sidebar_position: 4 content_type: how-to --- -import PublicPreviewBannerPartial from '../partials/_orbit-public-preview-banner-partial.md'; import CustomizeCautionBannerPartial from '../partials/_orbit-customize-caution-banner-partial.md'; - - ## Introduction @@ -19,7 +16,7 @@ Before customizing your Orbit chain, it's important to understand what the State The STF defines how new blocks are produced from input messages (i.e. transactions). This guide is only necessary for changes that modify the State Transition Function. To customize other node behavior, such as RPC behavior or the sequencer's ordering policy, you can simply -[build your own node](/run-arbitrum-node/nitro/01-build-nitro-locally.md) without worrying about the rest of this guide. +[build your own node](/run-arbitrum-node/nitro/01-build-nitro-locally.mdx) without worrying about the rest of this guide. However, changes that modify the STF require updating the fraud proving system to recognize the new behavior as correct. Otherwise, the fraud prover would side with unmodified nodes, which would win fraud proofs against your modified node. @@ -139,7 +136,7 @@ docker run --rm -it -v /path/to/your/node/dir:/home/user/.arbitrum -p 0.0.0.0:84 :::info -Note that the instructions provided in [How to run a full node](/run-arbitrum-node/03-run-full-node.md) **will not** work with your Orbit node. See [Optional parameters (Orbit)](/node-running/how-tos/running-an-orbit-node.mdx#optional-parameters) for Orbit-specific CLI flags. +Note that the instructions provided in [How to run a full node](/run-arbitrum-node/03-run-full-node.mdx) **will not** work with your Orbit node. See [Optional parameters (Orbit)](/node-running/how-tos/running-an-orbit-node.mdx#optional-parameters) for Orbit-specific CLI flags. ::: @@ -220,8 +217,8 @@ To do that, you'll need to first extract the replay binary from the `nitro-node- docker run --rm --name replay-binary-extractor --entrypoint sleep custom-nitro-node-dev infinity docker cp replay-binary-extractor:/home/user/target/machines/latest extracted-replay-binary docker stop replay-binary-extractor -cat extracted-replay-binary/module.root -mv extracted-replay-binary "target/machines/$(cat extracted-replay-binary/module.root)" +cat extracted-replay-binary/module-root.txt +mv extracted-replay-binary "target/machines/$(cat extracted-replay-binary/module-root.txt)" ``` These commands will output the new WASM module root, and create the directory `target/machines/`. diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/fast-withdrawals.mdx b/arbitrum-docs/launch-orbit-chain/how-tos/fast-withdrawals.mdx index 89e0d3547..3e0414932 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/fast-withdrawals.mdx +++ b/arbitrum-docs/launch-orbit-chain/how-tos/fast-withdrawals.mdx @@ -32,7 +32,7 @@ It is possible for an Orbit Rollup to adopt fast withdrawals. However, it would ### Minimum validator and DAC nodes -We recommend that any Fast Withdrawals-enabled chain have at least three DAC members and three validators acting in the fast withdrawals committee. Given that fast withdrawals will enable confirmation of new Rollup state much faster than the usual 7-day challenge period (15 minutes for L2s and 15 seconds for L3s), it becomes even more important to have additional parties involved in validation to further reduce trust assumptions. This requirement can be be met with three total operators, who each run a single DAS node and a single validator. +We recommend that any Fast Withdrawals-enabled chain have at least three DAC members and three validators acting in the fast withdrawals committee. Given that fast withdrawals will enable confirmation of new Rollup state much faster than the usual 6.4-day challenge period (15 minutes for L2s and 15 seconds for L3s), it becomes even more important to have additional parties involved in validation to further reduce trust assumptions. This requirement can be be met with three total operators, who each run a single DAS node and a single validator. ## Technical lower bound for fast withdrawals @@ -194,3 +194,9 @@ The following parameters need to be configured in those nodes. | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--node.staker.enable-fast-confirmation=true` | Enables fast withdrawals in the validator node | | `--node.staker.make-assertion-interval=0h15m0s` | Since assertions need to be created for them to be confirmed, the minimum interval to create these assertions should be set to an amount close to the `minimumAssertionPeriod` defined in the Rollup contract. Modify `0h15m0s` to the configured value. | + +:::note + +Immediately after configuring fast withdrawals - your chain may not be operating fully at speed yet. This is because the validators have to work through the backlog of assertions which were not yet confirmed. You will see a series of NodeCreated and NodeConfirmed events. Once the backlog has been processed, your chain should operate fully at speed. + +::: diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/manage-fee-collectors.md b/arbitrum-docs/launch-orbit-chain/how-tos/manage-fee-collectors.md index 923cda122..184f26f5b 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/manage-fee-collectors.md +++ b/arbitrum-docs/launch-orbit-chain/how-tos/manage-fee-collectors.md @@ -7,10 +7,6 @@ sidebar_position: 6 content_type: how-to --- -import PublicPreviewBannerPartial from '../partials/_orbit-public-preview-banner-partial.md'; - - - As part of the activity of an Orbit chain, different fees are collected with every transaction. These fees are collected as a single amount (the transaction fees) but are internally split into different components depending on their purpose. Each component can also be transferred to a different fee collector address that can be configured on your chain. This guide describes the different fees that are collected, and explains how to specify the fee collector address on your chain for each fee type. @@ -29,8 +25,8 @@ There are four fee types that are collected on every transaction of an Orbit cha You can find more detailed information about these fee types in these pages: -- [L2 fees](/how-arbitrum-works/gas-fees.md) for the Orbit base fee and surplus fee -- [L1 fees](/how-arbitrum-works/l1-gas-pricing.md) for the Parent chain base fee and surplus fee +- [L2 fees](/how-arbitrum-works/09-gas-fees.mdx#l2-gas-pricing) for the Orbit base fee and surplus fee +- [L1 fees](/how-arbitrum-works/09-gas-fees.mdx#l1-gas-pricing) for the Parent chain base fee and surplus fee ## How to configure the fee collector addresses? @@ -38,15 +34,15 @@ Let's now look at how to configure the collector addresses for each fee type. ### Orbit base fee -Orbit base fees are paid to the `infraFeeAccount` configured in your chain. You can retrieve the current configured address by calling the method `getInfraFeeAccount()` of the [ArbOwnerPublic](/build-decentralized-apps/precompiles/02-reference.md#arbownerpublic) precompile. For example: +Orbit base fees are paid to the `infraFeeAccount` configured in your chain. You can retrieve the current configured address by calling the method `getInfraFeeAccount()` of the [ArbOwnerPublic](/build-decentralized-apps/precompiles/02-reference.mdx#arbownerpublic) precompile. For example: ```shell cast call --rpc-url $ORBIT_CHAIN_RPC 0x000000000000000000000000000000000000006B "getInfraFeeAccount() (address)" ``` -_Note: The [ArbOwner](/build-decentralized-apps/precompiles/02-reference.md#arbowner) precompile also has a `getInfraFeeAccount()` method that can be used, but only by the owner of the chain._ +_Note: The [ArbOwner](/build-decentralized-apps/precompiles/02-reference.mdx#arbowner) precompile also has a `getInfraFeeAccount()` method that can be used, but only by the owner of the chain._ -Alternatively, you can use the Orbit SDK to retrieve the current address configured as `infraFeeAccount`, by calling the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.md#arbowner) precompile: +Alternatively, you can use the Orbit SDK to retrieve the current address configured as `infraFeeAccount`, by calling the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.mdx#arbowner) precompile: ```typescript const orbitChainClient = createPublicClient({ @@ -59,7 +55,7 @@ const infraFeeAccount = await orbitChainClient.arbOwnerReadContract({ }); ``` -To set a new `infraFeeAccount`, use the method `setInfraFeeAccount(address)` of the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.md#arbowner) precompile. For example: +To set a new `infraFeeAccount`, use the method `setInfraFeeAccount(address)` of the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.mdx#arbowner) precompile. For example: ```shell cast send --rpc-url $ORBIT_CHAIN_RPC --private-key $OWNER_PRIVATE_KEY 0x0000000000000000000000000000000000000070 "setInfraFeeAccount(address) ()" $NEW_INFRAFEEACCOUNT_ADDRESS @@ -88,15 +84,15 @@ await orbitChainClient.sendRawTransaction({ ### Orbit surplus fee -Orbit surplus fees are paid to the `networkFeeAccount` configured in your chain. You can retrieve the current configured address by calling the method `getNetworkFeeAccount()` of the [ArbOwnerPublic](/build-decentralized-apps/precompiles/02-reference.md#arbownerpublic) precompile. For example: +Orbit surplus fees are paid to the `networkFeeAccount` configured in your chain. You can retrieve the current configured address by calling the method `getNetworkFeeAccount()` of the [ArbOwnerPublic](/build-decentralized-apps/precompiles/02-reference.mdx#arbownerpublic) precompile. For example: ```shell cast call --rpc-url $ORBIT_CHAIN_RPC 0x000000000000000000000000000000000000006B "getNetworkFeeAccount() (address)" ``` -_Note: The [ArbOwner](/build-decentralized-apps/precompiles/02-reference.md#arbowner) precompile also has a `getNetworkFeeAccount()` method that can be used, but only by the owner of the chain._ +_Note: The [ArbOwner](/build-decentralized-apps/precompiles/02-reference.mdx#arbowner) precompile also has a `getNetworkFeeAccount()` method that can be used, but only by the owner of the chain._ -Alternatively, you can use the Orbit SDK to retrieve the current address configured as `networkFeeAccount`, by calling the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.md#arbowner) precompile: +Alternatively, you can use the Orbit SDK to retrieve the current address configured as `networkFeeAccount`, by calling the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.mdx#arbowner) precompile: ```typescript const orbitChainClient = createPublicClient({ @@ -109,7 +105,7 @@ const networkFeeAccount = await orbitChainClient.arbOwnerReadContract({ }); ``` -To set a new `networkFeeAccount`, use the method `setNetworkFeeAccount(address)` of the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.md#arbowner) precompile. For example: +To set a new `networkFeeAccount`, use the method `setNetworkFeeAccount(address)` of the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.mdx#arbowner) precompile. For example: ```shell cast send --rpc-url $ORBIT_CHAIN_RPC --private-key $OWNER_PRIVATE_KEY 0x0000000000000000000000000000000000000070 "setNetworkFeeAccount(address) ()" $NEW_NETWORKFEEACCOUNT_ADDRESS @@ -144,7 +140,7 @@ Reading information from the `ArgAggregator` precompile or using it to set new i ::: -Parent chain base fees are paid to the fee collector of the active batch poster configured in your chain. The current configured batch posters can be obtained by calling the method `getBatchPosters()` of the [ArbAggregator](/build-decentralized-apps/precompiles/02-reference.md#arbaggregator) precompile. For example: +Parent chain base fees are paid to the fee collector of the active batch poster configured in your chain. The current configured batch posters can be obtained by calling the method `getBatchPosters()` of the [ArbAggregator](/build-decentralized-apps/precompiles/02-reference.mdx#arbaggregator) precompile. For example: ```shell cast call --rpc-url $ORBIT_CHAIN_RPC 0x000000000000000000000000000000000000006D "getBatchPosters() (address[])" @@ -156,19 +152,19 @@ This list has to also be verified against the `SequencerInbox` contract living o cast call --rpc-url $PARENT_CHAIN_RPC $SEQUENCER_INBOX_ADDRESS "isBatchPoster(address) (bool)" $BATCH_POSTER_ADDRESS ``` -Once you have the current batch poster, you can obtain the fee collector address configured for that batch poster by calling the method `getFeeCollector(address)` of the [ArbAggregator](/build-decentralized-apps/precompiles/02-reference.md#arbaggregator) precompile and passing the address of the batch poster. +Once you have the current batch poster, you can obtain the fee collector address configured for that batch poster by calling the method `getFeeCollector(address)` of the [ArbAggregator](/build-decentralized-apps/precompiles/02-reference.mdx#arbaggregator) precompile and passing the address of the batch poster. ```shell cast call --rpc-url $ORBIT_CHAIN_RPC 0x000000000000000000000000000000000000006D "getFeeCollector(address) (address)" $BATCH_POSTER_ADDRESS ``` -To set a new fee collector for a specific batch poster, use the method `setFeeCollector(address, address)` of the [ArbAggregator](/build-decentralized-apps/precompiles/02-reference.md#arbaggregator) precompile and pass the address of the batch poster and the address of the new fee collector. +To set a new fee collector for a specific batch poster, use the method `setFeeCollector(address, address)` of the [ArbAggregator](/build-decentralized-apps/precompiles/02-reference.mdx#arbaggregator) precompile and pass the address of the batch poster and the address of the new fee collector. ```shell cast send --rpc-url $ORBIT_CHAIN_RPC --private-key $OWNER_PRIVATE_KEY 0x000000000000000000000000000000000000006D "setFeeCollector(address,address) ()" $BATCH_POSTER_ADDRESS $NEW_FEECOLLECTOR_ADDRESS ``` -Finally, if you want to set a new batch poster, you can call the method `addBatchPoster(address)` of the of the [ArbAggregator](/build-decentralized-apps/precompiles/02-reference.md#arbaggregator) precompile and pass the address of the new batch poster, and later call the method `setIsBatchPoster(address,bool)` of the SequencerInbox contract on the parent chain. +Finally, if you want to set a new batch poster, you can call the method `addBatchPoster(address)` of the of the [ArbAggregator](/build-decentralized-apps/precompiles/02-reference.mdx#arbaggregator) precompile and pass the address of the new batch poster, and later call the method `setIsBatchPoster(address,bool)` of the SequencerInbox contract on the parent chain. ```shell cast send --rpc-url $ORBIT_CHAIN_RPC --private-key $OWNER_PRIVATE_KEY 0x000000000000000000000000000000000000006D "addBatchPoster(address) ()" $NEW_BATCH_POSTER_ADDRESS @@ -182,13 +178,13 @@ _Note: When setting a new batch poster, its fee collector will be configured to ### Parent chain surplus fee -Parent chain surplus fees are paid to a specific `L1RewardRecipient` address that is configured individually per chain. The current fee collector address can be obtained by calling the method `getL1RewardRecipient()` of the [ArbGasInfo](/build-decentralized-apps/precompiles/02-reference.md#arbgasinfo) precompile. For example: +Parent chain surplus fees are paid to a specific `L1RewardRecipient` address that is configured individually per chain. The current fee collector address can be obtained by calling the method `getL1RewardRecipient()` of the [ArbGasInfo](/build-decentralized-apps/precompiles/02-reference.mdx#arbgasinfo) precompile. For example: ```shell cast call --rpc-url $ORBIT_CHAIN_RPC 0x000000000000000000000000000000000000006C "getL1RewardRecipient() (address)" ``` -To get the amount of rewards that are being paid to this fee collector, you can call the method `getL1RewardRate()` of the [ArbGasInfo](/build-decentralized-apps/precompiles/02-reference.md#arbgasinfo) precompile. This function will return the amount of wei per gas unit paid to the `L1RewardRecipient` configured. For example: +To get the amount of rewards that are being paid to this fee collector, you can call the method `getL1RewardRate()` of the [ArbGasInfo](/build-decentralized-apps/precompiles/02-reference.mdx#arbgasinfo) precompile. This function will return the amount of wei per gas unit paid to the `L1RewardRecipient` configured. For example: ```shell cast call --rpc-url $ORBIT_CHAIN_RPC 0x000000000000000000000000000000000000006C "getL1RewardRate() (uint64)" @@ -211,7 +207,7 @@ const parentChainRewardRate = await orbitChainClient.arbGasInfoReadContract({ }); ``` -To set a new `L1RewardRecipient` address, you can call the method `setL1PricingRewardRecipient(address)` of the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.md#arbowner) precompile, and pass the address of the new reward recipient. For example: +To set a new `L1RewardRecipient` address, you can call the method `setL1PricingRewardRecipient(address)` of the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.mdx#arbowner) precompile, and pass the address of the new reward recipient. For example: ```shell cast send --rpc-url $ORBIT_CHAIN_RPC --private-key $OWNER_PRIVATE_KEY 0x0000000000000000000000000000000000000070 "setL1PricingRewardRecipient(address) ()" $NEW_L1REWARDRECIPIENT_ADDRESS @@ -238,7 +234,7 @@ await orbitChainClient.sendRawTransaction({ }); ``` -To change the reward rate, you can use the method `setL1PricingRewardRate(uint64)` of the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.md#arbowner) precompile and pass the amount of wei per gas unit to reward. For example: +To change the reward rate, you can use the method `setL1PricingRewardRate(uint64)` of the [ArbOwner](/build-decentralized-apps/precompiles/02-reference.mdx#arbowner) precompile and pass the amount of wei per gas unit to reward. For example: ```shell cast send --rpc-url $ORBIT_CHAIN_RPC --private-key $OWNER_PRIVATE_KEY 0x0000000000000000000000000000000000000070 "setL1PricingRewardRate(uint64) ()" $NEW_REWARD_RATE diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/orbit-chain-finality.md b/arbitrum-docs/launch-orbit-chain/how-tos/orbit-chain-finality.md index 696540215..068d6e54a 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/orbit-chain-finality.md +++ b/arbitrum-docs/launch-orbit-chain/how-tos/orbit-chain-finality.md @@ -9,11 +9,11 @@ content_type: how-to ## Child chain transactions -Generally, transactions executed through the sequencer on Orbit chains [achieve finality](/how-arbitrum-works/tx-lifecycle.md) equivalent to their parent chain once the relevant transaction data has been [posted in a batch](/how-arbitrum-works/sequencer.md). This means that transactions on Orbit chains are considered final in minutes. +Generally, transactions executed through the sequencer on Orbit chains [achieve finality](/how-arbitrum-works/02-transaction-lifecycle.mdx) equivalent to their parent chain once the relevant transaction data has been [posted in a batch](/how-arbitrum-works/06-optimistic-rollup.mdx). This means that transactions on Orbit chains are considered final in minutes. ## Parent chain → child chain transactions -Messages being sent through the delayed inbox of a parent chain as [retryable tickets](/how-arbitrum-works/arbos/l1-l2-messaging.md#retryable-tickets), including deposits through token bridges, are released by the [sequencer](/how-arbitrum-works/inside-arbitrum-nitro.md#if-the-sequencer-is-well-behaved) once it has reasonable confidence of finality on the parent chain. For example, on an L2 chain settling to Ethereum, the sequencer will release delayed messages to the inbox after 40 blocks. Following this, the transaction must complete another finality period for the Ethereum transaction that promoted it to achieve finality. +Messages being sent through the delayed inbox of a parent chain as [retryable tickets](/how-arbitrum-works/10-l1-to-l2-messaging.mdx#retryable-tickets), including deposits through token bridges, are released by the [sequencer](/how-arbitrum-works/03-sequencer.mdx) once it has reasonable confidence of finality on the parent chain. For example, on an L2 chain settling to Ethereum, the sequencer will release delayed messages to the inbox after 40 blocks. Following this, the transaction must complete another finality period for the Ethereum transaction that prompted it to achieve finality. Orbit L3s may configure the finality of transactions executed through the delayed inbox to depend on different layers of finality. By default, Orbit chains will rely on the number of L1 block confirmations, effectively finalizing an L3 deposit as soon as L1 finalizes the batch posted by Arbitrum One or when a DACert is posted by Arbitrum Nova. This would be on the order of tens of minutes. @@ -33,4 +33,4 @@ Note, however, that if you choose to enable fast bridging, a re-org of un-finali ## Child chain → parent chain transactions -Normally, [outgoing transactions](/how-arbitrum-works/arbos/l2-l1-messaging.md) must wait until the assertion that includes their L2 message is confirmed (~one week) before a client can execute the message on L1. However, in the near future [Anytrust](/how-arbitrum-works/inside-anytrust.md) chains will be able to leverage their DAC to enable fast confirmations of withdrawals through the native token bridge. By immediately confirming assertions that have been signed by the DAC, finality can be reduced to ~fifteen minutes. +Normally, [outgoing transactions](/how-arbitrum-works/11-l2-to-l1-messaging.mdx) must wait until the assertion that includes their L2 message is confirmed (~one week) before a client can execute the message on L1. However, in the near future [Anytrust](/how-arbitrum-works/08-anytrust-protocol.mdx) chains will be able to leverage their DAC to enable fast confirmations of withdrawals through the native token bridge. By immediately confirming assertions that have been signed by the DAC, finality can be reduced to ~fifteen minutes. diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-configuring-orbit-chain.md b/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-configuring-orbit-chain.md index 1425a1de8..6e4fa3e36 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-configuring-orbit-chain.md +++ b/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-configuring-orbit-chain.md @@ -26,7 +26,7 @@ Orbit chains have three areas of configuration: ## 1. Parent chain configuration -Configuring the parent chain is the initial step to setting up your Orbit chain. Most of the parent chain configurations are specified during the setup phase. Detailed instructions can be found in the [Rollup Deployment Parameters](orbit-sdk-deploying-rollup-chain#rollup-deployment-parameter) section of the Rollup deployment guide. +Configuring the parent chain is the initial step to setting up your Orbit chain. Most of the parent chain configurations are specified during the setup phase. Detailed instructions can be found in the [Rollup Deployment Parameters](/launch-orbit-chain/how-tos/orbit-sdk-deploying-rollup-chain.md#rollup-deployment-parameters) section of the Rollup deployment guide. After the initial setup, the chain owner can modify configurations as needed. For instance, the validator set can be updated by invoking the [`setValidKeyset`](https://github.com/OffchainLabs/nitro-contracts/blob/90037b996509312ef1addb3f9352457b8a99d6a6/src/bridge/SequencerInbox.sol#L751) function with a new set of validators. This adaptability facilitates your chain's optimization and management. @@ -53,7 +53,7 @@ You can use these setter functions to configure the child chain parameters: | `setInfraFeeAccount` | Sets the infrastructure fee account address, which receives all fees collected on the child chain. It is meant to receive the minimum base fee, with any amount above that going to the network fee account. | | `setNetworkFeeAccount` | Sets the network fee account address. As mentioned, this address collects all fees above the base fee. Note that if you set this amount to the 0 address on your chain, all fees will be deposited into the infrastructure fee account. | | `scheduleArbOSUpgrade` | If you plan to upgrade the ArbOS version of your chain, this method can help you schedule the upgrade. For a complete guide, please refer to the explanation for the [arbos upgrade](arbos-upgrade.md). | -| `setChainConfig` | We discussed the `chainConfig` in the [Rollup deployment guide](orbit-sdk-deploying-rollup-chain.md#chain-config-parameter) in detail. If you wish to change any field of the `chainConfig`, you need to use this method on the child chain. | +| `setChainConfig` | We discussed the `chainConfig` in the [Rollup deployment guide](./orbit-sdk-deploying-rollup-chain.md#4-chainconfig) in detail. If you wish to change any field of the `chainConfig`, you need to use this method on the child chain. | ### Getter functions diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-anytrust-chain.md b/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-anytrust-chain.md index 558543234..64f56802c 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-anytrust-chain.md +++ b/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-anytrust-chain.md @@ -30,7 +30,7 @@ AnyTrust chains implement the Arbitrum AnyTrust protocol, an alternative to the ### Deployment steps -The deployment process of AnyTrust chains is very similar to that of [Rollup chains](orbit-sdk-deploying-rollup-chain.md#rollup-config-param), but with some differences that we'll discuss in this guide. +The deployment process of AnyTrust chains is very similar to that of [Rollup chains](/launch-orbit-chain/how-tos/orbit-sdk-deploying-rollup-chain.md#rollup-configuration-parameters), but with some differences that we'll discuss in this guide. Here are the steps involved in the deployment process: @@ -116,7 +116,7 @@ In this example, `txReceipt` refers to the transaction receipt you received afte ### 4. Setting valid keyset on parent chain -The final step is to set up a valid keyset for your Data Availability Committee (DAC) on the parent chain. See [How to configure a DAC](/run-arbitrum-node/data-availability-committees/04-configure-dac.md) for instructions. +The final step is to set up a valid keyset for your Data Availability Committee (DAC) on the parent chain. See [How to configure a DAC](/run-arbitrum-node/data-availability-committees/04-configure-dac.mdx) for instructions. Once created, your keyset needs to be established on your Orbit chain's `SequencerInbox` contract on the parent chain. To facilitate this, we provide an API in Orbit SDK named `setValidKeysetPrepareTransactionRequest`. This API requires specific information you can gather at [step three](#3-getting-the-anytrust-orbit-chain-information-after-deployment). This includes the `upgradeExecutor` and `sequencerInbox` addresses of your Orbit chain, the generated keyset for your committee, and the owner's account. diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-rollup-chain.md b/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-rollup-chain.md index acdcf4aa2..eefa942a0 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-rollup-chain.md +++ b/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-rollup-chain.md @@ -194,7 +194,7 @@ The Orbit SDK provides two APIs, `createRollupPrepareDeploymentParamsConfig` and This API is designed to take parameters defined in the Config struct and fill in the rest with default values. It outputs a complete Config struct that is ready for use. -For example, to create a Config struct with a specific chain ID (`chainId`), an owner address (`deployer_address`), and a `chainConfig` as described in the [previous section](#chain-config-parameter), you would use the Orbit SDK as follows: +For example, to create a Config struct with a specific chain ID (`chainId`), an owner address (`deployer_address`), and a `chainConfig` as described in the [previous section](#rollup-configuration-parameters), you would use the Orbit SDK as follows: ```js import { createPublicClient, http } from 'viem'; diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-token-bridge.md b/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-token-bridge.md index 619f57ea2..4254434d5 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-token-bridge.md +++ b/arbitrum-docs/launch-orbit-chain/how-tos/orbit-sdk-deploying-token-bridge.md @@ -22,7 +22,7 @@ This document is under construction and may change significantly as we incorpora :::info -See the [`ERC-20` token bridge overview](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.md) for more information about the token bridge's design and operational dynamics, and the ["create-token-bridge-eth" example ](https://github.com/OffchainLabs/arbitrum-orbit-sdk/tree/main/examples/create-token-bridge-eth) for additional guidance. +See the [`ERC-20` token bridge overview](/build-decentralized-apps/token-bridging/03-token-bridge-erc20.mdx) for more information about the token bridge's design and operational dynamics, and the ["create-token-bridge-eth" example ](https://github.com/OffchainLabs/arbitrum-orbit-sdk/tree/main/examples/create-token-bridge-eth) for additional guidance. ::: @@ -44,8 +44,8 @@ Once an Orbit chain has been deployed and initialized, the bridge contracts need The token bridge deployment process is the same for all Orbit chains types except for the following: -- **Custom fee token Orbit chains** which require [token approval](#step-1). -- **`ETH`-based Orbit chains**, for which you need to [set up a WETH gateway](#step-5). +- **Custom fee token Orbit chains** which require [token approval](#1-token-approval). +- **`ETH`-based Orbit chains**, for which you need to [set up a WETH gateway](#5-setting-up-the-weth-gateway). ::: @@ -93,7 +93,7 @@ Please note that after generating the raw transaction, the deployer must still s Deploying token bridge contracts is the first step in creating a bridge between the parent and the Orbit chain. -The deployment process is the same as Orbit chain contracts', where a primary contract facilitates the deployment of core contracts. The token bridge contracts are deployed on the parent and child chains by `TokenBridgeCreator`. `TokenBridgeCreator` does it in a single transaction using the [ Retryable Tickets protocol ](/how-arbitrum-works/arbos/l1-l2-messaging.md#retryable-ticketsO). +The deployment process is the same as Orbit chain contracts', where a primary contract facilitates the deployment of core contracts. The token bridge contracts are deployed on the parent and child chains by `TokenBridgeCreator`. `TokenBridgeCreator` does it in a single transaction using the [ Retryable Tickets protocol ](/how-arbitrum-works/10-l1-to-l2-messaging.mdx#retryable-tickets). Orbit SDK provides an API that automates the deployment by interacting with the `TokenBridgeCreator` contract. The API is `createTokenBridgePrepareTransactionRequest`, which processes the necessary inputs and generates a transaction request tailored for token bridge deployment. diff --git a/arbitrum-docs/launch-orbit-chain/how-tos/set-up-aep-fee-router.mdx b/arbitrum-docs/launch-orbit-chain/how-tos/set-up-aep-fee-router.mdx index 8b5ac2d7e..b28b645f2 100644 --- a/arbitrum-docs/launch-orbit-chain/how-tos/set-up-aep-fee-router.mdx +++ b/arbitrum-docs/launch-orbit-chain/how-tos/set-up-aep-fee-router.mdx @@ -1,58 +1,55 @@ --- title: 'How to set up an AEP fee router' sidebar_label: 'Set up an AEP fee router' -description: 'Learn how to implement AEP fee router.' -author: Midroni -sme: Midroni +description: 'Learn how to setup an AEP fee router.' +author: Midroni, TucksonDev +sme: Midroni, TucksonDev user_story: As a current Orbit chain owner, I need to learn how to set up an AEP fee router. content_type: how-to --- ## Quick start -- You can adopt the AEP Fee Router by using the [AEP Router deployment scripts](https://github.com/OffchainLabs/arbitrum-orbit-sdk/tree/main/examples/setup-aep-fee-router) provided in the [Orbit SDK](https://github.com/OffchainLabs/arbitrum-orbit-sdk/tree/main) +You can adopt the AEP Fee Router by using the [AEP Router deployment scripts](https://github.com/OffchainLabs/arbitrum-orbit-sdk/tree/main/examples/setup-aep-fee-router) provided in the [Orbit SDK](https://github.com/OffchainLabs/arbitrum-orbit-sdk/tree/main) -### Canonical Contracts +### Canonical contracts -| Network | Contract | Address | Configured For | -| ------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | -| Ethereum | `Parent2ChildRouter` | [https://etherscan.io/address/0x40Cd7D713D7ae463f95cE5d342Ea6E7F5cF7C999](https://etherscan.io/address/0x40Cd7D713D7ae463f95cE5d342Ea6E7F5cF7C999) | `ETH`, `ERC-20` | -| Arbitrum Nova | `Child2ParentRouter` | [https://nova.arbiscan.io/address/0x36D0170D92F66e8949eB276C3AC4FEA64f83704d](https://nova.arbiscan.io/address/0x36D0170D92F66e8949eB276C3AC4FEA64f83704d) | `ETH` | +| Network | Contract | Address | Configured for | +| ------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | --------------- | +| Ethereum | `Arbitrum Foundation's multisig wallet` | [0x1Afa41C006dA1605846271E7bdae942F2787f941](https://etherscan.io/address/0x1Afa41C006dA1605846271E7bdae942F2787f941) | `ETH`, `ERC-20` | +| Arbitrum Nova | `Child2ParentRouter` | [0xd27cb0fe2a696ebaa80d606ce0edf55aabaeab84](https://nova.arbiscan.io/address/0xd27cb0fe2a696ebaa80d606ce0edf55aabaeab84) | `ETH` | +| Base | `Child2ParentRouter` | [0xd9a2e0e5d7509f0bf1b2d33884f8c1b4d4490879](https://basescan.org/address/0xd9a2e0e5d7509f0bf1b2d33884f8c1b4d4490879) | `ETH` | ## The AEP fee router contract system -_Link to the [Router contracts' source code](https://github.com/OffchainLabs/fund-distribution-contracts/tree/main/src/FeeRouter)._ +This section describes the different fee distribution and router contracts that are available. You can find their source code [here](https://github.com/OffchainLabs/fund-distribution-contracts/tree/main/src/FeeRouter). ### RewardDistributor The **AEP fee router** system relies on configuring an escrow contract as the intended reward address for protocol fee components. This intermediary contract is known as the `RewardDistributor.` -The `RewardDistributor` is configured to separate the AEP portion of the fees from fees intended for the chain owner. The `RewardDistributor` can be permissionlessly called to perform a withdrawal which simultaneously transfers 90% of accrued fees to the chain’s fee collector and 10% of accrued fees to a routing contract on the parent chain. From here, the chain owner has complete control over their earned fees, and the routing contracts can direct AEP fees to a collecting address for the Arbitrum DAO. +The `RewardDistributor` is configured to separate the AEP portion of the fees from fees intended for the chain owner. The `RewardDistributor` can be permissionlessly called to perform a withdrawal which simultaneously transfers 90% of accrued fees to the chain’s fee collector and 10% of accrued fees to a target address on the parent chain. From here, the chain owner has complete control over their earned fees, and the routing contracts can direct AEP fees to a collecting address for the Arbitrum DAO. ### ChildToParentRouter AEP fees from the `RewardDistributor` must first be sent to Ethereum before they can be deposited to the DAO-controlled address on Arbitrum One. To facilitate this transfer to Ethereum, AEP fees are sent through a series of contracts known as `ChildToParentRouters.` -The `ChildToParentRouter` is configured to withdraw a single token (immutable and specified at deployment) from the child chain to a specific target address on the parent chain: either another `ChildToParentRouter` or the `ParentToChildRouter` on Ethereum. - -### ParentToChildRouter - -All AEP fees from the network of Orbit chains will arrive at the `ParentToChildRouter` on Ethereum. This contract can send ETH and arbitrary ERC-20 tokens to a DAO-controlled address on Arbitrum One. +The `ChildToParentRouter` is configured to withdraw a single token (immutable and specified at deployment) from the child chain to a specific target address on the parent chain: either another `ChildToParentRouter` or an address controlled by the Arbitrum Foundation on Ethereum. ## Deploying your AEP fee router contracts -An Orbit chain is responsible for deploying all `ChildToParentRouters` necessary for their AEP funds to arrive at the `ParentToChildRouter` on Ethereum. +An Orbit chain is responsible for deploying all `ChildToParentRouters` necessary for their AEP funds to arrive at the address controlled by the Arbitrum Foundation on Ethereum. This includes: - Deploying a `ChildToParentRouter` on their Orbit chain configured for their gas token and configured to send funds to either: - - The `ParentToChildRouter` on Ethereum (assuming the network is a Layer-2) + - An address controlled by the Arbitrum Foundation on Ethereum (assuming the network is a Layer-2) - Another `ChildToParentRouter` configured to the same gas token and configured to send funds to a successive parent chain (this is the case for a Layer-3 network or higher) - Deploying a `RewardDistributor` contract configured to forward 10% of fees to the `ChildToParentRouter` and 90% to the chain owner’s preferred reward-receiving address. -In the event that a `ChildToParentRouter` does not connect to the `ParentToChildRouter` on Ethereum, an Orbit chain must deploy successive `ChildToParentRouter` contracts until a connection to `ParentToChildRouter` is established. +In the event that a `ChildToParentRouter` does not connect to the address controlled by the Arbitrum Foundation on Ethereum, an Orbit chain must deploy successive `ChildToParentRouter` contracts until a connection to such address is established. Additional `ChildToParentRouter` contracts configured to route ETH have been deployed in certain networks and can be leveraged by chains created on top of these networks. You can see which networks have a router deployed [here](#canonical-contracts). -And optionally, an Orbit chain can decide to deduct assertion costs by following the instructions in the [Deducting Assertion Costs](/launch-orbit-chain/how-tos/calculate-aep-fees#assertion-costs) section: +Optionally, an Orbit chain can decide to deduct assertion costs by following the instructions in the [Deducting Assertion Costs](/launch-orbit-chain/how-tos/calculate-aep-fees#assertion-costs) section:
Arbitrum-native USDCUSDC Bridged USDC
Token NameUSD CoinUSDC Bridged USDC