-
Notifications
You must be signed in to change notification settings - Fork 324
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update section Differences with Ethereum
- Loading branch information
1 parent
83da993
commit d5d8f8a
Showing
13 changed files
with
342 additions
and
225 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
...-devs/concepts/differences-between-arbitrum-ethereum/block-numbers-and-time.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
--- | ||
title: 'Block numbers and time' | ||
sidebar_label: Block numbers and time | ||
sidebar_position: 2 | ||
description: This concept page provides information about the differences between Arbitrum and Ethereum in terms of block numbers and timing, so developers can easily understand what to expect when deploying to Arbitrum | ||
target_audience: developers who want to build on Arbitrum | ||
content-type: concept | ||
--- | ||
|
||
As in Ethereum, Arbitrum clients submit transactions, and the system executes those transactions at some later time. In Arbitrum, clients submit transactions by posting messages to the Ethereum chain, either [through the sequencer](/sequencer.mdx#happycommon-case-sequencer-is-live-and-well-behaved) or via the chain's [delayed inbox](/sequencer.mdx#unhappyuncommon-case-sequencer-isnt-doing-its-job). | ||
|
||
Once in the chain's core inbox contract, transactions are processed in order. Generally, some time will elapse between the time when a message is put into the inbox (and timestamped) and the time when the contract processes the message and carries out the transaction requested by the message. | ||
|
||
In this page we describe what does this mechanism mean for the block numbers and the time assumptions of the transactions submitted to Arbitrum. | ||
|
||
## Block numbers: Arbitrum vs. Ethereum | ||
|
||
Arbitrum blocks are assigned their own L2 block numbers, distinct from Ethereum's block numbers. | ||
|
||
A single Ethereum block could include multiple Arbitrum blocks within it; however, an Arbitrum block cannot span across multiple Ethereum blocks. Thus, any given Arbitrum transaction is associated with exactly one Ethereum block and one Arbitrum block. | ||
|
||
### Ethereum block numbers within Arbitrum | ||
|
||
Accessing block numbers within an Arbitrum smart contract (i.e., `block.number` in Solidity) will return a value _close to_ (but not necessarily exactly) the L1 block number at which the sequencer received the transaction. | ||
|
||
```sol | ||
// some Arbitrum contract: | ||
block.number // => returns L1 block number ("ish") | ||
``` | ||
|
||
As a general rule, any timing assumptions a contract makes about block numbers and timestamps should be considered generally reliable in the longer term (i.e., on the order of at least several hours) but unreliable in the shorter term (minutes). (It so happens these are generally the same assumptions one should operate under when using block numbers directly on Ethereum!) | ||
|
||
### Arbitrum block numbers | ||
|
||
Arbitrum blocks have their own block numbers, starting at 0 at the Arbitrum genesis block and updating sequentially. | ||
|
||
ArbOS and the sequencer are responsible for delineating when one Arbitrum block ends and the next one begins. However, block creation depends entirely on chain usage, meaning that blocks are only produced when there are transactions to sequence. In active chains, one can expect to see Arbitrum blocks produced at a relatively steady rate. In more quiet chains, block production might be sporadic depending on the rate at which transactions are received. | ||
|
||
A client that queries an Arbitrum node's RPC interface (for, e.g., transaction receipts) will receive the transaction's Arbitrum block number as the standard block number field. The L1 block number will also be included in the added `l1BlockNumber field`. | ||
|
||
```ts | ||
const txnReceipt = await arbitrumProvider.getTransactionReceipt('0x...'); | ||
/** | ||
txnReceipt.blockNumber => Arbitrum block number | ||
txnReceipt.l1BlockNumber => L1 block number ("ish") | ||
*/ | ||
``` | ||
|
||
The Arbitrum block number can also be retrieved within an Arbitrum contract via [ArbSys](/for-devs/dev-tools-and-resources/precompiles.mdx#arbsys) precompile: | ||
|
||
```sol | ||
ArbSys(100).arbBlockNumber() // returns Arbitrum block number | ||
``` | ||
|
||
### Example | ||
|
||
| Wall Clock time | 12:00 am | 12:00:15 am | 12:00:30 am | 12:00:45 am | 12:01 am | 12:01:15 am | | ||
| -------------------------------------- | -------- | ----------- | ----------- | ----------- | -------- | ----------- | | ||
| L1 `block.number` | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | | ||
| L2 `block.number` \* | 1000 | 1000 | 1000 | 1000 | 1004 | 1004 | | ||
| Arbitrum Block number (from RPCs) \*\* | 370000 | 370005 | 370006 | 370008 | 370012 | 370015 | | ||
|
||
_\* **L2 `block.number`:** updated to sync with L1 `block.number` approximately every minute. Thus, over time, it will, like the L1 `block.number`, average to ~15 seconds per block._ | ||
|
||
_\*\* **Arbitrum block number from RPCs:** note that this can be updated multiple times per L1 block (this lets the sequencer give sub-L1-block-time transaction receipts.)_ | ||
|
||
### Case study: the Multicall contract | ||
|
||
The Multicall contract offers a great case study for the differences between L1 and L2 block numbers. | ||
|
||
The [canonical implementation](https://github.com/makerdao/multicall/) of Multicall returns the value of `block.number`. If attempting to use out-of-the-box, some applications might face unintended behaviour. | ||
|
||
You can find a deployed version of the adapted Multicall2 at [0x7eCfBaa8742fDf5756DAC92fbc8b90a19b8815bF](https://arbiscan.io/address/0x7eCfBaa8742fDf5756DAC92fbc8b90a19b8815bF#code). | ||
|
||
By default the `getBlockNumber`, `tryBlockAndAggregate`, and `aggregate` functions return the L2 block number. This allows you to use this value to compare your state against the tip of the chain. | ||
|
||
The `getL1BlockNumber` function can be queried if applications need to surface the L1 block number. | ||
|
||
## Block timestamps: Arbitrum vs. Ethereum | ||
|
||
Block timestamps on Arbitrum are not linked to the timestamp of the L1 block. They are updated every L2 block based on the sequencer's clock. These timestamps must follow these two rules: | ||
|
||
1. Must be always equal or greater than the previous L2 block timestamp | ||
2. Must fall within the established boundaries (24 hours earlier than the current time or 1 hour in the future). More on this below. | ||
|
||
FUrthermore, for transactions that are force-included from L1 (bypassing the sequencer), the block timestamp will be equal to either the L1 timestamp when the transaction was put in the delayed inbox on L1 (not when it was force-included), or the L2 timestamp of the previous L2 block, whichever is greater of the two timestamps. | ||
|
||
### Timestamp boundaries of the sequencer | ||
|
||
As mentioned, block timestamps are usually set based on the sequencer's clock. Because there's a possibility that the sequencer fails to post batches on the parent chain (for example, Ethereum) for a period of time, it should have the ability to slightly adjust the timestamp of the block to account for those delays and prevent any potential reorganisations of the chain. To limit the degree to which the sequencer can adjust timestamps, some boundaries are set, currently to 24 hours earlier than the current time, and 1 hour in the future. |
44 changes: 44 additions & 0 deletions
44
arbitrum-docs/for-devs/concepts/differences-between-arbitrum-ethereum/overview.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
--- | ||
title: 'Differences between Arbitrum and Ethereum: Overview' | ||
sidebar_label: Overview | ||
sidebar_position: 1 | ||
description: This concept page provides information about the differences between Arbitrum and Ethereum so developers can easily understand what to expect when deploying to Arbitrum | ||
author: jose-franco | ||
sme: jose-franco | ||
target_audience: developers who want to build on Arbitrum | ||
content-type: concept | ||
--- | ||
|
||
Arbitrum is designed to be as compatible and consistent with Ethereum as possible, from its high-level RPCs to its low-level bytecode and everything in between. Decentralized app (dApp) developers with experience building on Ethereum will likely find that little-to-no new specific knowledge is required to build on Arbitrum. | ||
|
||
This section describes the differences, perks, and gotchas that devs are advised to be aware of when working with Arbitrum. This first page serves as an overview of where you might these differences, with links to the relevant pages when needed. | ||
|
||
## Block numbers and time | ||
|
||
Time in L2s is tricky. The timing assumptions one is used to making about Ethereum blocks don't exactly carry over into the timing of Arbitrum blocks. See [Block numbers and time](/for-devs/concepts/differences-between-arbitrum-ethereum/block-numbers-and-time.mdx) for details about how block numbers and time are handled in Arbitrum. | ||
|
||
## RPC methods | ||
|
||
Although the majority of RPC methods follow the same behavior than in Ethereum, some methods might produce a different result, or add more information, when used on an Arbitrum chain. You can find more information about these differences in [RPC methods](/for-devs/concepts/differences-between-arbitrum-ethereum/rpc-methods.mdx). | ||
|
||
## Solidity support | ||
|
||
You can deploy Solidity contracts onto Arbitrum just like you do Ethereum. There are only a few minor differences in behavior. Find more information about it in [Solidity support](/for-devs/concepts/differences-between-arbitrum-ethereum/solidity-support.mdx). | ||
|
||
## Fees | ||
|
||
The fees an Arbitrum transaction pays essentially work identically to gas fees on Ethereum. Arbitrum transactions must also, however, pay a fee component to cover the cost of posting their calldata to the parent chain (for example, calldata on Arbitrum One, an L2, is posted to Ethereum, an L1). Find more information about the two components of gas fees in [Gas and fees](/arbos/gas.mdx) and [L1 pricing](/arbos/l1-pricing.mdx). | ||
|
||
## Cross-chain messaging | ||
|
||
Arbitrum chains support arbitrary message passing from a parent chain (for example, a Layer 1 (L1) like Ethereum) to a child chain (for example, a Layer 2 (L2) like Arbitrum One or Arbitrum Nova). These are commonly known as "L1 to L2 messages". Developers using this functionality should familiarize themselves with how they work. Find more information about it in [L1 to L2 messaging](/arbos/l1-to-l2-messaging.mdx). | ||
|
||
Similarly, Arbitrum chains can also send messages to the parent chain, although these follow more strict rules. Find more information about them in [L2 to L1 messaging and the outbox](/arbos/l2-to-l1-messaging.mdx). | ||
|
||
## Precompiles | ||
|
||
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. You can find a full reference of them in [Precompiles](/for-devs/concepts/precompiles.mdx). | ||
|
||
## NodeInterface | ||
|
||
Arbitrum Nitro software includes a special `NodeInterface` contract available at address `0xc8` that only exists in the RPC (it's not deployed on-chain). Find more information about this interface in [NodeInterface.sol](/arbos/gas.mdx#nodeinterfacesol). |
Oops, something went wrong.