# Amsterdam hardfork support

Description: Reference documentation for Hardhat's experimental support for the upcoming Amsterdam hardfork

Note: This document was authored using MDX

  Source: https://github.com/NomicFoundation/hardhat-website/tree/main/src/content/docs/docs/reference/amsterdam-support.mdx

  Components used in this page:
    - <Run cmd="..."/>: Runs a command in the terminal with npm/pnpm/yarn.
    - :::caution: A warning callout block. Supports custom title `:::caution[Title]` and icon `:::caution{icon="name"}` syntax.

import Run from "@hh/Run.astro";

Hardhat provides **experimental** support for the upcoming Amsterdam execution-layer hardfork. It lets you start testing your contracts against Amsterdam's new behavior before it activates on Ethereum Mainnet.

:::caution

Amsterdam support is experimental and incomplete. The hardfork is still being specified and implemented. The EIPs it includes may change in backward-incompatible ways before launch.

:::

Amsterdam is not enabled by default: `osaka` remains Hardhat's default and latest stable hardfork. You have to opt in explicitly, see [enabling Amsterdam](#enabling-amsterdam).

We are implementing Amsterdam's EIPs incrementally, and will add more as the hardfork is finalized in the run-up to launch.

## Supported features

The following Amsterdam EIPs are currently supported:

- [EIP-7708: ETH transfers emit logs](#eip-7708-eth-transfers-emit-logs)

## Enabling Amsterdam

Set `hardfork` to `"amsterdam"` on a simulated network with the `l1` or `generic` chain type:

```ts
// hardhat.config.ts
import { defineConfig } from "hardhat/config";

export default defineConfig({
  networks: {
    edrAmsterdam: {
      type: "edr-simulated",
      chainType: "l1",
      hardfork: "amsterdam",
    },
  },
});
```

You can then use the new network as the default in scripts and tests with the `--network` flag:

<Run command="hardhat run scripts/example.ts --network edrAmsterdam" />

Or you can name it explicitly when creating a network:

```ts
import { network } from "hardhat";

const connection = await network.create({ network: "edrAmsterdam" });
```

## EIP-7708: ETH transfers emit logs

Under [EIP-7708](https://eips.ethereum.org/EIPS/eip-7708), ETH transfers emit a log with the same shape as an ERC-20 `Transfer` event:

- **address**: the system address `0xfffffffffffffffffffffffffffffffffffffffe`
- **topics[0]**: `keccak256("Transfer(address,address,uint256)")`
- **topics[1]**: the sender
- **topics[2]**: the recipient
- **data**: the amount in wei

This means plain ETH transfers — which previously produced no logs — now emit one. The following is a minimal script that sends 1 ETH and prints the resulting log using viem:

```ts
// scripts/transfer-logs.ts
import { network } from "hardhat";

import {
  decodeEventLog,
  formatEther,
  getAddress,
  parseAbiItem,
  toEventSelector,
} from "viem";

// EIP-7708: value-transferring operations emit a log from this system address
const LOG_EMITTING_SYSTEM_ADDRESS =
  "0xfffffffffffffffffffffffffffffffffffffffe";

// topics[0] is keccak256("Transfer(address,address,uint256)")
const transferEvent = parseAbiItem(
  "event Transfer(address indexed from, address indexed to, uint256 value)",
);
const TRANSFER_TOPIC = toEventSelector(transferEvent);

const { viem } = await network.create({ network: "edrAmsterdam" });

const [sender, recipient] = await viem.getWalletClients();
const publicClient = await viem.getPublicClient();

const hash = await sender.sendTransaction({
  to: recipient.account.address,
  value: 10n ** 18n, // 1 ETH
});

const receipt = await publicClient.waitForTransactionReceipt({ hash });

const transferLogs = receipt.logs.filter(
  (log) =>
    getAddress(log.address) === getAddress(LOG_EMITTING_SYSTEM_ADDRESS) &&
    log.topics[0] === TRANSFER_TOPIC,
);

console.log("ETH transfer logs emitted by the system address:\n");
for (const log of transferLogs) {
  const { args } = decodeEventLog({
    abi: [transferEvent],
    data: log.data,
    topics: log.topics,
  });

  console.log({
    emittedBy: getAddress(log.address),
    from: args.from,
    to: args.to,
    value: `${formatEther(args.value)} ETH`,
  });
}
```

Running it prints a log emitted by the system address, with the `from` and `to` addresses derived from its topics and the transferred amount from its data:

<Run command="hardhat run scripts/transfer-logs.ts" />
