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

diamond-deployment.mddocs/

Diamond Deployment

Full EIP-2535 diamond pattern implementation with automatic facet management, upgrade detection, and deterministic deployment support.

Capabilities

Diamond Deploy Function

Deploy diamond contracts with facet management and automatic upgrade handling.

/**
 * Deploy a diamond contract with specified facets
 * @param name - Diamond deployment name
 * @param options - Diamond deployment configuration
 * @returns Promise resolving to deployment result
 */
diamond: {
  deploy(name: string, options: DiamondOptions): Promise<DeployResult>;
}

interface DiamondOptions extends TxOptions {
  /** Owner address for the diamond */
  owner?: Address;
  /** Array of facets to deploy/configure */
  facets: DiamondFacets;
  /** Custom diamond contract to use as base */
  diamondContract?: string | ArtifactData;
  /** Diamond constructor arguments */
  diamondContractArgs?: any[];
  /** Include default DiamondCutFacet */
  defaultCutFacet?: boolean;
  /** Include default OwnershipFacet */
  defaultOwnershipFacet?: boolean;
  /** Include default DiamondLoupeFacet */
  defaultLoupeFacet?: boolean;
  /** Initialization execution after deployment */
  execute?: {
    contract?:
      | string
      | { name: string; artifact: string | ArtifactData; args?: any[] };
    methodName: string;
    args: any[];
  };
  /** Exclude specific selectors from facets */
  excludeSelectors?: {
    [facetName: string]: string[];
  };
  /** Salt for deterministic diamond deployment */
  deterministicSalt?: string;
  /** Constructor arguments for all facets */
  facetsArgs?: any[];
  /** Libraries for linking */
  libraries?: Libraries;
  /** Additional data for tracking */
  linkedData?: any;
  /** Upgrade tracking index */
  upgradeIndex?: number;
}

Usage Examples:

import { deployments, getNamedAccounts } from "hardhat";

// Basic diamond deployment
const { deployer } = await getNamedAccounts();
await deployments.diamond.deploy("GameDiamond", {
  from: deployer,
  owner: deployer,
  facets: [
    "PlayerFacet",
    "InventoryFacet",
    "BattleFacet",
  ],
});

// Diamond with custom facet configurations
await deployments.diamond.deploy("AdvancedDiamond", {
  from: deployer,
  owner: deployer,
  facets: [
    {
      name: "CustomPlayerFacet",
      contract: "PlayerFacetV2",
      args: ["player", "init", "args"],
    },
    {
      name: "InventoryFacet",
      deterministic: true,
    },
    "BattleFacet", // Simple string facet
  ],
  execute: {
    methodName: "initialize",
    args: ["diamond", "initialization"],
  },
});

// Diamond with excluded selectors
await deployments.diamond.deploy("SelectiveDiamond", {
  from: deployer,
  owner: deployer,
  facets: ["ComprehensiveFacet"],
  excludeSelectors: {
    ComprehensiveFacet: ["deprecatedFunction()", "internalFunction()"],
  },
});

Facet Configuration

Configure individual facets with specific deployment options and arguments.

type DiamondFacets = Array<string | FacetOptions>;

interface FacetOptions {
  /** Custom name for the facet deployment */
  name?: string;
  /** Contract artifact name or data */
  contract?: string | ArtifactData;
  /** Constructor arguments for this facet */
  args?: any[];
  /** Additional data for this facet */
  linkedData?: any;
  /** Libraries for this facet */
  libraries?: Libraries;
  /** Enable deterministic deployment */
  deterministic?: boolean | string;
}

Usage Examples:

// Mixed facet configuration
await deployments.diamond.deploy("FlexibleDiamond", {
  from: deployer,
  owner: deployer,
  facets: [
    // Simple string facet
    "CoreFacet",
    
    // Facet with custom configuration
    {
      name: "ConfigurableFacet",
      contract: "AdvancedFacet",
      args: ["custom", "constructor", "args"],
      deterministic: true,
    },
    
    // Facet with libraries
    {
      name: "LibraryFacet",
      contract: "FacetWithLibrary",
      libraries: {
        MathLib: "0x1234567890123456789012345678901234567890",
      },
    },
    
    // Facet with custom artifact
    {
      name: "CustomFacet",
      contract: {
        abi: [...], // Custom ABI
        bytecode: "0x...", // Custom bytecode
      },
      args: [],
    },
  ],
});

// Deterministic facet deployment
await deployments.diamond.deploy("DeterministicDiamond", {
  from: deployer,
  owner: deployer,
  deterministicSalt: "0x1234567890123456789012345678901234567890123456789012345678901234",
  facets: [
    {
      name: "FacetA",
      deterministic: "0x1111111111111111111111111111111111111111111111111111111111111111",
    },
    {
      name: "FacetB",
      deterministic: true, // Uses default salt
    },
  ],
});

Diamond Upgrades

Automatic facet upgrade detection and diamond cut execution.

Usage Examples:

// Upgrade tracking
await deployments.diamond.deploy("UpgradeableDiamond", {
  from: deployer,
  owner: deployer,
  upgradeIndex: 2, // Only upgrade if current version < 2
  facets: [
    "FacetV1",
    "FacetV2", // New facet for upgrade
  ],
});

// Post-upgrade execution
await deployments.diamond.deploy("InitializableDiamond", {
  from: deployer,
  owner: deployer,
  facets: ["DataFacet", "LogicFacet"],
  execute: {
    contract: {
      name: "DiamondInit",
      artifact: "InitializationContract",
      args: ["init", "contract", "args"],
    },
    methodName: "init",
    args: ["post", "upgrade", "data"],
  },
});

// Custom diamond base contract
await deployments.diamond.deploy("CustomBaseDiamond", {
  from: deployer,
  owner: deployer,
  diamondContract: "MyCustomDiamond",
  diamondContractArgs: ["{owner}", "{facetCuts}", "{init}"],
  facets: ["MyFacet"],
});

Facet Management

Control default facets and selector exclusions.

Usage Examples:

// Minimal diamond (no default facets)
await deployments.diamond.deploy("MinimalDiamond", {
  from: deployer,
  owner: deployer,
  defaultCutFacet: false,
  defaultOwnershipFacet: false,
  defaultLoupeFacet: true, // Keep only loupe for introspection
  facets: ["BusinessLogicFacet"],
});

// Diamond with selector exclusions
await deployments.diamond.deploy("FilteredDiamond", {
  from: deployer,
  owner: deployer,
  facets: [
    "MultiFunctionFacet",
    "AnotherFacet",
  ],
  excludeSelectors: {
    MultiFunctionFacet: [
      "dangerousFunction()",
      "deprecatedFunction(uint256)",
    ],
    AnotherFacet: [
      "internalHelper()",
    ],
  },
});

// Global facet arguments
await deployments.diamond.deploy("UniformDiamond", {
  from: deployer,
  owner: deployer,
  facetsArgs: ["shared", "constructor", "args"], // Used by all facets
  facets: [
    "FacetA", // Will use facetsArgs
    "FacetB", // Will use facetsArgs
    {
      name: "FacetC",
      args: ["custom", "args"], // Overrides facetsArgs
    },
  ],
});

Types

interface DiamondOptions extends TxOptions {
  owner?: Address;
  facets: DiamondFacets;
  diamondContract?: string | ArtifactData;
  diamondContractArgs?: any[];
  defaultCutFacet?: boolean;
  defaultOwnershipFacet?: boolean;
  execute?: {
    contract?:
      | string
      | { name: string; artifact: string | ArtifactData; args?: any[] };
    methodName: string;
    args: any[];
  };
  excludeSelectors?: {
    [facetName: string]: string[];
  };
  deterministicSalt?: string;
  facetsArgs?: any[];
  libraries?: Libraries;
  linkedData?: any;
  upgradeIndex?: number;
}

type DiamondFacets = Array<string | FacetOptions>;

interface FacetOptions {
  name?: string;
  contract?: string | ArtifactData;
  args?: any[];
  linkedData?: any;
  libraries?: Libraries;
  deterministic?: boolean | string;
}

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

interface FacetCut extends Facet {
  action: FacetCutAction;
}

enum FacetCutAction {
  Add,
  Replace,
  Remove,
}

interface TxOptions extends CallOptions {
  from: string;
  log?: boolean;
  autoMine?: boolean;
  estimatedGasLimit?: string | number | BigNumber;
  estimateGasExtra?: string | number | BigNumber;
  waitConfirmations?: number;
}

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