Skip to content

No per-call wait between deploy and read causes RPC read-after-write races #601

Description

@technophile-04

Hello! Following up on the scaffold-eth-2 migration where we hit one more rough edge worth surfacing:

const yourContract = await env.deploy("YourContract", {
  account: deployer,
  artifact: artifacts.YourContract,
  args: [deployer],
});
const greeting = await env.read(yourContract, { functionName: "greeting" }); // we read from the contract

The env.read fails with AbiDecodingZeroDataError: Cannot decode zero data ("0x") roughly half the time. The deploy itself succeeds, and the contract is on-chain — the eth_call just lands on a replica that hasn't yet replicated the post-deploy block.

Actual error:
❯ yarn deploy --reset --network baseSepolia
No contracts to compile
✔ Enter password to decrypt private key:
Environment: baseSepolia
         Chain: Base Sepolia
         Tags: testnet
✔ This will delete all deployments for env: baseSepolia, including any successful, failed or in-flight state.
 (Note that this applies to all deployments irrespective of the tags provided)
Do you want to proceed? … yes
✔ gas price is currently in this range:
slow: 0.000000000005946 (priority: 0.000000000000946)
average: 0.00000000000607 (priority: 0.00000000000107)
fast: 0.00000000000874 (priority: 0.00000000000374)

Do you want to proceed (note that gas price can change for each tx) … yes
- Executing /Users/shivbhonde/Desktop/github/scaffold-eth-2/packages/hardhat/deploy/00_deploy_your_contract.ts
  - Deploying YourContract  with tx:
      0x95113c725362400ae211dce45477f9487128442c4868b8b12ec7c0564ad62d7e
      (tx not found)
    => 0x40d9108fb89cb07401a364ea3d96f86c962004d1
An unexpected error occurred:

AbiDecodingZeroDataError: Cannot decode zero data ("0x") with ABI parameters.

Version: viem@2.48.4

Repro

Minimal repro at technophile-04/hardhat-deploy-read-after-deploy-repro, based on template-ethereum-contracts. Requires Node >= 22.13.

git clone https://github.com/technophile-04/hardhat-deploy-read-after-deploy-repro
cd hardhat-deploy-read-after-deploy-repro
pnpm install

# Copy the example and set DEPLOYER_PRIVATE_KEY to a key with OP Sepolia ETH
cp contracts/.env.example contracts/.env
$EDITOR contracts/.env

# --reset forces a fresh deploy tx every run, which is what triggers the race
pnpm contracts:deploy --network optimismSepolia --reset

Alchemy URLs are preset to scaffold-eth-2's public shared fallback key (already publicly committed there), so the only thing reviewers need to provide is a funded testnet PK.

NOTE: You need to run it twice or thirce pnpm contracts:deploy --network optimismSepolia --reset

Possible hack:

Wrapping env.network.provider with ethers' BrowserProvider and calling waitForTransaction between deploy and read:

import { BrowserProvider } from "ethers";

const yourContract = await env.deploy("YourContract", { /* ... */ });

const provider = new BrowserProvider(env.network.provider as any);
await provider.waitForTransaction(yourContract.transaction.hash, 2);

const greeting = await env.read(yourContract, { functionName: "greeting" });

but maybe there is better way? Instead of instiating the BrowserProvider?

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions