Hardhat RPCs In Revive-dev-node: A Feature Request

Alex Johnson
-
Hardhat RPCs In Revive-dev-node: A Feature Request

Introduction

In the realm of blockchain development, the seamless migration and testing of Solidity projects are crucial for fostering innovation and ensuring reliability. Many projects rely heavily on tools like Hardhat, particularly its built-in Hardhat Network, for in-depth testing. This network offers a suite of helper methods and JSON-RPC extensions that significantly streamline the testing process. However, when migrating projects to revive-dev-node (revm-based), the absence of these helpers can pose a significant challenge, often requiring developers to skip substantial portions of their test suites. This article delves into the necessity of implementing Hardhat Network's helper RPCs in revive-dev-node, highlighting the benefits, impact, and a suggested implementation plan. The goal is to make migration and compatibility testing more practical and efficient, thereby accelerating the adoption of Substrate-based EVM environments.

The Importance of Hardhat Helpers in Solidity Development

Hardhat has become a cornerstone in the Solidity development ecosystem, offering a comprehensive suite of tools that simplify the development, testing, and deployment of smart contracts. One of its key features is the Hardhat Network, a local Ethereum network designed for development and testing purposes. This network provides several helper methods and JSON-RPC extensions that developers rely on to thoroughly test their smart contracts. These helpers allow developers to manipulate the blockchain environment, such as adjusting timestamps, impersonating accounts, and modifying storage, all of which are crucial for simulating various real-world scenarios and edge cases. For instance, time manipulation helpers are essential for testing time-sensitive functionalities like vesting schedules or auction mechanisms. Account impersonation allows developers to test access control mechanisms by simulating different user roles. Storage manipulation is vital for testing upgrade patterns and proxy contracts.

The Challenge of Migrating Solidity Projects to revive-dev-node

When migrating Solidity projects from Hardhat to other environments like revive-dev-node, the absence of these Hardhat-specific helpers becomes a major roadblock. revive-dev-node, being a revm-based environment, offers its own set of functionalities, but it does not inherently support the Hardhat Network's helper methods. This discrepancy means that developers often have to skip large portions of their test suites when migrating, leading to reduced test coverage and lower confidence in the compatibility of their contracts. Popular libraries and protocols like OpenZeppelin, Uniswap, and various Account Abstraction implementations heavily rely on these helpers. Without them, the testing process becomes cumbersome, time-consuming, and less reliable. Therefore, implementing these RPCs in revive-dev-node is not just a convenience but a necessity for ensuring smooth migration and robust testing.

The Need for Hardhat Helper RPCs in revive-dev-node

Integrating Hardhat helper RPCs into revive-dev-node is a pivotal step towards streamlining the migration and testing process for Solidity projects. The current lack of these helpers necessitates skipping significant portions of test suites, thereby undermining confidence in compatibility. Popular libraries and protocols like OpenZeppelin, Uniswap, and Account Abstraction implementations heavily depend on these helpers, making their absence a considerable hurdle. By implementing these RPCs, revive-dev-node can significantly lower the barrier for projects to validate on Substrate-based EVM environments. This section will delve into the specific helpers that are most critical and the impact their implementation would have on the developer experience.

High-Impact Helpers to Prioritize

Among the various Hardhat Network helpers, loadFixture stands out as a high-impact tool that should be prioritized. The loadFixture helper, along with its underlying RPCs (evm_snapshot and evm_revert), is widely used across most Hardhat-based repositories to speed up and stabilize tests. It allows developers to create a snapshot of the blockchain state at a certain point and revert to it later, effectively resetting the environment to a known state. This is particularly useful for tests that involve stateful interactions, where the outcome of a test depends on the state of the blockchain. By using loadFixture, developers can avoid the overhead of redeploying contracts and re-executing setup transactions for each test, significantly reducing test execution time and improving stability. Additionally, the frequently used evm_mine RPC, which mines a new block, is crucial for advancing the blockchain's state and triggering events that depend on block progression.

Requested Helper Methods and Their Impact

Beyond loadFixture, several other helper methods are frequently used in Solidity projects. These can be broadly grouped into three categories: Time Manipulation, Account Impersonation, and Storage Manipulation. Each category addresses specific testing needs and contributes to the overall robustness of smart contract validation.

1. Time Manipulation

Time manipulation helpers are essential for testing functionalities that depend on the passage of time, such as vesting contracts, auctions, and governance mechanisms. The common methods include:

  • time.clock.timestamp() and time.latest(): These methods retrieve the current timestamp of the latest block.
  • time.increase(seconds) and time.increaseBy.timestamp(duration): These methods increase the blockchain's timestamp by a specified duration.
  • time.increaseTo(timestamp) and time.increaseTo.timestamp(to): These methods set the blockchain's timestamp to a specific value.
  • time.setNextBlockTimestamp(ts): This method sets the timestamp for the next block to be mined.
  • time.clockFromReceipt.timestamp(receipt): This method calculates the timestamp based on a transaction receipt.
  • time.clock[mode](): This method retrieves the latest timestamp or block number based on the specified mode.
  • mine() / mine(n): These methods mine a single block or a specified number of blocks.

These methods rely on underlying RPCs such as evm_increaseTime and evm_setNextBlockTimestamp, which are crucial for simulating the passage of time in a controlled manner. The ability to manipulate time is critical for testing various scenarios, such as the unlocking of tokens after a certain period, the expiration of an auction, or the enactment of governance proposals. The impact areas observed in the OpenZeppelin migration experience include access control, governance, finance, and token implementations (particularly ERC20Votes/Votes.behavior).

2. Account Impersonation

Account impersonation helpers allow developers to simulate interactions from different accounts without needing their private keys. This is particularly useful for testing access control mechanisms and administrative flows. The common methods include:

  • impersonate(account) and impersonateAccount(account): These methods impersonate a specified account, allowing transactions to be sent from that account's address.
  • setBalance(address, balance): This method sets the balance of a specified account, which is often used in conjunction with impersonation to ensure the account has sufficient funds for transactions.

These methods rely on underlying RPCs such as hardhat_impersonateAccount and hardhat_setBalance. Account impersonation is essential for testing scenarios where different accounts have different permissions or roles, such as an administrator who can perform privileged actions or a regular user who can only perform certain functions. The impact areas observed include access/manager patterns and admin flows.

3. Storage Manipulation

Storage manipulation helpers allow developers to directly modify the storage of a smart contract. This is particularly useful for testing proxy patterns, upgrade mechanisms, and other scenarios where the state of a contract needs to be altered directly. The common methods include:

  • setStorageAt(address, slot, value) and setSlot(address, slot, value): These methods set the value of a specified storage slot in a contract.

These methods rely on the underlying RPC hardhat_setStorageAt. Storage manipulation is crucial for testing the integrity of data structures and the behavior of contracts when their storage is modified. The impact areas observed include proxies (e.g., ERC1967Utils), access/manager patterns, and upgrade test flows.

Why Implementing Hardhat RPCs Matters

The implementation of Hardhat RPCs in revive-dev-node is not merely a convenience; it is a critical step towards enhancing the developer experience and accelerating ecosystem adoption. Popular libraries and protocols, such as OpenZeppelin, Uniswap, and Account Abstraction implementations, rely heavily on these helpers. Without them, developers are forced to conditionally skip large portions of test suites, which reduces coverage and undermines confidence in the compatibility of their projects. This section elaborates on the significance of these helpers and the benefits of their implementation.

Lowering the Barrier for Project Validation

One of the primary reasons why implementing Hardhat RPCs matters is that it significantly lowers the barrier for projects to validate on Substrate-based EVM environments. Many Solidity projects are initially developed and tested using Hardhat due to its ease of use and comprehensive feature set. When these projects are migrated to other environments, the absence of familiar tools and helpers can create a steep learning curve and increase the effort required for testing. By providing Hardhat-compatible RPCs, revive-dev-node can make the migration process smoother and more efficient.

Enhancing Test Coverage and Confidence

The use of Hardhat helpers allows developers to write more comprehensive and robust tests. For example, the loadFixture helper enables the creation of stable and reproducible test environments, while time manipulation helpers allow for the simulation of time-dependent scenarios. Account impersonation and storage manipulation helpers provide the flexibility to test access control mechanisms and contract upgrades thoroughly. When these helpers are not available, developers are often forced to skip tests that rely on them, which reduces test coverage and can lead to undetected bugs. By implementing these RPCs, revive-dev-node ensures that developers can maintain high test coverage and have greater confidence in the reliability of their contracts.

Accelerating Ecosystem Adoption

The ease of testing and validation is a crucial factor in the adoption of any blockchain platform. By providing a development environment that is familiar and easy to use, revive-dev-node can attract more developers and projects to the Substrate-based EVM ecosystem. The implementation of Hardhat RPCs is a key step in this direction, as it removes a significant obstacle for projects looking to migrate or validate their contracts on revive-dev-node. This can lead to increased adoption of the platform and a more vibrant and diverse ecosystem.

Suggested Implementation Plan

An incremental implementation plan is the most pragmatic approach to adding Hardhat helper RPCs to revive-dev-node. This allows for a phased rollout, focusing on the most critical helpers first and gradually adding others based on their impact and complexity. This section outlines a suggested implementation plan, breaking it down into phases to ensure a smooth and efficient integration process.

Phase 1: Highest Leverage Helpers

The first phase should focus on implementing the helpers that provide the highest leverage in terms of testing efficiency and coverage. These include:

  • loadFixture: As discussed earlier, loadFixture is a critical helper for stabilizing stateful test flows and dramatically speeding up execution. It relies on the underlying RPCs evm_snapshot and evm_revert.
  • evm_snapshot and evm_revert: These RPCs are fundamental to the loadFixture helper and are also commonly used independently for managing blockchain state in tests.
  • evm_mine / hardhat_mine: These RPCs are used to mine new blocks, which is essential for advancing the blockchain's state and triggering events that depend on block progression.
  • evm_increaseTime: This RPC allows for the manipulation of the blockchain's timestamp, which is crucial for testing time-dependent functionalities.
  • evm_setNextBlockTimestamp: This RPC sets the timestamp for the next block to be mined, providing more precise control over time manipulation.

Implementing these helpers in Phase 1 would address the most pressing needs of developers and significantly improve the testing experience on revive-dev-node.

Phase 2: Account Impersonation

The second phase should focus on implementing account impersonation helpers, which are essential for testing access control mechanisms and administrative flows. These include:

  • hardhat_impersonateAccount: This RPC allows for the impersonation of a specified account, enabling transactions to be sent from that account's address.
  • hardhat_setBalance: This RPC sets the balance of a specified account, which is often used in conjunction with impersonation to ensure the account has sufficient funds for transactions.

Implementing these helpers in Phase 2 would enable developers to thoroughly test scenarios where different accounts have different permissions or roles.

Phase 3: Storage Manipulation

The third phase should focus on implementing storage manipulation helpers, which are crucial for testing proxy patterns, upgrade mechanisms, and other scenarios where the state of a contract needs to be altered directly. This includes:

  • hardhat_setStorageAt: This RPC allows for the direct modification of a specified storage slot in a contract.

Implementing this helper in Phase 3 would provide developers with the ability to test the integrity of data structures and the behavior of contracts when their storage is modified.

Optional: Hardhat Time Helpers and Block Timestamp Semantics

As an optional phase, the implementation could include additional Hardhat time helpers such as time.latest and time.latestBlock. It's also crucial to ensure that block timestamp semantics match expectations, as inconsistencies in this area can lead to unexpected behavior in tests. This involves ensuring that the timestamp returned by time.latest is consistent with the timestamp of the latest block mined.

Notes from Testing: OpenZeppelin Migration Experience

During the OpenZeppelin migration to revive-dev-node, several key observations highlighted the importance of Hardhat helpers. All tests that used Hardhat-only helpers had to be skipped, which significantly reduced test coverage. The loadFixture helper was identified as particularly critical due to its ability to stabilize stateful test flows and dramatically speed up execution. Additionally, stricter txpool validation (e.g., “priority too low”) with revm/Substrate was observed, which increases the importance of these helpers to keep tests deterministic and debuggable. This section provides a detailed account of these observations and their implications.

The Critical Role of loadFixture

The loadFixture helper emerged as one of the most crucial tools for testing Solidity projects. Its ability to create snapshots of the blockchain state and revert to them as needed significantly reduces test execution time and improves stability. In the OpenZeppelin migration, the absence of loadFixture meant that tests had to be rerun from scratch for each scenario, which is both time-consuming and resource-intensive. By implementing loadFixture and its underlying RPCs (evm_snapshot and evm_revert), revive-dev-node can provide a more efficient and reliable testing environment.

Handling Stricter Txpool Validation

The stricter txpool validation observed with revm/Substrate adds another layer of complexity to the testing process. Issues such as “priority too low” errors can arise if transactions are not submitted with sufficient gas or priority fees. This makes it even more important to have tools that can control the blockchain's state and ensure that tests are deterministic and debuggable. Hardhat helpers, such as time manipulation and account impersonation, can help developers manage these issues by allowing them to simulate different scenarios and adjust transaction parameters as needed.

References: Hardhat Network Helpers and JSON-RPC Methods

To fully understand the scope of this feature request, it's essential to refer to the documentation for Hardhat Network Helpers and JSON-RPC methods. This section provides links to these resources and highlights the specific methods that are most relevant to the implementation plan.

Hardhat Network Helpers

The Hardhat Network Helpers documentation provides an overview of the various helper methods available in the Hardhat Network. These helpers cover a wide range of functionalities, including time manipulation, account impersonation, and storage manipulation.

Hardhat JSON-RPC Methods

The Hardhat JSON-RPC methods documentation provides detailed information about the underlying RPCs that are used by the Hardhat Network Helpers. These RPCs allow developers to interact directly with the blockchain and perform various operations, such as taking snapshots, reverting state, and manipulating time.

  • Hardhat JSON-RPC methods: https://hardhat.org/hardhat-network/docs/reference
  • Specific RPCs of interest: evm_snapshot, evm_revert, evm_increaseTime, evm_mine, evm_setNextBlockTimestamp, hardhat_impersonateAccount, hardhat_setBalance, hardhat_setStorageAt, hardhat_mine

Proposed Solution: Dev-Only Sandbox Mode

To effectively implement Hardhat helper RPCs without compromising the integrity of the main chain, a dev-only sandbox mode is proposed for revive-dev-node. This mode would run REVM instead of a full consensus-driven chain, decoupling testing from consensus/finality rules and making Hardhat-style helpers trivial to implement and deterministic. This section delves into the rationale behind the sandbox mode and its benefits.

Why a Sandbox Mode?

A sandbox mode offers several advantages for implementing Hardhat helper RPCs:

  • Simplifies time: With no consensus clock, dev_setNextBlockTimestamp and dev_mine can directly control the next block’s timestamp and production without violating chain rules. This makes time manipulation helpers much easier to implement and use.
  • Deterministic tests: Manual sealing avoids variability from txpool/authoring, ensuring that tests are reproducible. evm_snapshot/evm_revert become cheap in-memory operations, further improving test efficiency.
  • Easier helpers: Impersonation, balance/top-up, and storage overrides no longer need to respect chain economics; they’re just local mutations guarded by a dev flag. This simplifies the implementation of these helpers and makes them more flexible.
  • Clear separation: Keeps production-node behavior intact while giving test suites a purpose-built environment. This ensures that the testing environment does not interfere with the main chain and that production code behaves as expected.

Implementation Details

The sandbox mode could be implemented as a flag for revive-dev-node (e.g., --sandbox or --dev-sandbox) or as a separate binary (revive-sandbox). This mode would provide a dedicated environment for testing, with all the necessary Hardhat helper RPCs available.

Conclusion

The addition of Hardhat helper RPCs to revive-dev-node is a crucial step towards making it a more developer-friendly and versatile platform for Solidity projects. By implementing these helpers, revive-dev-node can significantly lower the barrier for projects to validate on Substrate-based EVM environments, enhance test coverage and confidence, and accelerate ecosystem adoption. The proposed dev-only sandbox mode offers a pragmatic and efficient way to implement these helpers without compromising the integrity of the main chain.

By following the suggested incremental implementation plan, revive-dev-node can gradually add the most critical helpers, starting with loadFixture and its underlying RPCs, followed by account impersonation and storage manipulation helpers. This phased approach ensures that the most pressing needs of developers are addressed first, while also allowing for a smooth and efficient integration process.

In conclusion, implementing Hardhat RPCs in revive-dev-node is a strategic move that will benefit the entire ecosystem, making it easier for developers to build, test, and deploy their Solidity projects on Substrate-based EVM environments. This will foster innovation, increase adoption, and ultimately strengthen the blockchain community.

For further reading on Hardhat Network and its capabilities, visit the official Hardhat Documentation. This resource provides comprehensive information on Hardhat's features, including its network helpers and JSON-RPC methods.

You may also like