Setup & Configuration (Stylus-first Shims)
This document describes installation and configuration for the Stylus-first precompile shims used in this integration. Scope is limited to shim mode, reseeding from a Stylus RPC, and validation via Hardhat scripts.
Prerequisites
- Node.js: v22 LTS recommended.
- Hardhat: project includes
@nomicfoundation/hardhat-ethers(ethers v6).
Installation
Before configuring the plugin, you must first install it as a development dependency in your Hardhat project:
npm install --save-dev @dappsoverapps.com/hardhat-patch
-
Repository layout (relevant parts):
TEXTsrc/hardhat-patch/ index.ts arbitrum-patch.ts native-precompiles.ts shims/ ArbSysShim.json ArbGasInfoShim.json tasks/ arb-install-shims.ts arb-reseed-shims.ts arb-gas-info.ts probes/hardhat/ hardhat.config.js precompiles.config.json (optional) contracts/ ArbSysShim.sol ArbGasInfoShim.sol scripts/ predeploy-precompiles.js (preinstall bytecode at 0x…64/0x…6c) install-and-check-shims.js (one-shot install + verify) check-gasinfo-local.js (read getPricesInWei()) validate-precompiles.js (end-to-end probe)
Options (Hardhat arbitrum block)
| Key | Type | Default | Notes |
|---|---|---|---|
enabled | boolean | true | Turns the patch on/off. |
runtime | "stylus" | "nitro" | "stylus" | Stylus-first target. |
precompiles.mode | "shim" | "auto" | "native" | "auto" | integration uses shim path; auto gracefully installs shims. |
stylusRpc | string | (unset) | Remote RPC used by tasks when --stylus is selected. Can also be set via STYLUS_RPC. |
gas.pricesInWei | string[6] | (unset) | Shim order: [ perL2Tx, perL1CalldataFee, perStorageAllocation, perArbGasBase, perArbGasCongestion, perArbGasTotal ]. Used when no RPC/ cache is chosen. |
arbSysChainId | number | 42161 | Returned by ArbSysShim at slot 0. |
costing.enabled | boolean | false | If implemented, returns a small, stable non-zero gasUsed for precompile calls in shim mode (off by default). |
Configuration
hardhat.config.js (Stylus-first defaults)
require("@nomicfoundation/hardhat-ethers");
require("@dappsoverapps.com/hardhat-patch"); // plugin entry; auto-loads tasks
module.exports = {
solidity: "0.8.19",
networks: {
hardhat: { chainId: 42161 },
// optional persistent node:
// localhost: { url: "http://127.0.0.1:8549", chainId: 42161 }
},
arbitrum: {
enabled: true,
runtime: "stylus", // Stylus-first
precompiles: { mode: "auto" }, // tries native later; shims today
// stylusRpc: "https://sepolia-rollup.arbitrum.io/rpc", // optional default
},
};
runtime: "stylus"sets Stylus as the default runtime flavor.precompiles.mode: "auto"enables lazy shim installation in this integration (native hooks can be introduced in a later phase).
precompiles.config.json (optional)
{
"arbSysChainId": 42161,
"runtime": "stylus",
"gas": {
"pricesInWei": ["69440", "496", "2000000000000", "100000000", "0", "100000000"]
},
"stylusRpc": "https://sepolia-rollup.arbitrum.io/rpc"
}
-
gas.pricesInWeiis a 6-tuple in shim order:TEXT[ perL2Tx, perL1CalldataFee, perStorageAllocation, perArbGasBase, perArbGasCongestion, perArbGasTotal ] -
When both
stylusRpcandgas.pricesInWeiare present, reseeding prioritizes RPC (§3.4).
2.3 Environment variables (optional)
STYLUS_RPC— RPC endpoint for Stylus (for example,https://sepolia-rollup.arbitrum.io/rpc).ARB_PRECOMPILES_CONFIG— path override to a non-defaultprecompiles.config.json.
Stability toggles (often helpful on WSL/docker):
NODE_OPTIONS=--dns-result-order=ipv4firstNODE_NO_HTTP2=1
Example:
export NODE_OPTIONS=--dns-result-order=ipv4first
export NODE_NO_HTTP2=1
export STYLUS_RPC=https://sepolia-rollup.arbitrum.io/rpc
Shim installation & reseeding
Two flows are supported: ephemeral (in-process Hardhat VM) and persistent (a running Hardhat node on a port, e.g., 8549). Both install shims at the canonical addresses:
- ArbSys —
0x0000000000000000000000000000000000000064 - ArbGasInfo —
0x000000000000000000000000000000000000006c
Ephemeral Hardhat (fastest loop)
This mode spins up a fresh in-process Hardhat network per command.
# One-shot install + verify
npx hardhat --config hardhat.config.js run scripts/install-and-check-shims.js
Expected example:
Arbitrum Precompile Installer & Verifier
Target Address: 0x000000000000000000000000000000000000006c
[1/4] Compiling contracts... Nothing to compile
Done.
[2/4] Installing bytecode (4091 bytes)... Done.
[3/4] Seeding default configuration...
[4/4] Verifying State:
Parameter | Actual | Expected | Status
---------------------+-----------------+-----------------+-------
Wei: Per L2 Tx | 1843139200 | 1843139200 | OK
Wei: Per L1 Call | 13165280 | 13165280 | OK
Arb: Per L2 Tx | 91 | 91 | OK
Arb: Per Storage | 20000 | 20000 | OK
Tasks auto-loaded by the plugin can also be used:
npx hardhat --config hardhat.config.js arb:install-shims
Persistent Hardhat node (HTTP)
Start a node and point “localhost” at it:
# Start persistent node on 8549
npx hardhat node --port 8549
# …leave running
Optional environment setup:
export NODE_OPTIONS=--dns-result-order=ipv4first
export NODE_NO_HTTP2=1
export STYLUS_RPC=https://sepolia-rollup.arbitrum.io/rpc
Network entry for the persistent node:
networks: {
localhost: { url: "http://127.0.0.1:8549", chainId: 42161 },
}
Predeploy shim bytecode:
npx hardhat --config hardhat.config.js run --network localhost scripts/predeploy-precompiles.js
# Example:
# ArbSys code len: 582 ArbGasInfo code len: 1600
# ✅ Shims predeployed at 0x...64 and 0x...6c
Reseed from Stylus (preferred)
# Reseed using Stylus RPC (explicit flag)
npx hardhat --config hardhat.config.js arb:reseed-shims --network localhost --stylus
Examples:
Success
=== Arbitrum Shim Reseeder ===
[RPC] Fetched Wei Prices from Stylus.
[RPC] Fetched ArbGas Prices from Stylus.
> Processing updates...
[Success] Wei Prices Updated:
- Per L2 Tx : 88946706240
- Per L1 Call : 635333616
- Per Storage : 400000000000
- ArbGas Base : 20000000
- Congestion : 0
- Total : 20000000
[Success] ArbGas Prices Updated: [4446, 31, 20000]
[Success] Nitro Scalars Updated
[Success] Constraints Updated (6 items)
Temporary failure (fallback)
=== Arbitrum Shim Reseeder ===
[Config] Using JSON for Wei Prices.
[Config] Using JSON for ArbGas Prices.
> Processing updates...
[Success] Wei Prices Updated:
- Per L2 Tx : 69440
- Per L1 Call : 1
- Per Storage : 2000000000000
- ArbGas Base : 100000000
- Congestion : 0
- Total : 1
[Success] ArbGas Prices Updated: [91, 0, 20000]
[Success] Nitro Scalars Updated
[Success] Constraints Updated (1 items)
Source priority (reseeding)
- Stylus RPC (flag
--stylus, orstylusRpc/STYLUS_RPC) precompiles.config.json(gas.pricesInWeiin shim order)- Built-in fallback (safe defaults)
Supported flags:
--stylus— prioritize Stylus RPC--nitro— prioritize Nitro RPC (optional, for parity checks)- No flag — follow config/env; otherwise fall back to config/defaults
Validation scripts
Readback sanity check
npx hardhat --config hardhat.config.js run --network localhost scripts/check-gasinfo-local.js
# Example:
# [ '69440', '496', '2000000000000', '100000000', '0', '100000000' ]
Full validation (raw selectors + contract calls)
npx hardhat --config hardhat.config.js run --network localhost scripts/validate-precompiles.js
Expected example:
Validating Arbitrum Precompiles in Hardhat Context...
Arbitrum patch found in HRE
Found 2 precompile handlers:
ArbSys: 0x0000000000000000000000000000000000000064
ArbGasInfo: 0x000000000000000000000000000000000000006c
Testing ArbSys arbChainID...
ArbSys arbChainID returned: 42161
⛽ Testing ArbGasInfo getL1BaseFeeEstimate...
ArbGasInfo getL1BaseFeeEstimate returned: 1000000000 wei (1 gwei)
📄 Testing contract deployment and precompile calls...
ArbProbes contract deployed at: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
Contract ArbSys call returned: 42161
Contract ArbGasInfo call returned: 496
Precompile validation completed!
Note: in shim mode, getCurrentTxL1GasFees() returns the estimate (slot 1) for deterministic test results.
Operational notes
- Address immutability: shims are placed at canonical precompile addresses; this mirrors Arbitrum expectations in local testing.
- Determinism vs. realism: shim values can be fixed via config or sampled via RPC. For reproducible tests, the config tuple is recommended.
- RPC networking:
ipv4firstandNODE_NO_HTTP2=1often resolve transient TLS/HTTP2 issues on WSL/docker. - ChainId:
ArbSysShimreturnsarbSysChainId(from config) at slot 0; default resolves to 42161.
Quick reference (common commands)
Ephemeral, one-shot
npx hardhat --config hardhat.config.js run scripts/install-and-check-shims.js
# or
npx hardhat --config hardhat.config.js arb:install-shims
Persistent node (8549)
# Terminal A
npx hardhat node --port 8549
# Terminal B
npx hardhat --config hardhat.config.js run --network localhost scripts/predeploy-precompiles.js
STYLUS_RPC=https://sepolia-rollup.arbitrum.io/rpc \
npx hardhat --config hardhat.config.js arb:reseed-shims --network localhost --stylus
npx hardhat --config hardhat.config.js run --network localhost scripts/check-gasinfo-local.js
npx hardhat --config hardhat.config.js run --network localhost scripts/validate-precompiles.js