A gentle introduction
ArbOS is the child chain EVM hypervisor that provides the execution environment for the Arbitrum chain. Acting as a trusted "system glue" component within the STF, ArbOS is responsible for:
1. Managing network resources
It allocates and tracks resources necessary for executing transactions on the child chain.
2. Block production
ArbOS processes incoming sequencer data batches to produce child chain blocks, ensuring the state is updated correctly.
3. Cross-chain messaging
It facilitates communication between the parent and child chains, supporting functionalities like Ether and token deposits and withdrawals.
4. Enhanced EVM execution
ArbOS operates its instrumented instance of Geth to execute smart contracts, incorporating additional logic specific to the child chain environment.
5. Stylus-specific tasks in ArbOS
ArbOS manages host I/O calls, memory operations, and execution context for Stylus transactions, ensuring efficient and deterministic processing with the WASM runtime.
By offloading tasks that would execute at a high cost on the parent chain, ArbOS enables these operations to be performed quickly and cost-effectively on the child chain. This design reduces computational and storage costs and offers significant flexibility, allowing the child chain code to evolve or be customized more easily than a parent chain-enforced architecture.
While Ethereum's STF forms the basis for secure and deterministic state updates, Arbitrum's Nitro stack builds on this foundation with key modifications–ranging from dual gas accounting to cross-chain messaging–to optimize performance and flexibility. These innovations are realized through minimal yet strategic modifications to Geth, integrated seamlessly with ArbOS, forming the "geth sandwich."
With the introduction of Stylus, Arbitrum extends its execution model beyond the EVM, enabling high-performance WASM-based smart contracts. This integration introduces additional modifications to Geth, ensuring compatibility with Stylus transactions while preserving Ethereum-like execution guarantees. These changes include handling Stylus-specific transaction types and ensuring smooth interaction between the EVM and WASM environments.
In the following section, we'll dive deep into these modifications, exploring how Nitro leverages 'Geth at the core' and the custom enhancements provided by ArbOS to deliver an advanced, high-performance STF. Stylus-specific tasks within ArbOS are covered separately to highlight its role in managing execution, host I/O, and memory operations.
How precompiles work
A precompile consists of a Solidity interface in contracts/src/precompiles/ and a corresponding Golang implementation in precompiles/. Using Geth's ABI generator, solgen/gen.go generates solgen/go/precompilesgen/precompilesgen.go, which collects the ABI data of the precompiles. The runtime installer uses this generated file to check the type safety of each precompile's implementer.
The installer uses runtime reflection to ensure each implementer has all the right methods and signatures. This reflection 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 and debugOnly to their installation entry.
Completion of calling, dispatching, and recording of precompile methods occurs via runtime reflection, which avoids any human error manually parsing and writing bytes could introduce, and uses Geth's stable APIs for packing and unpacking values.
Each time a transaction calls a method of a child chain-specific precompile, a call context gets created to track and record the gas burnt. For convenience, it also provides access to the public fields of the underlying TxProcessor. Because sub-transactions could revert without updates to this struct, the TxProcessor only makes public what is safe, such as the amount of parent chain calldata paid by the top-level transaction.
For a complete list of precompiles refer to the precompile references.