or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

contract-interaction.mdcore-deployment.mddeployment-management.mddiamond-deployment.mdindex.mdnamed-accounts.mdproxy-deployment.mdtest-fixtures.mdverification.md
tile.json

deployment-management.mddocs/

Deployment Management

Store, retrieve, and manage deployment artifacts with comprehensive metadata tracking, deployment execution control, and artifact access.

Capabilities

Deployment Storage

Save and manage deployment artifacts with comprehensive metadata.

/**
 * Save a deployment with metadata
 * @param name - Deployment name
 * @param deployment - Deployment data to save
 * @returns Promise that resolves when saved
 */
save(name: string, deployment: DeploymentSubmission): Promise<void>;

/**
 * Delete a saved deployment
 * @param name - Deployment name to delete
 * @returns Promise that resolves when deleted
 */
delete(name: string): Promise<void>;

interface DeploymentSubmission {
  /** Contract ABI */
  abi: ABI;
  /** Deployed contract address */
  address: Address;
  /** Deployment transaction receipt */
  receipt?: Receipt;
  /** Deployment transaction hash */
  transactionHash?: string;
  /** Constructor arguments */
  args?: any[];
  /** Additional deployment metadata */
  linkedData?: any;
  /** Implementation address for proxies */
  implementation?: string;
  /** Diamond facets for diamond contracts */
  facets?: Facet[];
  /** Execution details for initialization */
  execute?: {
    methodName: string;
    args: any[];
  };
  /** Linked library addresses */
  libraries?: Libraries;
  /** Contract metadata from compilation */
  metadata?: string;
  /** Contract creation bytecode */
  bytecode?: string;
  /** Contract runtime bytecode */
  deployedBytecode?: string;
  /** Deployment history for upgrades */
  history?: Deployment[];
  /** Solidity compiler input */
  solcInput?: string;
  /** Hash of solidity compiler input */
  solcInputHash?: string;
  /** Contract documentation */
  userdoc?: any;
  devdoc?: any;
  /** Method identifiers mapping */
  methodIdentifiers?: any;
  /** Contract storage layout */
  storageLayout?: any;
  /** Gas usage estimates */
  gasEstimates?: any;
  /** Factory dependencies (zksync) */
  factoryDeps?: string[];
}

Usage Examples:

import { deployments } from "hardhat";

// Save custom deployment
await deployments.save("CustomContract", {
  abi: contractAbi,
  address: "0x1234567890123456789012345678901234567890",
  args: ["constructor", "arguments"],
  linkedData: { version: "1.0.0", deployer: "Alice" },
  metadata: "contract metadata string",
  libraries: {
    MathLib: "0x9876543210987654321098765432109876543210",
  },
});

// Save deployment with receipt
await deployments.save("TrackedContract", {
  abi: abi,
  address: contractAddress,
  receipt: transactionReceipt,
  transactionHash: txHash,
  args: constructorArgs,
  bytecode: compiledBytecode,
  deployedBytecode: runtimeBytecode,
});

// Save proxy deployment
await deployments.save("ProxyContract", {
  abi: mergedAbi,
  address: proxyAddress,
  implementation: implementationAddress,
  execute: {
    methodName: "initialize",
    args: ["init", "params"],
  },
  history: [previousDeployment], // For upgrade tracking
});

// Delete deployment
await deployments.delete("OldContract");

Deployment Retrieval

Access stored deployment information with error handling.

/**
 * Get a deployment by name (throws if not found)
 * @param name - Deployment name to retrieve
 * @returns Promise resolving to deployment data
 */
get(name: string): Promise<Deployment>;

/**
 * Get a deployment by name (returns null if not found)
 * @param name - Deployment name to retrieve
 * @returns Promise resolving to deployment data or null
 */
getOrNull(name: string): Promise<Deployment | null>;

/**
 * Get all deployments for a specific address
 * @param address - Contract address to find deployments for
 * @returns Promise resolving to array of deployments
 */
getDeploymentsFromAddress(address: string): Promise<Deployment[]>;

/**
 * Get all saved deployments
 * @returns Promise resolving to mapping of deployment names to data
 */
all(): Promise<{ [name: string]: Deployment }>;

interface Deployment {
  address: Address;
  abi: ABI;
  receipt?: Receipt;
  transactionHash?: string;
  args?: any[];
  linkedData?: any;
  implementation?: string;
  facets?: Facet[];
  libraries?: Libraries;
  metadata?: string;
  bytecode?: string;
  deployedBytecode?: string;
  history?: Deployment[];
  numDeployments?: number;
  solcInputHash?: string;
  userdoc?: any;
  devdoc?: any;
  methodIdentifiers?: any;
  storageLayout?: any;
  gasEstimates?: any;
  factoryDeps?: string[];
}

Usage Examples:

// Get deployment (throws if not exists)
try {
  const deployment = await deployments.get("MyContract");
  console.log(`Contract at: ${deployment.address}`);
  console.log(`ABI functions: ${deployment.abi.length}`);
} catch (error) {
  console.log("Contract not deployed");
}

// Get deployment safely
const deployment = await deployments.getOrNull("OptionalContract");
if (deployment) {
  console.log(`Found contract at: ${deployment.address}`);
} else {
  console.log("Contract not found");
}

// Get all deployments
const allDeployments = await deployments.all();
for (const [name, deployment] of Object.entries(allDeployments)) {
  console.log(`${name}: ${deployment.address}`);
}

// Find deployments by address
const deployments_at_address = await deployments.getDeploymentsFromAddress(
  "0x1234567890123456789012345678901234567890"
);
console.log(`Found ${deployments_at_address.length} deployments at address`);

// Access deployment metadata
const contract = await deployments.get("DetailedContract");
if (contract.implementation) {
  console.log(`Proxy implementation: ${contract.implementation}`);
}
if (contract.libraries) {
  console.log(`Linked libraries:`, contract.libraries);
}
if (contract.history) {
  console.log(`Upgrade history: ${contract.history.length} versions`);
}

Deployment Execution Control

Run deployment scripts with tagging and dependency management.

/**
 * Execute deployment scripts
 * @param tags - Optional tags to filter deployment scripts
 * @param options - Execution configuration options
 * @returns Promise resolving to deployments that were executed
 */
run(
  tags?: string | string[],
  options?: {
    /** Reset deployment memory before execution */
    resetMemory?: boolean;
    /** Delete existing deployment files */
    deletePreviousDeployments?: boolean;
    /** Write deployments to disk */
    writeDeploymentsToFiles?: boolean;
    /** Export deployments to file */
    export?: string;
    /** Export all network deployments to file */
    exportAll?: string;
  }
): Promise<{ [name: string]: Deployment }>;

Usage Examples:

// Run all deployment scripts
const deployments_result = await deployments.run();
console.log(`Deployed ${Object.keys(deployments_result).length} contracts`);

// Run specific tagged deployments
await deployments.run(["Token", "DEX"]);

// Run with reset
await deployments.run(["Core"], {
  resetMemory: true,
  deletePreviousDeployments: true,
});

// Run with export
await deployments.run(["Production"], {
  writeDeploymentsToFiles: true,
  export: "./exports/mainnet-deployments.json",
});

// Run multiple tags
await deployments.run(["Infrastructure", "Business", "Frontend"]);

// Run with comprehensive options
const result = await deployments.run(["System"], {
  resetMemory: false,
  deletePreviousDeployments: false,
  writeDeploymentsToFiles: true,
  export: "./deployments-export.json",
  exportAll: "./all-networks-export.json",
});

// Check what was deployed
for (const [name, deployment] of Object.entries(result)) {
  console.log(`Deployed ${name} at ${deployment.address}`);
}

Artifact Management

Access contract compilation artifacts without deployment information.

/**
 * Get hardhat compilation artifact
 * @param name - Contract name to get artifact for
 * @returns Promise resolving to compilation artifact
 */
getArtifact(name: string): Promise<Artifact>;

/**
 * Get extended artifact with additional compilation information
 * @param name - Contract name to get extended artifact for
 * @returns Promise resolving to extended artifact
 */
getExtendedArtifact(name: string): Promise<ExtendedArtifact>;

interface Artifact {
  contractName: string;
  sourceName: string;
  abi: ABI;
  bytecode: string;
  deployedBytecode: string;
  linkReferences: LinkReferences;
  deployedLinkReferences: LinkReferences;
}

interface ExtendedArtifact {
  abi: ABI;
  bytecode: string;
  deployedBytecode?: string;
  metadata?: string;
  linkReferences?: LinkReferences;
  deployedLinkReferences?: LinkReferences;
  solcInput?: string;
  solcInputHash?: string;
  userdoc?: any;
  devdoc?: any;
  methodIdentifiers?: any;
  storageLayout?: any;
  evm?: any;
}

Usage Examples:

// Get basic artifact
const artifact = await deployments.getArtifact("MyContract");
console.log(`Contract name: ${artifact.contractName}`);
console.log(`Source file: ${artifact.sourceName}`);
console.log(`ABI entries: ${artifact.abi.length}`);

// Get extended artifact with metadata
const extendedArtifact = await deployments.getExtendedArtifact("DetailedContract");
if (extendedArtifact.storageLayout) {
  console.log("Storage layout available");
}
if (extendedArtifact.userdoc) {
  console.log("User documentation available");
}
if (extendedArtifact.methodIdentifiers) {
  console.log("Method identifiers:", extendedArtifact.methodIdentifiers);
}

// Use artifact for deployment
const contractArtifact = await deployments.getArtifact("CustomContract");
await deployments.deploy("CustomDeployment", {
  from: deployer,
  contract: contractArtifact,
  args: ["arg1", "arg2"],
});

// Access compilation metadata
const artifact = await deployments.getExtendedArtifact("VerifiableContract");
if (artifact.solcInput && artifact.solcInputHash) {
  console.log("Contract can be verified with solc input");
  // Use for contract verification
}

Hardhat Task Constants

Task identifiers used by hardhat-deploy for defining and referencing deployment tasks.

/** Main deploy task identifier */
const TASK_DEPLOY = 'deploy';

/** Internal main deployment task */
const TASK_DEPLOY_MAIN = 'deploy:main';

/** Internal run deployment subtask */
const TASK_DEPLOY_RUN_DEPLOY = 'deploy:runDeploy';

/** Export deployment data task */
const TASK_EXPORT = 'export';

/** Etherscan verification task */
const TASK_ETHERSCAN_VERIFY = 'etherscan-verify';

/** Sourcify verification task */
const TASK_SOURCIFY = 'sourcify';

Usage Examples:

import { TASK_DEPLOY, TASK_EXPORT } from "hardhat-deploy";

// Use in custom tasks
task("custom-deploy", "Custom deployment task")
  .addFlag("verify", "Verify contracts after deployment")
  .setAction(async (taskArgs, hre) => {
    // Run main deployment task
    await hre.run(TASK_DEPLOY, {
      tags: "core",
      export: "./deployments.json",
    });
    
    if (taskArgs.verify) {
      await hre.run(TASK_ETHERSCAN_VERIFY);
    }
  });

// Reference in scripts
if (hre.hardhatArguments.task === TASK_DEPLOY) {
  console.log("Running deployment task");
}

Utility Functions

Access deployment state information, logging, and helper utilities.

/**
 * Log messages (only shown when logging is enabled)
 * @param args - Arguments to log
 */
log(...args: any[]): void;

/**
 * Get the current network name
 * @returns Network name string
 */
getNetworkName(): string;

/**
 * Get total gas used in current deployment session
 * @returns Total gas used as number
 */
getGasUsed(): number;

/**
 * Get network name from network object
 * @param network - Hardhat network object
 * @returns Network name string
 */
function getNetworkName(network: Network): string;

/**
 * Traverse multiple directories and return all subdirectories
 * @param dirs - Array of directory paths to traverse
 * @returns Array of all subdirectory paths found
 */
function traverseMultipleDirectory(dirs: string[]): string[];

/**
 * Filter ABI entries based on filter criteria
 * @param abi - Contract ABI to filter
 * @param filter - Filter criteria object
 * @returns Filtered ABI array
 */
function filterABI(abi: ABI[], filter: any): ABI[];

/**
 * Merge multiple ABIs into a single ABI
 * @param abis - Array of ABIs to merge
 * @param options - Merge options
 * @returns Merged ABI array
 */
function mergeABIs(abis: ABI[][], options?: any): ABI[];

Usage Examples:

// Network utilities
import { getNetworkName } from "hardhat-deploy";
const network = hre.network;
const name = getNetworkName(network);
console.log(`Current network: ${name}`);

// Directory traversal for deployment scripts
import { traverseMultipleDirectory } from "hardhat-deploy";
const deployPaths = ["./deploy", "./deploy-scripts", "./migrations"];
const allDirs = traverseMultipleDirectory(deployPaths);
console.log(`Found deployment directories: ${allDirs.length}`);

// ABI manipulation
import { filterABI, mergeABIs } from "hardhat-deploy";

// Filter ABI to only include specific function types
const fullABI = contractArtifact.abi;
const viewFunctions = filterABI(fullABI, { type: "function", stateMutability: "view" });
console.log(`Contract has ${viewFunctions.length} view functions`);

// Merge multiple contract ABIs
const tokenABI = await deployments.getArtifact("Token").then(a => a.abi);
const saleABI = await deployments.getArtifact("Sale").then(a => a.abi);
const mergedABI = mergeABIs([tokenABI, saleABI], { 
  deduplicate: true,
  filter: { type: "function" }
});
console.log(`Merged ABI has ${mergedABI.length} entries`);

Error Handling

Handle deployment errors and unknown signer scenarios.

/**
 * Error thrown when a required signer is not available
 */
class UnknownSignerError extends Error {
  /** Transaction that failed due to unknown signer */
  txInfo: {
    from: string;
    to?: string;
    value?: string;
    data?: string;
  };
  
  constructor(message: string, txInfo: any);
}

/**
 * Catch and handle unknown signer errors gracefully
 * @param action - Promise or function that might throw UnknownSignerError
 * @param options - Error handling options
 * @returns Transaction info if error caught, null if successful
 */
catchUnknownSigner(
  action: Promise<any> | (() => Promise<any>),
  options?: { log?: boolean }
): Promise<null | {
  from: string;
  to?: string;
  value?: string;
  data?: string;
}>;

Usage Examples:

// Handle unknown signer scenarios
try {
  await deployments.execute("MyContract", 
    { from: multisigAddress }, 
    "updateSettings", 
    newValue
  );
} catch (error) {
  if (error instanceof UnknownSignerError) {
    console.log("Multisig signer not available locally");
    console.log("Transaction details:", error.txInfo);
  }
}

// Use catchUnknownSigner wrapper
const result = await deployments.catchUnknownSigner(
  deployments.execute("ProxyContract", 
    { from: proxyOwner }, 
    "upgrade", 
    newImplementation
  ),
  { log: true }
);

if (result) {
  // Transaction details for manual execution
  console.log("Manual transaction required:");
  console.log(`From: ${result.from}`);
  console.log(`To: ${result.to}`);
  console.log(`Data: ${result.data}`);
} else {
  console.log("Transaction executed successfully");
}

// Wrap deployment for multisig scenarios
const txInfo = await deployments.catchUnknownSigner(async () => {
  return await deployments.deploy("NewContract", {
    from: deployerMultisig,
    args: ["constructor", "args"],
    proxy: {
      owner: upgradeMultisig,
      proxyContract: "OpenZeppelinTransparentProxy",
    },
  });
});

if (txInfo) {
  console.log("Deployment requires multisig execution");
  // Save transaction details for later execution
}

// Logging during deployment
await deployments.log("Starting deployment phase 1");
await deployments.deploy("Contract1", { from: deployer });
await deployments.log("Contract1 deployed successfully");

// Get network information
const networkName = deployments.getNetworkName();
console.log(`Deploying on network: ${networkName}`);

// Track gas usage
const initialGas = deployments.getGasUsed();
await deployments.deploy("GasHeavyContract", { from: deployer });
const finalGas = deployments.getGasUsed();
console.log(`Deployment used ${finalGas - initialGas} gas`);

// Conditional behavior based on network
const network = deployments.getNetworkName();
if (network === "mainnet") {
  deployments.log("Deploying to mainnet - using conservative gas settings");
} else {
  deployments.log("Deploying to testnet - using aggressive gas settings");
}

File Operations

Manage deployment-related files and metadata.

/**
 * Read a dot file from deployments directory
 * @param name - File name to read (without .dot prefix)
 * @returns Promise resolving to file contents
 */
readDotFile(name: string): Promise<string>;

/**
 * Save content to a dot file in deployments directory
 * @param name - File name to save (without .dot prefix)
 * @param content - Content to save
 * @returns Promise that resolves when saved
 */
saveDotFile(name: string, content: string): Promise<void>;

/**
 * Delete a dot file from deployments directory
 * @param name - File name to delete (without .dot prefix)
 * @returns Promise that resolves when deleted
 */
deleteDotFile(name: string): Promise<void>;

Usage Examples:

// Save deployment metadata
await deployments.saveDotFile("deployment-info", JSON.stringify({
  timestamp: Date.now(),
  deployer: "0x...",
  network: "mainnet",
  version: "1.0.0",
}));

// Read deployment metadata
try {
  const info = await deployments.readDotFile("deployment-info");
  const metadata = JSON.parse(info);
  console.log(`Deployment from: ${new Date(metadata.timestamp)}`);
} catch (error) {
  console.log("No deployment info found");
}

// Save configuration
await deployments.saveDotFile("config", JSON.stringify({
  tokenName: "MyToken",
  tokenSymbol: "MT",
  initialSupply: "1000000",
}));

// Delete temporary files
await deployments.deleteDotFile("temp-data");

// Use for deployment state management
const deploymentState = {
  phase: "initialization",
  contracts: ["Token", "Sale", "Governance"],
  completed: ["Token"],
  pending: ["Sale", "Governance"],
};

await deployments.saveDotFile("state", JSON.stringify(deploymentState));

// Later, resume deployment
const stateContent = await deployments.readDotFile("state");
const state = JSON.parse(stateContent);
console.log(`Resuming deployment at phase: ${state.phase}`);

Types

interface DeploymentSubmission {
  abi: ABI;
  address: Address;
  receipt?: Receipt;
  transactionHash?: string;
  args?: any[];
  linkedData?: any;
  implementation?: string;
  facets?: Facet[];
  execute?: {
    methodName: string;
    args: any[];
  };
  libraries?: Libraries;
  metadata?: string;
  bytecode?: string;
  deployedBytecode?: string;
  history?: Deployment[];
  solcInput?: string;
  solcInputHash?: string;
  userdoc?: any;
  devdoc?: any;
  methodIdentifiers?: any;
  storageLayout?: any;
  gasEstimates?: any;
  factoryDeps?: string[];
}

interface Deployment {
  address: Address;
  abi: ABI;
  receipt?: Receipt;
  transactionHash?: string;
  args?: any[];
  linkedData?: any;
  implementation?: string;
  facets?: Facet[];
  libraries?: Libraries;
  metadata?: string;
  bytecode?: string;
  deployedBytecode?: string;
  history?: Deployment[];
  numDeployments?: number;
  solcInputHash?: string;
  userdoc?: any;
  devdoc?: any;
  methodIdentifiers?: any;
  storageLayout?: any;
  gasEstimates?: any;
  factoryDeps?: string[];
}

interface Facet {
  facetAddress: string;
  functionSelectors: string[];
}

type Libraries = { [libraryName: string]: Address };
type Address = string;
type ABI = any[];