Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the deployment chain-aware, if possible #777

Open
luismasuelli opened this issue Jun 7, 2024 · 4 comments
Open

Make the deployment chain-aware, if possible #777

luismasuelli opened this issue Jun 7, 2024 · 4 comments
Labels
status:ready This issue is ready to be worked on type:feature Fetaure request

Comments

@luismasuelli
Copy link

luismasuelli commented Jun 7, 2024

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

@kanej kanej added status:ready This issue is ready to be worked on type:feature Fetaure request and removed status:triaging labels Jun 10, 2024
@kanej
Copy link
Member

kanej commented Jun 10, 2024

This is a great point. How should modules deal with differences between chains.
We have consider the equivalent of m.getChainId() as part of the Module API but deferred the decision.
We want to keep the constraint that a single deployment (so a run of a module) is against a single chain, with different runs of the module against different chains leading to multiple deployments. But that still leaves open the question as to how to vary a module based on the context of the chain (e.g. the address that PriceFeed is deployed at).

@luismasuelli
Copy link
Author

I was thinking about some alternatives, all of them considering the premise: A single deployment of a module being against a single chain (and thus making specific additions to the journal, so the integrity / reproducibility / reconciliability of the journal remains a property of ignition, while also doing per-chain logic):

  1. To implement getChainId and getDeploymentId (yes: both) methods in the IgnitionModuleBuilder interface and the IgnitionModuleBuilderImplementation class. This one is harder (TBH I did not clone this repo yet but only traversed transpiled code) but, still, doable.
  2. To add arguments like $chainId and $deploymentId as arguments. I'm not sure but as far as I can remember doing this was not that hard.

Later, I'll properly clone the repo and try some tweaks for either alternative (and, if able, I'll propose the changes in a PR). I'll keep you updated if I succeed.

@SebastienGllmt
Copy link

Although just a workaround, you can pass different parameters or even call different deploy scripts entirely from your CI, so you could have deploy:localhost, deploy:testnet and deploy:mainnet that call different scripts (or the same script with different parameters)

@luismasuelli
Copy link
Author

luismasuelli commented Jun 24, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status:ready This issue is ready to be worked on type:feature Fetaure request
Projects
Status: No status
Development

No branches or pull requests

3 participants