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

feat: initLocalEnvironment #47

Merged
merged 11 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 90 additions & 2 deletions packages/plugin/src/MultichainHardhatRuntimeEnvironmentField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,21 @@ import {
transferStatusInterval,
mapNetworkArgs,
} from "./utils";
import { AdapterABI } from "./adapterABI";
import {
AdapterABI,
AdapterBytecode,
CreateXABI,
CreateXBytecode,
MockBridgeABI,
MockBridgeBytecode,
MockFeeHandlerABI,
MockFeeHandlerBytecode,
} from "./adapterABI";
import {
DeployOptions,
NetworkArguments,
DeployMultichainResponse,
DeployedLocalEnvironmentContracts,
} from "./types";

export class MultichainHardhatRuntimeEnvironmentField {
Expand All @@ -26,7 +36,7 @@ export class MultichainHardhatRuntimeEnvironmentField {
this.web3 = new Web3(provider);
}

public ADAPTER_ADDRESS = vars.get(
private ADAPTER_ADDRESS = vars.get(
"ADAPTER_ADDRESS",
"0x85d62ad850b322152bf4ad9147bfbf097da42217"
);
Expand All @@ -49,6 +59,84 @@ export class MultichainHardhatRuntimeEnvironmentField {
this.isInitiated;
}

/**
* Initializes the local development environment by deploying mock contracts necessary for testing interactions with the Sygma Bridge through Adapter contracts. This setup is vital for developers aiming to simulate the deployment process and contract interactions within a local and controlled environment, closely replicating interactions with the Sygma Bridge in production.
*
* @param deployer - Optional. The Ethereum address of the deployer account. If not provided, the method defaults to using the first available account. This account is tasked with deploying the mock contracts and is essential for setting up the local testing environment.
* @returns A `Promise` that resolves to an object containing the addresses of the deployed mock contracts. These addresses are crucial for conducting further development or testing, enabling comprehensive interaction with the contracts.
*
* @example
* const { adapterAddress } = await initLocalEnvironment();
*
* const options = {
* salt: "0xcafe00000000000000000000000000000000000000000000000000000000cafe",
* adapterAddress,
* };
* await this.hre.multichain.deployMultichain("HelloContract", networkArgs, options);
*/
public async initLocalEnvironment(
deployer?: string
): Promise<DeployedLocalEnvironmentContracts> {
// Assign default values if is not provided
if (!deployer) deployer = (await this.web3.eth.getAccounts())[0];

const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";

/** Deploy Mock Sygma Bridge */
const DOMAIN_ID = BigInt(10);

const feeHandler = new this.web3.eth.Contract(MockFeeHandlerABI);
const feeHandlerResponse = await feeHandler
.deploy({ data: MockFeeHandlerBytecode })
.send({ from: deployer });
const feeHandlerAddress =
feeHandlerResponse.options.address || ZERO_ADDRESS;

const bridge = new this.web3.eth.Contract(MockBridgeABI);
const bridgeResponse = await bridge
.deploy({
data: MockBridgeBytecode,
arguments: [deployer, feeHandlerAddress, DOMAIN_ID],
})
.send({ from: deployer });
const bridgeAddress = bridgeResponse.options.address || ZERO_ADDRESS;

/** Deploy Adapter */
const RESOURCE_ID =
"0x000000000000000000000000000000000000000000000000000000000000cafe";

const createX = new this.web3.eth.Contract(CreateXABI);
const createXResponse = await createX
.deploy({
data: CreateXBytecode,
})
.send({ from: deployer });
const createXAddress = createXResponse.options.address || ZERO_ADDRESS;
console.log(`CreateX locally deployed: ${createXAddress}`);

const adapter = new this.web3.eth.Contract(AdapterABI);
const adapterResponse = await adapter
.deploy({
data: AdapterBytecode,
arguments: [createXAddress, bridgeAddress, RESOURCE_ID],
})
.send({ from: deployer });
const adapterAddress = adapterResponse.options.address || ZERO_ADDRESS;

console.log(
`Adapter locally deployed: ${adapterAddress}` +
"\n" +
"Local environment initiated"
);

return {
adapterAddress,
createXAddress,
bridgeAddress,
feeHandlerAddress,
};
}

/**
* Deploys a contract to multiple blockchain networks.
*
Expand Down
13 changes: 13 additions & 0 deletions packages/plugin/src/adapterABI.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
import CrosschainDeployAdapter from "@chainsafe/hardhat-plugin-multichain-deploy-contracts/artifacts/contracts/CrosschainDeployAdapter.sol/CrosschainDeployAdapter";
import CreateX from "@chainsafe/hardhat-plugin-multichain-deploy-contracts/artifacts/contracts/deps/CreateX.sol/CreateX";
import MockFeeHandler from "@chainsafe/hardhat-plugin-multichain-deploy-contracts/artifacts/contracts/mocks/MockFeeHandler.sol/MockFeeHandler";
import MockBridge from "@chainsafe/hardhat-plugin-multichain-deploy-contracts/artifacts/contracts/mocks/MockBridge.sol/MockBridge";

export const AdapterABI = CrosschainDeployAdapter.abi;
export const AdapterBytecode = CrosschainDeployAdapter.bytecode;

export const CreateXABI = CreateX.abi;
export const CreateXBytecode = CreateX.bytecode;

export const MockFeeHandlerABI = MockFeeHandler.abi;
export const MockFeeHandlerBytecode = MockFeeHandler.bytecode;

export const MockBridgeABI = MockBridge.abi;
export const MockBridgeBytecode = MockBridge.bytecode;
7 changes: 7 additions & 0 deletions packages/plugin/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,10 @@ export interface DeployMultichainResponse {
domainIDs: bigint[];
transactionHash: HexString;
}

export interface DeployedLocalEnvironmentContracts {
createXAddress: string;
adapterAddress: string;
feeHandlerAddress: string;
bridgeAddress: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// We load the plugin here.
import { HardhatUserConfig } from "hardhat/types";
import { Environment } from "@buildwithsygma/sygma-sdk-core";

import "../../../src/index";

const config: HardhatUserConfig = {
solidity: "0.7.3",
defaultNetwork: "hardhat",
multichain: {
environment: Environment.TESTNET,
},
};

export default config;
7 changes: 7 additions & 0 deletions packages/plugin/test/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from "path";
import { resetHardhatContext } from "hardhat/plugins-testing";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { TASK_NODE } from "hardhat/builtin-tasks/task-names";

declare module "mocha" {
interface Context {
Expand All @@ -19,3 +20,9 @@ export function useEnvironment(fixtureProjectName: string) {
resetHardhatContext();
});
}

export function useHardhatNode() {
beforeEach("Loading hardhat node", function () {
this.hre.run(TASK_NODE);
});
}
18 changes: 17 additions & 1 deletion packages/plugin/test/project.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import chaiAsPromised from "chai-as-promised";
import { Environment } from "@buildwithsygma/sygma-sdk-core";
import { MultichainHardhatRuntimeEnvironmentField } from "../src/MultichainHardhatRuntimeEnvironmentField";

import { useEnvironment } from "./helpers";
import { useEnvironment, useHardhatNode } from "./helpers";

use(chaiAsPromised);

Expand Down Expand Up @@ -35,4 +35,20 @@ describe("Integration tests examples", function () {
describe("Hardhat Runtime Environment extension", function () {
useEnvironment("hardhat-project");
});

describe("Hardhat Runtime Environment extension - initLocalEnvironment", function () {
useEnvironment("hardhat-localhost");
useHardhatNode();

it("Should deploy all required contracts on testnet", async function () {
const addresses = await this.hre.multichain.initLocalEnvironment();

assert.deepEqual(addresses, {
adapterAddress: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
createXAddress: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
bridgeAddress: "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
feeHandlerAddress: "0x5FbDB2315678afecb367f032d93F642f64180aa3",
});
});
});
});
Loading