Hardhat plugin providing comprehensive deployment system for Ethereum smart contracts with replicable deployments and enhanced testing capabilities.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Contract deployment functionality with comprehensive options for deployment strategies, transaction settings, and artifact management.
Deploy a contract with full tracking and redeployment detection.
/**
* Deploy a contract with the given name and options
* @param name - Unique name for the deployment
* @param options - Deployment configuration options
* @returns Promise resolving to deployment result with status
*/
deploy(name: string, options: DeployOptions): Promise<DeployResult>;
interface DeployOptions {
/** Address to deploy from (required) */
from: string;
/** Contract artifact name or ArtifactData object */
contract?: string | ArtifactData;
/** Constructor arguments array */
args?: any[];
/** Enable deterministic deployment using CREATE2 */
deterministicDeployment?: boolean | string;
/** Proxy deployment configuration */
proxy?: boolean | string | ProxyOptions;
/** Library addresses for linking */
libraries?: Libraries;
/** Skip deployment if already deployed */
skipIfAlreadyDeployed?: boolean;
/** Gas limit for deployment transaction */
gasLimit?: string | number | BigNumber;
/** Gas price for deployment transaction */
gasPrice?: string | BigNumber;
/** EIP-1559 max fee per gas */
maxFeePerGas?: string | BigNumber;
/** EIP-1559 max priority fee per gas */
maxPriorityFeePerGas?: string | BigNumber;
/** Transaction nonce */
nonce?: string | number | BigNumber;
/** Ether value to send with deployment */
value?: string | BigNumber;
/** Enable deployment logging */
log?: boolean;
/** Auto-mine transaction on development networks */
autoMine?: boolean;
/** Number of confirmations to wait for */
waitConfirmations?: number;
/** Estimated gas limit for optimization */
estimatedGasLimit?: string | number | BigNumber;
/** Extra gas to add to estimates */
estimateGasExtra?: string | number | BigNumber;
/** Additional data for deployment tracking */
linkedData?: any;
/** Custom data for transaction (zksync support) */
customData?: Record<string, any>;
}Usage Examples:
import { deployments, getNamedAccounts } from "hardhat";
// Basic deployment
const { deployer } = await getNamedAccounts();
const result = await deployments.deploy("MyContract", {
from: deployer,
args: ["arg1", "arg2"],
log: true,
});
console.log(`Deployed at: ${result.address}`);
console.log(`Newly deployed: ${result.newlyDeployed}`);
// Deployment with libraries
await deployments.deploy("ContractWithLibrary", {
from: deployer,
libraries: {
MyLibrary: "0x1234567890123456789012345678901234567890",
},
log: true,
skipIfAlreadyDeployed: true,
});
// Custom contract artifact
await deployments.deploy("CustomContract", {
from: deployer,
contract: "contracts/Custom.sol:CustomContract",
args: [42],
gasLimit: 5000000,
});Get deterministic address and deploy function for CREATE2 deployments.
/**
* Get deterministic deployment address and deploy function
* @param name - Contract deployment name
* @param options - CREATE2 deployment options
* @returns Promise with address and deploy function
*/
deterministic(
name: string,
options: Create2DeployOptions
): Promise<{
address: Address;
implementationAddress?: Address;
deploy(): Promise<DeployResult>;
}>;
interface Create2DeployOptions extends DeployOptionsBase {
/** Salt for CREATE2 deployment */
salt?: string;
}
interface DeployOptionsBase extends TxOptions {
contract?: string | ArtifactData;
args?: any[];
skipIfAlreadyDeployed?: boolean;
linkedData?: any;
libraries?: Libraries;
proxy?: boolean | string | ProxyOptions;
}Usage Examples:
// Get deterministic address before deployment
const { address, deploy } = await deployments.deterministic("MyContract", {
from: deployer,
args: ["constructor", "args"],
salt: "0x1234567890123456789012345678901234567890123456789012345678901234",
});
console.log(`Will deploy to: ${address}`);
// Deploy when ready
const result = await deploy();
console.log(`Deployed to: ${result.address}`); // Same as address above
// Deterministic proxy deployment
const proxyInfo = await deployments.deterministic("ProxiedContract", {
from: deployer,
proxy: {
proxyContract: "OptimizedTransparentProxy",
execute: {
methodName: "initialize",
args: ["init", "args"],
},
},
salt: "0x1111111111111111111111111111111111111111111111111111111111111111",
});
console.log(`Proxy address: ${proxyInfo.address}`);
console.log(`Implementation address: ${proxyInfo.implementationAddress}`);Check if deployment would be different from existing deployment without deploying.
/**
* Check if deployment would be different from existing deployment
* @param name - Deployment name to check
* @param options - Deployment options to compare
* @returns Promise with difference status and address
*/
fetchIfDifferent(
name: string,
options: DeployOptions
): Promise<{ differences: boolean; address?: string }>;Usage Examples:
// Check if redeployment needed
const { differences, address } = await deployments.fetchIfDifferent("MyContract", {
from: deployer,
args: ["new", "args"],
});
if (differences) {
console.log("Contract needs redeployment");
await deployments.deploy("MyContract", {
from: deployer,
args: ["new", "args"],
});
} else {
console.log(`Contract unchanged at ${address}`);
}
// Check deterministic deployment
const deterministicCheck = await deployments.fetchIfDifferent("DeterministicContract", {
from: deployer,
deterministicDeployment: "0x1234567890123456789012345678901234567890123456789012345678901234",
args: ["test"],
});
if (!deterministicCheck.differences && deterministicCheck.address) {
console.log(`Already deployed at deterministic address: ${deterministicCheck.address}`);
}interface DeployResult extends Deployment {
/** Whether this deployment was newly created */
newlyDeployed: boolean;
}
interface Deployment {
/** Deployed contract address */
address: Address;
/** Contract ABI */
abi: ABI;
/** Deployment transaction receipt */
receipt?: Receipt;
/** Deployment transaction hash */
transactionHash?: string;
/** Constructor arguments used */
args?: any[];
/** Additional deployment data */
linkedData?: any;
/** Implementation address for proxies */
implementation?: string;
/** Diamond facets for diamond contracts */
facets?: Facet[];
/** Linked library addresses */
libraries?: Libraries;
/** Contract metadata */
metadata?: string;
/** Contract bytecode */
bytecode?: string;
/** Deployed bytecode */
deployedBytecode?: string;
/** Deployment history for upgrades */
history?: Deployment[];
/** Number of times deployed */
numDeployments?: number;
}
interface ArtifactData {
abi: ABI;
bytecode: string;
deployedBytecode?: string;
metadata?: string;
methodIdentifiers?: any;
storageLayout?: any;
userdoc?: any;
devdoc?: any;
gasEstimates?: any;
}
interface TxOptions extends CallOptions {
from: string;
log?: boolean;
autoMine?: boolean;
estimatedGasLimit?: string | number | BigNumber;
estimateGasExtra?: string | number | BigNumber;
waitConfirmations?: number;
}
interface CallOptions {
from?: string;
gasLimit?: string | number | BigNumber;
gasPrice?: string | BigNumber;
maxFeePerGas?: string | BigNumber;
maxPriorityFeePerGas?: string | BigNumber;
value?: string | BigNumber;
nonce?: string | number | BigNumber;
to?: string;
data?: string;
customData?: Record<string, any>;
}
type Libraries = { [libraryName: string]: Address };
type Address = string;
type ABI = any[];