Skip to content

Make the deployment chain-aware, if possible #777

Open
@luismasuelli

Description

@luismasuelli

Describe the feature

Sometimes the deployment of certain features depends on contracts that do not fully belong to us. For example:

  1. Interacting with a per-chain ENS contract.
  2. Reading prices from a Chainlink Price Feed contract.
  3. Interacting with other Chainlink features (VRF, functions).
  4. A company creates, in a first stage, a set of contracts A, B, C... which are on testnet(s) and mainnet(s). In a later stage, the same company (or perhaps another one) wants to develop a contract D (perhaps an extensible videogame or ecosystem) which relies on A, B and/or C.

What happens in this case? Not all the networks are the same. Just to start, contract A (this also applies to B and C) will have a different address in the testnet(s) vs. the mainnet(s). Also, contract A will not exist on local networks ("localhost" to manually play with, and "hardhat" to run the tests against). In these cases, the user that develops D might have either the full source code of A to locally deploy (if in-company this might be the case) or at least some sort of mock (specially if not being part of the same company).

For example, in my case I wanted to seamlessly interact with Chainlink's Price Feeds (ONE of them in particular) in localhost, testnet, and mainnet. My intention was to create something like this, but I'm aware this is not supported:

Please note: certain parts of the code do not exist and are made up but precisely the idea is for these parts to exist.

// Remember: getChainId does not exist (yet).
const { buildModule, getChainId } = require("@nomicfoundation/hardhat-ignition/modules");

module.exports = buildModule("PriceFeed", (m) => {
  let contract;
  // Remember: getChainId does not exist (yet).
  const chainId = getChainId();

  switch(chainId)
  {
    case 31337:
      // Deploying the mock when on localhost/hardhat.
      contract = m.contract("PriceFeed", [8, 65000000]);
      break;
    case 80002:
      // Using the address of the contract deployed @ Polygon Amoy.
      contract = m.contractAt("PriceFeed", "0x001382149eBa3441043c1c66972b4772963f5D43");
      break;
    case 137:
      // Using the address of the contract deployed @ Polygon Mainnet.
      contract = m.contractAt("PriceFeed", "0xAB594600376Ec9fD91F8e885dADF0CE036862dE0");
      break;
    default:
      // The idea is that this module cannot be definied
      // (i.e. their futures retrieved) if the network was
      // not one of the allowed ones, in my case.
      throw new Error(`Unexpected chain id: ${chainId}`);
  }

  return { contract };
});

In this case, I'd reference a contract when using external networks, but would deploy a local contract (most likely, a mock) when using local.

The idea is to only rely on these kinds of things to make the structure and invariants of the deployment depend on the chosen network.

Search terms

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    status:readyThis issue is ready to be worked ontype:featureFetaure request

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions