This AIP proposes the activation of ArbOS 31 on Arbitrum One and Arbitrum Nova. This ArbOS upgrade brings a number of improvements, including:
This AIP combines the following three temperature checks:
A new ArbOS 31 “Bianca” was released between the time of the temperature check votes and submitting this proposal. ArbOS 31 release builds upon ArbOS 30 and includes new optimizations that were discovered during rigorous testing and feedback from Stylus teams. The ArbOS upgrade is shipped as a new Nitro node release alongside new upgrades to the rollup contracts for Arbitrum One and Arbitrum Nova.
Note: ArbOS 31 “Bianca” will be the canonical ArbOS version for the “Bianca” family of releases.
Since the DAO has already signaled support for the adoption of all three changes in all three temperature checks, this proposal will proceed to an on-chain AIP on Tally next.
Stylus is an upgrade to the node software that powers all Arbitrum chains. This upgrade introduces a new WASM-based Virtual Machine (VM) that runs alongside the EVM. This enables developers to write smart contracts in new programming languages, like Rust, that are more efficient than Solidity smart contracts.
Stylus is a first-of-its-kind technology resulting from breakthrough engineering efforts in the Arbitrum ecosystem. Unlike other alternative VMs, the Stylus VM is not a replacement for the EVM & is instead purely additive to the EVM. This means that Stylus contracts and EVM contracts are fully interoperable. The two VMs work together to facilitate state transitions, each playing their part in executing their respective bytecode. Support for more memory efficient and safer languages will unlock a new generation of applications that were previously impossible to build on the EVM.
The Stylus VM and fraud prover were originally developed as a fork of the Nitro codebase before. The Stylus codebase has since been audited (Trail of Bits audit report 1) and merged back into the Nitro codebase:
Stylus contracts can be written using the Stylus SDK, which employs Solidity-equivalent ABIs and storage patterns to ensure cross-language interoperability. For example, existing Solidity DEXs can list Rust tokens without modification. New SDKs for additional programming languages can be added over time. Current SDK repositories:
If you would like to better understand the lifecycle of a Stylus contract, head over to A Gentle Introduction: Stylus 1. For teams who are curious to learn more about how Stylus is expected to interact with their project’s existing infrastructure, we encourage folks to check out this Stylus launch ecosystem one-pager.
Note: Support for Stylus contract verification is currently under development by major block explorers. We expect that contract verification will be fully supported before ArbOS 31 Bianca gets activated on Arbitrum One and Arbitrum Nova, pending the DAO’s decision to adopt this proposal.
Passkeys offer a solution that removes the need for a web3 user to personally store a private key for their wallet. Passkeys accomplish this by leveraging WebAuthn, a global standard for passwordless authentication used by Google, Facebook, Microsoft, and all major web browsers. The private key generated when creating a passkey can be encrypted and can only be decrypted using a specialized hardware module called the Secure Enclave. The Secure Enclave ensures a user’s private key can never leave the device, transforming any compatible device into a hardware wallet. Users can authorize transactions with biometric features like Touch ID or Face ID when using passkey-based wallets for key management. These qualities add flexibility and significantly improve UX while maintaining high security.
Adding support for RIP-7212 1 decreases the costs of verifying the secp256r1 curve on-chain by 99% when compared to current implementations, making them more feasible for everyday use and enabling dApp developers and protocols to offer their users improved UX on Arbitrum One and Arbitrum Nova. Without a precompile, verifying this signature on-chain is extremely expensive. Passkey-based wallets offer a better level of security than a typical EOA and seamless cross-device support. Many wallets, and notably, apps using embedded wallets, have been requesting this feature for over a year.
The specifications of RIP-7212 1, including test cases, can be found in the RIP repository 1. If approved, Arbitrum One and Arbitrum Nova will use this specification as the reference for implementation. The Ethereum Magicians Forum discusses design decisions, iterations, and the transformation of the proposal from an EIP (Ethereum Improvement Proposal) to a RIP.
This pre-compile is part of Nitro 3.1.0 and was added to our fork of Go Ethereum in Add Precompile for secp256r1 conditionally based on ArbOS version by anodar · Pull Request #303 · OffchainLabs/go-ethereum · GitHub and has been upstreamed into Nitro 3.1.0. Nitro 3.1.0 is the minimum supported version of Nitro for ArbOS 31 “Bianca”.
Today, the ArbitrumDAO’s portion of the transaction fees from Arbitrum Nova are sent to the Core Governance L1 Timelock address, which is accessible via the core governance system. This setup is disadvantageous because any time the ArbitrumDAO wishes to spend/move the funds, a roundtrip, constitutional proposal must be passed before the DAO.
This proposal updates the setup such that all Arbitrum Nova transaction fees, that are currently sent to the Core Governance L1 Timelock Address, are instead sent to a system of “fee routers” that automatically send all funds to the ArbitrumDAO treasury. Benefits of this new setup include:
This new, proposed system of “fee routers” results in a fee collection lifecycle as follows:
distributeRewards
function call is made on the RewardDistributor
contract, sending funds to a ChildtoParentRouter
contractrouteFunds
, the ChildToParentRouter
creates an L2-to-L1 message which sends the contract’s full Ether balance.ParentToChildRouter
contract on L1.routeFunds
is called on ParentToChildRouter
, creating a retryable ticket which transfers its full Ether balance to the DAO Treasury on Arbitrum One.Note that the addresses deployed during the Snapshot vote 2 for the ParentToChildRewardRouter
and ChildToParentRewardRouter
have been re-deployed at [0x40Cd7D713D7ae463f95cE5d342Ea6E7F5cF7C999](https://nova.arbiscan.io/address/0x40Cd7D713D7ae463f95cE5d342Ea6E7F5cF7C999)
and [0x36D0170D92F66e8949eB276C3AC4FEA64f83704d](https://nova.arbiscan.io/address/0x36D0170D92F66e8949eB276C3AC4FEA64f83704d)
, respectively.
All of the above changes were independently audited. The list below contains all relevant audit reports:
The canonical version of ArbOS 31 “Bianca” this proposal aims to adopt is implemented in the Arbitrum Nitro git commit hash 7d1d84c75db7fd26d27d24ffb75f8b1c93d4f980 and can be viewed in: Merge pull request #2485 from OffchainLabs/fix-disable-p2p · OffchainLabs/nitro@7d1d84c · GitHub.
The current full code diff can be viewed via this link: Comparing consensus-v20...consensus-v31 · OffchainLabs/nitro · GitHub 2.
ArbOS 31 “Bianca” will be shipped as part of a future release of Nitro. Node operators may see a small increase in latency for Stylus eth_call
queries, if ArbOS 31 is approved for activation on mainnet by the ArbitrumDAO.
The Action smart contracts used to execute the on-chain upgrade can be viewed in Arbos 31 actions by godzillaba · Pull Request #296 · ArbitrumFoundation/governance · GitHub.
Action contract deployments for ArbOS 31 and Stylus:
$ cast storage 0x51dEDBD2f190E0696AFbEE5E60bFdE96d86464ec 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 --rpc-url=https://arb1.arbitrum.io/rpc
0x000000000000000000000000db216562328215e010f819b5abe947bad4ca961e (Arb One Proxy Admin)
$ cast storage 0x20586F83bF11a7cee0A550C53B9DC9A5887de1b7 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 --rpc-url=https://nova.arbitrum.io/rpc
0x000000000000000000000000f58ea15b20983116c21b05c876cc8e6cdae5c2b9 (Nova Proxy Admin)
Action contracts, deployments, and Fee Router contracts for the Fee Router AIP:
The Fee Router contracts can be found here: fund-distribution-contracts/src/FeeRouter at v1.0.1 · OffchainLabs/fund-distribution-contracts · GitHub
Nova ArbChildToParentRewardRouter: ArbChildToParentRewardRouter | Address 0x36D0170D92F66e8949eB276C3AC4FEA64f83704d | Arbiscan
The current ArbOS version used on Arbitrum One and Arbitrum Nova is ArbOS 20, corresponding to the Arbitrum Nitro consensus-v20 git tag.
You can verify this by running the previously mentioned steps to build the WASM module root on that git tag, which produces the WASM module root 0x8b104a2e80ac6165dc58b9048de12f301d70b02a0ab51396c22b4b4b802a16a4, which is what the rollup contract’s wasmModuleRoot() method returns for both Arbitrum One and Arbitrum Nova.
To audit the code difference from ArbOS 20 to ArbOS 31, you could simply generate a full nitro diff with git diff consensus-v20 consensus-v31 (and also generate a diff of the go-ethereum submodule mentioned in that nitro diff). However, that includes a lot of code that isn’t part of the WASM module root. To filter down to just the replay binary which defines the state transition function, you can start by generating a list of files in the nitro and go-ethereum repositories included by the replay binary in either ArbOS 20 or ArbOS 31 with bash:
# !/usr/bin/env bash
set -e
mkdir -p ~/tmp
# This script uses ~/tmp as scratch space and output
# This script should be run in the nitro repository:
# Checkout and update submodules for consensus-v31
git checkout consensus-v31
git submodule update --init --recursive
make .make/solgen
# List dependencies for replay command, filter nitro dependencies, and save to file
go list -f "{{.Deps}}" ./cmd/replay | tr -d '[]' | sed 's/ /\\n/g' | grep 'github.com/offchainlabs/nitro/' | sed 's@github.com/offchainlabs/nitro/@@' | while read dir; do
find "$dir" -type f -name '*.go' -maxdepth 1
done | grep -v '_test\\.go$' > ~/tmp/consensus-v31-nitro-files.txt
# List dependencies for replay command, filter geth dependencies, and save to file
go list -f "{{.Deps}}" ./cmd/replay | tr -d '[]' | sed 's/ /\\n/g' | grep 'github.com/ethereum/go-ethereum/' | sed 's@github.com/ethereum/go-ethereum/@go-ethereum/@' | while read dir; do
find "$dir" -type f -name '*.go' -maxdepth 1
done | grep -v '_test\\.go$' > ~/tmp/consensus-v31-geth-files.txt
# Checkout and update submodules for consensus-v20
git checkout consensus-v20
git submodule update --init --recursive
make .make/solgen
# List dependencies for replay command, filter nitro dependencies, and save to file
go list -f "{{.Deps}}" ./cmd/replay | tr -d '[]' | sed 's/ /\\n/g' | grep 'github.com/offchainlabs/nitro/' | sed 's@github.com/offchainlabs/nitro/@@' | while read dir; do
find "$dir" -type f -name '*.go' -maxdepth 1
done | grep -v '_test\\.go$' > ~/tmp/consensus-v20-nitro-files.txt
# List dependencies for replay command, filter geth dependencies, and save to file
go list -f "{{.Deps}}" ./cmd/replay | tr -d '[]' | sed 's/ /\\n/g' | grep 'github.com/ethereum/go-ethereum/' | sed 's@github.com/ethereum/go-ethereum/@go-ethereum/@' | while read dir; do
find "$dir" -type f -name '*.go' -maxdepth 1
done | grep -v '_test\\.go$' > ~/tmp/consensus-v20-geth-files.txt
# Combine and sort nitro dependencies
sort -u ~/tmp/consensus-v20-nitro-files.txt ~/tmp/consensus-v31-nitro-files.txt > ~/tmp/replay-binary-nitro-dependencies.txt
# Combine, sort, and filter geth dependencies
sort -u ~/tmp/consensus-v20-geth-files.txt ~/tmp/consensus-v31-geth-files.txt | sed 's@^[./]*go-ethereum/@@' > ~/tmp/replay-binary-geth-dependencies.txt
Now, ~/tmp/replay-binary-dependencies.txt contains a list of dependencies of the replay binary that were present in ArbOS 20 or ArbOS 31. To use that to generate a smaller diff of the nitro repository, you can run:
git diff consensus-v20 consensus-v31 -- cmd/replay $(cat ~/tmp/replay-binary-nitro-dependencies.txt)
The fraud prover is not part of the on-chain upgrade, but may be helpful in understanding the fraud proving smart contract changes and other components:
git diff consensus-20 consensus-v31 -- arbitrator/prover arbitrator/wasm-libraries/ arbitrator/arbutil ':!**/Cargo.lock' ':!**/kzg-trusted-setup.json'
For the go-ethereum submodule, you can first find out what go-ethereum commit ArbOS 20 and 31 used:
$ git ls-tree consensus-v20 go-ethereum
160000 commit abe584818e104dd5b4fdb8f60381a14eede896de go-ethereum
$ git ls-tree consensus-v31 go-ethereum
160000 commit 5a89d012232039ab57e28f9628c8e50b9093edc7 go-ethereum
Those commit hashes are the go-ethereum commit hashes pinned by each Nitro commit. Then, you can again use git diff and the files generated by the earlier script to generate a diff limited to code used by the replay binary:
# this should be run inside the go-ethereum submodule folder
git diff abe584818e104dd5b4fdb8f60381a14eede896de 5a89d012232039ab57e28f9628c8e50b9093edc7 -- $(cat ~/tmp/replay-binary-geth-dependencies.txt)
This diff also includes the diff between upstream go-ethereum versions v1.13.3 and v1.13.11, as ArbOS 20 used the former and ArbOS 31 uses the latter.
To filter out that difference, you can use this tool to find the intersection of two git diffs:
Git diff intersection finder
We can use that to find the intersection of the diff of ArbOS 31’s go-ethereum against ArbOS 20’s go-ethereum and the diff of ArbOS 31’s go-etheruem against upstream go-ethereum v1.13.11:
# This should be run inside the go-ethereum submodule folder
# Generate diff between two specific commits and save to file
git diff abe584818e104dd5b4fdb8f60381a14eede896de 5a89d012232039ab57e28f9628c8e50b9093edc7 -- $(cat ~/tmp/replay-binary-geth-dependencies.txt) > ~/tmp/arbos-20-vs-31-geth.diff
# Generate diff between upstream geth and nitro geth, and save to file
git diff v1.13.11 5a89d012232039ab57e28f9628c8e50b9093edc7 -- $(cat ~/tmp/replay-binary-geth-dependencies.txt) > ~/tmp/arbos-31-vs-upstream-geth.diff
# Run the diff-intersection script with the specified diff files and ignored files
diff-intersection.py ~/tmp/arbos-20-vs-31-geth.diff ~/tmp/arbos-31-vs-upstream-geth.diff --ignore-files 'core/blockchain*.go' arbitrum_types/txoptions.go 'rawdb/**' 'rpc/**'
The above command ignores files that are included by the replay binary but whose components are not used with these arguments:
--ignore-files 'core/blockchain*.go' arbitrum_types/txoptions.go 'rawdb/**' 'rpc/**'.
To also review those diffs, you can remove those arguments.
Note that by default, diff-intersection.py does a line based intersection. To instead do an intersection based on chunks in the diff, known as hunks in git terminology, you can add the --only-hunks
flag.