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

chore: improve code docs #28

Merged
merged 17 commits into from
Feb 5, 2024
42 changes: 42 additions & 0 deletions docs/plugin/DeployOptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# DeployOptions

DeployOptions provides additional configuration settings for deploying smart contracts across multiple blockchain networks. These options allow for customization of the deployment process, including contract address generation, network-specific deployments, and transaction settings.

## Interface

```ts
interface DeployOptions {
salt?: MatchPrimitiveType<"bytes32", unknown>;
isUniquePerChain?: boolean;
customNonPayableTxOptions?: NonPayableCallOptions;
}
```

## Usages

### salt
- **Description**: Provides entropy for generating a unique contract address. This can be a hexadecimal string `HexString` or a `Uint8Array`.
- **Purpose**: Used to create a predictable yet unique address for the smart contract across different deployments.

### isUniquePerChain
- **Description**: A boolean flag that, when set to true, ensures the contract is deployed with distinct addresses on each blockchain network.

### customNonPayableTxOptions
- **Details**: Customizes transaction settings for contract calls. This option allows setting sender details and other transaction parameters.
- **Reference**: For detailed information about `NonPayableCallOptions`, please refer to the [web3.js documentation](https://docs.web3js.org/api/web3-types/interface/NonPayableCallOptions/).

## Example

In this example, `DeployOptions` is configured to deploy a contract with a specified salt for address generation, ensuring unique addresses on each chain, and customizing the sender address for the deployment transaction.

```ts
const options: DeployOptions = {
salt: "0x0d832502cc5af3e4cf5c9118b013acea29808616be3bd44f89d231c1c56af61f",
isUniquePerChain: true,
customNonPayableTxOptions: {
from: "0x1605B51d318bFfBFd246D565Ee55522b66ddc34a",
},
};
```

This setup ensures a predictable and unique deployment process tailored to specific requirements of a multichain environment.
62 changes: 62 additions & 0 deletions docs/plugin/NetworkArguments.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# NetworkArguments
irubido marked this conversation as resolved.
Show resolved Hide resolved

NetworkArguments define the configuration for deploying smart contracts across various blockchain networks. This setup allows for specifying different deployment settings for each network, providing detailed control over the deployment process.

## Interface

```typescript
interface NetworkArguments<Abi extends ContractAbi = any> {
[network: string]: NetworkArgument<Abi>;
}

interface NetworkArgument<Abi extends ContractAbi = any> {
args: ContractConstructorArgs<Abi>;
initData?: {
initMethodName: keyof ContractMethods<Abi>;
initMethodArgs: unknown[];
};
}
```

## Usages

### NetworkArguments
- **Description**: An object where each key is a network name registered on Sygma, mapped to their respective `NetworkArgument`. This structure facilitates network-specific deployment configurations, allowing for deployment across networks recognized by the Sygma protocol.
- **Purpose**: Enables the deployment of contracts to specified networks, leveraging the configurations tailored for each network as recognized by Sygma.

### NetworkArgument
- **args**
- **Description**: Constructor arguments for the contract on each specified network.
- **Purpose**: Used for initializing the contract upon deployment.

- **initData**
- **Description**: An optional object that specifies additional initialization to be performed after the contract's deployment. When used, it must include both `initMethodName` and `initMethodArgs`.
- **initMethodName**
- **Description**: Specifies the contract method to call for further initialization.
- **initMethodArgs**
- **Description**: An array of values that correspond to the parameters required by the method named in `initMethodName`. These arguments are passed directly to the initialization method call.

## Example

```typescript
const abi = [ ... ] as const;

const networks: NetworkArguments<typeof abi> = {
sepolia: {
args: [18, "zToken"],
initData: {
initMethodName: "setName",
initMethodArgs: ["SuperToken"],
}
},
goerli: {
args: [18, "zToken"],
initData: {
initMethodName: "setName",
initMethodArgs: ["GummyToken"],
}
},
};
```

This example shows how `NetworkArguments` can be used to deploy a contract with specific constructor arguments on the Sepolia and Goerli test networks. It includes optional post-deployment initialization to set unique token names for each network through the `setName` method.
97 changes: 61 additions & 36 deletions packages/plugin/README.md
Original file line number Diff line number Diff line change
@@ -1,58 +1,78 @@
# Chainsafe's Hardhat Plugin for Multichain deployment with Sygma

Experience the seamless integration of Hardhat with Sygma: the ultimate plugin for effortlessly deploying your Ethereum smart contracts across multiple chains.
Embrace the power of Sygma protocol, and transform your deployment process into a streamlined, efficient, and multi-chain adventure.
With this tool, you're not just deploying contracts; you're unlocking new horizons in the blockchain ecosystem.
# ChainSafe's Hardhat Plugin for Multichain Deployment with Sygma

Unlock the full potential of Hardhat with Sygma: the premier plugin for effortlessly deploying your Ethereum smart contracts across multiple blockchain networks. Leveraging the Sygma protocol, this tool revolutionizes your deployment process, making it efficient, streamlined, and truly multi-chain. With ChainSafe's plugin, you're not just deploying contracts—you're exploring new possibilities within the blockchain ecosystem.

## Installation

To install, run:

```bash
npm install --save-dev @chainsafe/hardhat-plugin-multichain-deploy
npm install --save-dev @chainsafe/hardhat-plugin-multichain-deploy @buildwithsygma/sygma-sdk-core
```

Import the plugin in your `hardhat.config.js``:
### Importing the Plugin

For JavaScript users, add this line to your `hardhat.config.js`:

```js
require("@chainsafe/hardhat-plugin-multichain-deploy");
```

Or if you are using TypeScript, in your `hardhat.config.ts``:
For TypeScript users, include it in your `hardhat.config.ts`:

```js
import "@chainsafe/hardhat-plugin-multichain-deploy";
```

## Environment extensions
## Environment Extensions

The plugin adds a `multichain` namespace to the Hardhat Runtime Environment (HRE), introducing new methods for deployment:

```ts
async deployMultichain<Abi extends ContractAbi = any>(
contractName: string,
networkArgs: NetworkArguments<Abi>,
options?: DeployOptions
): Promise<{
deploymentInfo: DeploymentInfo[];
receipt: Transaction;
} | void>

async deployMultichainBytecode<Abi extends ContractAbi = any>(
contractBytecode: string,
contractAbi: Abi,
networkArgs: NetworkArguments<Abi>,
options?: DeployOptions
): Promise<{
deploymentInfo: DeploymentInfo[];
receipt: Transaction;
} | void>
```

- `contractName`: Name of the contract for deployment.
- `contractBytecode`: Compiled bytecode of the contract.
- `contractAbi`: Contract ABI, detailing methods and structures for interaction.
- `networkArgs`: Maps network identifiers to deployment arguments. Refer to [NetworkArguments.md](../../docs/plugin/NetworkArguments.md) for more.
- `options`: Optional deployment settings. Details in [DeployOptions.md](../../docs/plugin/DeployOptions.md).

The package introduces a `multichain` namespace to the Hardhat Runtime Environment (HRE).
## Environment Variable

New methods introduced:
* `async waitInitialization(): Promise<void>`: Returns a promise. Wait for this promise to resolve to ensure readiness for using Sygma.
* `async deployMultichain(nameOrBytecode: string, arguments: string[], options?: Object): Promise<TxHash>`: Deploys a smart contract.
* `nameOrBytecode`: Name or bytecode of the smart contract.
* `arguments`: Arguments for the smart contract deployment.
* `options`: Additional deployment options (details TBD).
- `ADAPTER_ADDRESS`: Address of the adapter, facilitating deployment across chains with Sygma. Use this if deploying custom adapters.

## Configuration

The Hardhat Plugin Multichain Deployment plugin requires specific configurations for successful multi-chain deployment.
To utilize the Multichain Deployment plugin, specific settings are required:

This plugin extends introduce new name space called `multichain` with options:
* `environment`: Specifies the Sygma environment for deployment.
* Import `Environment` from `@buildwithsygma/sygma-sdk-core` for constant values.
* Options: `mainnet`, `testnet`, `devnet`, `local`.
* `deploymentNetworks`: List of networks for deployment.
* Ensure network names match those in `networks`.
* Networks must correspond with Sygma routes. Refer to [Sygma documentation](https://docs.buildwithsygma.com/environments) for routes.
- `multichain` namespace: Configures deployment settings.
- `environment`: Defines the Sygma environment. Use `Environment` from `@buildwithsygma/sygma-sdk-core` for constants.

Example configuration:
### Example Configuration

```typescript
import { Environment } from "@buildwithsygma/sygma-sdk-core";

const config: HardhatUserConfig = {
// ... other configurations ...
// Other configurations...
defaultNetwork: "goerli",
networks: {
sepolia: { ... },
Expand All @@ -61,25 +81,30 @@ const config: HardhatUserConfig = {
},
multichain: {
environment: Environment.TESTNET,
deploymentNetworks: ["sepolia", "optimisticGoerli"],
},
};
```

## Usages

### TODO
## Usage

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you add example how to use it with local network?

After familiarizing yourself with the capabilities, let's see how everything works together.
With the setup complete, let’s deploy an ERC20 contract across multiple chains:

Example scenario: You've created an ERC20 contract and want to deploy it across multiple chains using the configuration mentioned above.
```typescript
// Deploy the contract
const tx = await hre.multichain.deployMultichain('MySuperToken', [name, symbol, decimals], { singer: web3signer });
const networkArgs = {
sepolia: {
args: [name, symbol, decimals],
},
goerli: {
args: [name, symbol, decimals],
},
};
const options = {
salt: "0xcafe00000000000000000000000000000000000000000000000000000000cafe",
};

console.log("Transaction Hash: ", tx);
this.hre.multichain.deployMultichain("MySuperToken", networkArgs, options);
```

## Contribution

For contributing to the project, please refer to the [root readme](../../README.md) file.
To contribute to this project, please see the [monorepo readme](../../README.md) for guidelines.
55 changes: 48 additions & 7 deletions packages/plugin/src/MultichainHardhatRuntimeEnvironmentField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,27 @@ export class MultichainHardhatRuntimeEnvironmentField {
}

/**
* @param contractName name of the contract
* @param networkArgs record key is name of the networks on which contract is being deployed
* @param args contract contructor args
* @param initData optional init method details, method name and args required
* @param salt optional or generated by default from randombytes(32)
* @param isUniquePerChain optional
* @param customNonPayableTxOptions non payable options for web3 deploy.method.send(), payable summed fees are always calculated by the method
* Deploys a contract to multiple blockchain networks.
*
* @param contractName - The name of the contract to be deployed.
* @param networkArgs - An object mapping network identifiers to their deployment arguments. Each network can have unique settings for the deployment. See {@link https://github.com/ChainSafe/hardhat-plugin-multichain-deploy/docs/plugin/NetworkArguments NetworkArguments}.
* @param options - Optional settings for the deployment process. These can include various configurations specific to the deployment. See {@link https://github.com/ChainSafe/hardhat-plugin-multichain-deploy/docs/plugin/DeployOptions DeployOptions}.
* @returns A Promise resolving to a Transaction object or void.
*
* @example
* ```
* const networkArgs = {
* sepolia: {
* args: [ 18, "token" ],
* },
* goerli: { ... },
* };
* const options = {
* salt: "0xcafe00000000000000000000000000000000000000000000000000000000cafe",
* };
*
* this.hre.multichain.deployMultichain("HelloContract", networkArgs, options);
* ```
*/
public async deployMultichain<Abi extends ContractAbi = any>(
contractName: string,
Expand All @@ -77,6 +91,33 @@ export class MultichainHardhatRuntimeEnvironmentField {
);
}

/**
* Deploys a contract using its bytecode and ABI to multiple blockchain networks.
*
* @param contractBytecode - The bytecode of the contract to be deployed. This is the compiled code of the contract.
* @param contractAbi - The ABI of the contract. It defines the methods and structures used to interact with the binary contract.
* @param networkArgs - An object mapping network identifiers to their deployment arguments. Each network can have unique settings for the deployment. See {@link https://github.com/ChainSafe/hardhat-plugin-multichain-deploy/docs/plugin/NetworkArguments NetworkArguments}.
* @param options - Optional settings for the deployment process. These can include various configurations specific to the deployment. See {@link https://github.com/ChainSafe/hardhat-plugin-multichain-deploy/docs/plugin/DeployOptions DeployOptions}.
* @returns A Promise resolving to a Transaction object or void.
*
* @example
* ```
* const contractBytecode = "0x60a060405234801561001057600080fd5b5060405161052b38038061052b83...";
* const contractAbi = [{ ... }, { ... }];
*
* const networkArgs = {
* sepolia: {
* args: [ 18, "token" ],
* },
* goerli: { ... },
* };
* const options = {
* salt: "0xcafe00000000000000000000000000000000000000000000000000000000cafe",
* };
*
* this.hre.multichain.deployMultichain(contractBytecode, contractAbi, networkArgs, options);
* ```
*/
public async deployMultichainBytecode<Abi extends ContractAbi = any>(
contractBytecode: string,
contractAbi: Abi,
Expand Down
18 changes: 10 additions & 8 deletions packages/plugin/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ export type DeploymentNetwork =
| "holesky"
| string;

export type NetworkArguments<Abi extends ContractAbi = any> = {
[network in DeploymentNetwork]: {
args: ContractConstructorArgs<Abi>;
initData?: {
initMethodName: keyof ContractMethods<Abi>;
//impossible to type unless we do something like this.getInitMethod(artifact, methodName).encode(args);
initMethodArgs: unknown[];
};
interface NetworkArgument<Abi extends ContractAbi = any> {
args: ContractConstructorArgs<Abi>;
initData?: {
initMethodName: keyof ContractMethods<Abi>;
//impossible to type unless we do something like this.getInitMethod(artifact, methodName).encode(args);
initMethodArgs: unknown[];
};
}

export type NetworkArguments<Abi extends ContractAbi = any> = {
[network in DeploymentNetwork]: NetworkArgument<Abi>;
};

export interface DeployOptions {
Expand Down
Loading