v10| Resources common to all EthereumJS implementations. | | ————————————————— |
Common holds the chain configuration, active hardfork, EIP set, and protocol parameters shared across the EthereumJS libraries. Instantiate one Common per network context and pass it to tx, block, evm, vm, and related packages.
Runnable examples live in examples/.
npm install @ethereumjs/common
import (ESM, TypeScript):
import { Chain, Common, Hardfork, Mainnet } from '@ethereumjs/common'
require (CommonJS, Node.js):
const { Common, Hardfork, Mainnet } = require('@ethereumjs/common')
CommonPick a built-in chain preset (Mainnet, Sepolia, …) and optionally pin a hardfork. When omitted, the chain’s defaultHardfork is used (Hardfork.Prague on Mainnet today).
// ./examples/instantiation.ts
import { Common, Hardfork, Mainnet } from '@ethereumjs/common'
const withHardfork = new Common({ chain: Mainnet, hardfork: Hardfork.Prague })
const withDefault = new Common({ chain: Mainnet })
console.log(`Explicit hardfork: ${withHardfork.hardfork()}`)
console.log(
`Default hardfork: ${withDefault.hardfork()} (DEFAULT_HARDFORK=${withDefault.DEFAULT_HARDFORK})`,
)
Built-in presets: Mainnet, Sepolia, Holesky, Hoodi. Each exposes chainId(), genesis(), hardforks(), bootstrapNodes(), dnsNetworks(), and consensus metadata.
// ./examples/testnetChains.ts
import { Common, Holesky, Hoodi, Mainnet, Sepolia } from '@ethereumjs/common'
for (const chain of [Mainnet, Sepolia, Holesky, Hoodi]) {
const common = new Common({ chain })
console.log(
`${common.chainName()}: chainId=${common.chainId()} hardfork=${common.hardfork()} bootstrapNodes=${common.bootstrapNodes().length}`,
)
}
Chain fields are defined in chains.ts and the ChainConfig type in types.ts.
Set hardfork in the constructor when you know the fork up front (tests, single-fork tooling).
For block replay, syncing, or VM runs, use getHardforkBy() / setHardforkBy(). Pre-merge forks use block number; post-merge forks need timestamp (and typically block number as well).
// ./examples/hardforkByBlock.ts
import { Common, Hardfork, Mainnet } from '@ethereumjs/common'
const common = new Common({ chain: Mainnet })
// Pre-merge: block number alone determines the active hardfork
console.log(`HF at block 12_965_000 (London): ${common.getHardforkBy({ blockNumber: 12_965_000n })}`)
common.setHardforkBy({ blockNumber: 12_965_000n })
console.log(`After setHardforkBy: ${common.hardfork()}`)
// Post-merge: pass timestamp (and block number) for timestamp-based forks
common.setHardforkBy({ blockNumber: 19_000_000n, timestamp: 1_710_338_135n })
console.log(`HF at Cancun timestamp: ${common.hardfork()}`)
common.setHardforkBy({ blockNumber: 19_000_000n, timestamp: 1_746_612_311n })
console.log(`HF at Prague timestamp: ${common.hardfork()}`)
console.log(`Prague active on block 19M: ${common.hardforkIsActiveOnBlock(Hardfork.Prague, 19_000_000n)}`)
This mirrors what @ethereumjs/vm does when executing a block.
Past and upcoming hardforks include chainstart through osaka, plus in-development amsterdam. Hardfork.Prague is the current Mainnet default; Hardfork.Amsterdam is experimental — see the canonical Amsterdam overview in @ethereumjs/vm for release ↔ spec tracking.
Hardfork and EIP parameters (gas costs, limits, rewards, …) are read with param(), paramByHardfork(), and paramByBlock(). Parameter definitions live in hardforks.ts and eips.ts.
// ./examples/paramAccess.ts
import { Common, Hardfork, Mainnet } from '@ethereumjs/common'
// Hardfork-local params (defined on the BPO hardfork schedule)
const bpo = new Common({ chain: Mainnet, hardfork: Hardfork.Bpo1 })
console.log(`BPO target blob count: ${bpo.param('target')}`)
// Downstream packages ship default EIP param sets; inject manually on standalone Common
const common = new Common({ chain: Mainnet, hardfork: Hardfork.London })
common.updateParams({ 1559: { initialBaseFee: 1_000_000_000 } })
console.log(`London initialBaseFee: ${common.param('initialBaseFee')}`)
// paramByBlock() picks the hardfork active at a block (then reads the param)
console.log(`HF at block 12_965_000: ${common.getHardforkBy({ blockNumber: 12_965_000n })}`)
console.log(
`initialBaseFee at block 12_965_000: ${common.paramByBlock('initialBaseFee', 12_965_000n)}`,
)
Downstream packages may supply extra param dictionaries (e.g. @ethereumjs/tx paramsTx for tx-specific EIP params). Pass them via the constructor params option when needed.
EIP-4844 blob gas limits and EIP-7892 BPO schedule changes are exposed through getBlobGasSchedule(). BPO hardforks (Bpo1, …) carry target / max on the hardfork definition; earlier forks need EIP-4844 params (merged automatically when using @ethereumjs/vm / @ethereumjs/evm, or via updateParams() on standalone Common).
// ./examples/blobGasSchedule.ts
import { Common, Hardfork, Mainnet } from '@ethereumjs/common'
const blob4844Params = {
targetBlobGasPerBlock: 393216,
maxBlobGasPerBlock: 786432,
blobGasPriceUpdateFraction: 3338477,
blobGasPerBlob: 131072,
}
// Pre-BPO: EIP-4844 param names
const cancun = new Common({ chain: Mainnet, hardfork: Hardfork.Cancun })
cancun.updateParams({ 4844: blob4844Params })
const cancunSchedule = cancun.getBlobGasSchedule()
console.log(
`Cancun: target=${cancunSchedule.targetBlobGasPerBlock} max=${cancunSchedule.maxBlobGasPerBlock}`,
)
// BPO hardforks: target/max counts are on the HF; multiply by blobGasPerBlob
for (const hardfork of [Hardfork.Bpo1, Hardfork.Bpo2]) {
const common = new Common({ chain: Mainnet, hardfork })
common.updateParams({ 4844: { blobGasPerBlob: blob4844Params.blobGasPerBlob } })
const schedule = common.getBlobGasSchedule()
console.log(
`${hardfork}: target=${schedule.targetBlobGasPerBlock} max=${schedule.maxBlobGasPerBlock} updateFraction=${schedule.blobGasPriceUpdateFraction}`,
)
}
EIPs activate through the hardfork schedule and/or the constructor eips array. Query with isActivatedEIP().
// ./examples/activateEIPs.ts
import { Common, Hardfork, Mainnet } from '@ethereumjs/common'
// Default-on via hardfork schedule (Prague ships EIP-7702)
const prague = new Common({ chain: Mainnet, hardfork: Hardfork.Prague })
console.log(`EIP-7702 on Prague: ${prague.isActivatedEIP(7702)}`)
// Opt-in before schedule: activate on an earlier hardfork via constructor `eips`
const early7702 = new Common({ chain: Mainnet, hardfork: Hardfork.Cancun, eips: [7702] })
console.log(`EIP-7702 forced on Cancun: ${early7702.isActivatedEIP(7702)}`)
// Experimental Amsterdam fork (in development) — full bundle via Hardfork.Amsterdam
const amsterdam = new Common({ chain: Mainnet, hardfork: Hardfork.Amsterdam })
console.log(`EIP-7928 BAL on Amsterdam: ${amsterdam.isActivatedEIP(7928)}`)
console.log(`EIP-7708 transfer logs: ${amsterdam.isActivatedEIP(7708)}`)
console.log(`EIP-8037 two-dimensional gas: ${amsterdam.isActivatedEIP(8037)}`)
console.log(`EIP-7843 SLOTNUM / slotNumber: ${amsterdam.isActivatedEIP(7843)}`)
The following EIPs are currently supported (sorted by EIP number):
Annotations:
(Prague)) indicate default activation on that fork(Amsterdam, experimental) and (experimental) mark unstable specs; behaviour may change on patch releases@ethereumjs/vmcommon.events is an EventEmitter3 instance:
| Event | Description |
|---|---|
hardforkChanged |
Emitted when setHardfork() changes the active hardfork |
// ./examples/hardforkEvents.ts
import { Common, Hardfork, Mainnet } from '@ethereumjs/common'
const common = new Common({ chain: Mainnet, hardfork: Hardfork.London })
common.events.on('hardforkChanged', (hardfork) => {
console.log(`hardforkChanged event: ${hardfork}`)
})
common.setHardfork(Hardfork.Prague)
createCustomCommon() adjusts a base preset or supplies a full ChainConfig. Use it for L2 chain IDs, devnets, and PoA networks.
// ./examples/customChainId.ts
import { Mainnet, createCustomCommon } from '@ethereumjs/common'
// Keep Mainnet params but override chainId — typical for L2 / private networks
const l2Common = createCustomCommon({ chainId: 42161 }, Mainnet)
console.log(`chainId=${l2Common.chainId()} name=${l2Common.chainName()}`)
console.log(`Hardfork schedule inherited (${l2Common.hardforks().length} entries)`)
See the @ethereumjs/tx README for signing with a custom Common.
ChainConfig// ./examples/customChain.ts
import { Hardfork, Mainnet, createCustomCommon } from '@ethereumjs/common'
import { customChainConfig } from '@ethereumjs/testdata'
const common = createCustomCommon(customChainConfig, Mainnet)
console.log(`Chain ${common.chainName()} (chainId=${common.chainId()})`)
console.log(`Hardfork at block 4: ${common.getHardforkBy({ blockNumber: 4n })}`)
console.log(`Bootstrap nodes: ${common.bootstrapNodes().length}`)
common.setHardfork(Hardfork.Byzantium)
console.log(`Active hardfork on custom chain: ${common.hardfork()}`)
// ./examples/consensusConfig.ts
import { Common, Hardfork } from '@ethereumjs/common'
import { testnetMergeChainConfig } from '@ethereumjs/testdata'
const common = new Common({ chain: testnetMergeChainConfig, hardfork: Hardfork.London })
console.log(`consensusType: ${common.consensusType()}`)
console.log(`consensusAlgorithm: ${common.consensusAlgorithm()}`)
const clique = common.consensusConfig()
console.log(`clique period=${clique.period}s epoch=${clique.epoch} blocks`)
For devnets and testnets, derive Common from a Geth genesis.json (chain config + alloc):
// ./examples/fromGethGenesis.ts
import { createCommonFromGethGenesis } from '@ethereumjs/common'
import { postMergeGethGenesis } from '@ethereumjs/testdata'
import { hexToBytes } from '@ethereumjs/util'
const genesisHash = hexToBytes('0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a')
const common = createCommonFromGethGenesis(postMergeGethGenesis, {
chain: 'customChain',
genesisHash,
})
// Defer genesisHash when unknown at init time — set later after computing the genesis block hash
common.setForkHashes(genesisHash)
console.log(`Hardfork is ${common.hardfork()} chainId=${common.chainId()}`)
console.log(`Paris fork hash: ${common.forkHash('paris')}`)
By default, EthereumJS uses audited pure-JS crypto from ethereum-cryptography. For performance or blob/KZG support, pass replacements on customCrypto (types.ts).
Note: WASM backends add supply-chain and audit surface. Evaluate before enabling in production.
// ./examples/customCrypto.ts
import { createBlock } from '@ethereumjs/block'
import { Common, Mainnet } from '@ethereumjs/common'
import { keccak256, waitReady } from '@polkadot/wasm-crypto'
const main = async () => {
await waitReady()
const common = new Common({ chain: Mainnet, customCrypto: { keccak256 } })
const block = createBlock({}, { common })
// Downstream calls on objects sharing this `common` use the custom hash
console.log(block.hash())
}
void main()
KZG is required for blob transactions (EIP-4844) and cell proofs (EIP-7594). Wire any library implementing the KZG interface; the example below uses micro-eth-signer:
// ./examples/initKZG.ts
import { Common, Hardfork, Mainnet } from '@ethereumjs/common'
import { trustedSetup } from '@paulmillr/trusted-setups/fast-peerdas.js'
import { KZG as microEthKZG } from 'micro-eth-signer/kzg.js'
const main = async () => {
const kzg = new microEthKZG(trustedSetup)
const common = new Common({
chain: Mainnet,
hardfork: Hardfork.Cancun,
customCrypto: { kzg },
})
console.log(common.customCrypto.kzg !== undefined)
}
void main()
Hybrid ESM/CJS builds ship with v10; libraries are pure JS by default (no hard-wired WASM). See examples/browser.html for a local dev-server setup.
Generated TypeDoc: Documentation
Helper methods include paramByBlock(), hardforkIsActiveOnBlock(), forkHash(), setForkHashes(), copy(), and updateParams() for advanced overrides.
Hybrid CJS/ESM builds: ESM import resolves to dist/esm/; Node require resolves to dist/cjs/.
The EthereumJS GitHub organization and its repositories are managed by members of the former Ethereum Foundation JavaScript team and the broader Ethereum community. See developer docs and code of conduct.