diff --git a/node_modules/@openzeppelin/hardhat-upgrades/dist/deploy-proxy.js b/node_modules/@openzeppelin/hardhat-upgrades/dist/deploy-proxy.js
index 01e2cd9..a278d26 100644
--- a/node_modules/@openzeppelin/hardhat-upgrades/dist/deploy-proxy.js
+++ b/node_modules/@openzeppelin/hardhat-upgrades/dist/deploy-proxy.js
@@ -15,7 +15,64 @@ function makeDeployProxy(hre, defenderModule) {
         opts = (0, utils_2.enableDefender)(hre, defenderModule, opts);
         const { provider } = hre.network;
         const manifest = await upgrades_core_1.Manifest.forNetwork(provider);
-        const { impl, kind } = await (0, utils_1.deployProxyImpl)(hre, ImplFactory, opts);
+        let impl;
+        let kind = opts.kind;
+        if (opts.create2Factory?.implementationAddress) {
+            const { getDeployData } = await Promise.resolve().then(() => require('./utils/deploy-impl'));
+            const deployData = await getDeployData(hre, ImplFactory, opts);
+            const { validateProxyImpl } = await Promise.resolve().then(() => require('./utils/validate-impl'));
+            await validateProxyImpl(deployData, opts);
+            if (opts.kind === undefined) {
+                throw new Error('Broken invariant: Proxy kind is undefined');
+            }
+            kind = opts.kind;
+            impl = opts.create2Factory.implementationAddress;
+        }
+        else if (opts.create2Factory && opts.create2Factory.deployImpl !== false) {
+            const { getDeployData } = await Promise.resolve().then(() => require('./utils/deploy-impl'));
+            const deployData = await getDeployData(hre, ImplFactory, opts);
+            const { validateProxyImpl } = await Promise.resolve().then(() => require('./utils/validate-impl'));
+            await validateProxyImpl(deployData, opts);
+            if (opts.kind === undefined) {
+                throw new Error('Broken invariant: Proxy kind is undefined');
+            }
+            kind = opts.kind;
+            const implSalt = opts.create2Factory.implSalt;
+            if (!implSalt) {
+                throw new Error('create2Factory implementation deployment requires an implementation salt');
+            }
+            const implBytecode = ImplFactory.bytecode;
+            const initCode = hre.ethers.concat([implBytecode, '0x']);
+            const expectedAddress = hre.ethers.getCreate2Address(opts.create2Factory.address, implSalt, hre.ethers.keccak256(initCode));
+            const existingCode = await hre.ethers.provider.getCode(expectedAddress);
+            const implExists = existingCode !== '0x';
+            const deployment = await (0, upgrades_core_1.fetchOrDeployGetDeployment)(deployData.version, deployData.provider, async () => {
+                const abi = ImplFactory.interface.format(true);
+                if (implExists) {
+                    return {
+                        abi,
+                        layout: deployData.layout,
+                        address: expectedAddress,
+                        txHash: undefined,
+                    };
+                }
+                const implDeployment = await (0, utils_1.deployViaCreate2Factory)(hre, opts.create2Factory.address, implSalt, implBytecode, '0x');
+                return {
+                    abi,
+                    layout: deployData.layout,
+                    address: implDeployment.address,
+                    txHash: implDeployment.txHash,
+                    deployTransaction: implDeployment.deployTransaction,
+                    remoteDeploymentId: implDeployment.remoteDeploymentId || '',
+                };
+            }, opts, false);
+            impl = deployment.address;
+        }
+        else {
+            const result = await (0, utils_1.deployProxyImpl)(hre, ImplFactory, opts);
+            impl = result.impl;
+            kind = result.kind;
+        }
         const contractInterface = ImplFactory.interface;
         const data = (0, utils_1.getInitializerData)(contractInterface, args, opts.initializer);
         const deployFn = opts.deployFunction || utils_1.deploy;
@@ -34,6 +91,39 @@ function makeDeployProxy(hre, defenderModule) {
             }
         }
         const signer = (0, utils_1.getSigner)(ImplFactory.runner);
+        const deployCreate2Proxy = async (artifactName, constructorTypes, constructorValues) => {
+            if (!opts.create2Factory) {
+                throw new Error('create2Factory is required');
+            }
+            const proxyArtifact = await hre.artifacts.readArtifact(artifactName);
+            const proxyBytecode = proxyArtifact.bytecode;
+            const constructorArgs = hre.ethers.AbiCoder.defaultAbiCoder().encode(constructorTypes, constructorValues);
+            const proxyInitCode = hre.ethers.concat([proxyBytecode, constructorArgs]);
+            const expectedProxyAddress = hre.ethers.getCreate2Address(opts.create2Factory.address, opts.create2Factory.salt, hre.ethers.keccak256(proxyInitCode));
+            const existingProxyCode = await hre.ethers.provider.getCode(expectedProxyAddress);
+            if (existingProxyCode !== '0x') {
+                return {
+                    kind,
+                    address: expectedProxyAddress,
+                    txHash: '0x0000000000000000000000000000000000000000000000000000000000000000',
+                    remoteDeploymentId: '',
+                };
+            }
+            if (opts.create2Factory.multicall) {
+                const deployerAddress = await signer.getAddress();
+                return {
+                    kind,
+                    ...(await (0, utils_1.deployViaMulticall)(hre, opts.create2Factory.multicall, opts.create2Factory.address, opts.create2Factory.salt, proxyBytecode, constructorArgs, expectedProxyAddress, data, deployerAddress, opts.create2Factory.transferOwnership === true, opts.create2Factory.postDeployCalls || [])),
+                };
+            }
+            if (opts.create2Factory.postDeployCalls?.length) {
+                throw new Error('create2Factory.postDeployCalls requires create2Factory.multicall');
+            }
+            return {
+                kind,
+                ...(await (0, utils_1.deployViaCreate2Factory)(hre, opts.create2Factory.address, opts.create2Factory.salt, proxyBytecode, constructorArgs)),
+            };
+        };
         let proxyDeployment;
         switch (kind) {
             case 'beacon': {
@@ -44,7 +134,12 @@ function makeDeployProxy(hre, defenderModule) {
                     throw new upgrades_core_1.InitialOwnerUnsupportedKindError(kind);
                 }
                 const ProxyFactory = opts.proxyFactory || (await (0, utils_1.getProxyFactory)(hre, signer));
-                proxyDeployment = Object.assign({ kind }, await deployFn(hre, opts, ProxyFactory, impl, data));
+                if (opts.create2Factory) {
+                    proxyDeployment = await deployCreate2Proxy('@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy', ['address', 'bytes'], [impl, opts.create2Factory.multicall ? '0x' : data]);
+                }
+                else {
+                    proxyDeployment = Object.assign({ kind }, await deployFn(hre, opts, ProxyFactory, impl, data));
+                }
                 break;
             }
             case 'transparent': {
@@ -53,7 +148,12 @@ function makeDeployProxy(hre, defenderModule) {
                     throw new upgrades_core_1.UpgradesError('`initialOwner` must not be a ProxyAdmin contract.', () => `If the contract at address ${initialOwner} is not a ProxyAdmin contract and you are sure that this contract is able to call functions on an actual ProxyAdmin, skip this check with the \`unsafeSkipProxyAdminCheck\` option.`);
                 }
                 const TransparentUpgradeableProxyFactory = opts.proxyFactory || (await (0, utils_1.getTransparentUpgradeableProxyFactory)(hre, signer));
-                proxyDeployment = Object.assign({ kind }, await deployFn(hre, opts, TransparentUpgradeableProxyFactory, impl, initialOwner, data));
+                if (opts.create2Factory) {
+                    proxyDeployment = await deployCreate2Proxy('@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy', ['address', 'address', 'bytes'], [impl, initialOwner, opts.create2Factory.multicall ? '0x' : data]);
+                }
+                else {
+                    proxyDeployment = Object.assign({ kind }, await deployFn(hre, opts, TransparentUpgradeableProxyFactory, impl, initialOwner, data));
+                }
                 break;
             }
         }
diff --git a/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/deploy.d.ts b/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/deploy.d.ts
index da66d9a..403db3f 100644
--- a/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/deploy.d.ts
+++ b/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/deploy.d.ts
@@ -9,4 +9,10 @@ export type EthersOrDefenderDeployment = Required<Deployment> & DeployTransactio
 export type DefenderDeployment = Required<Deployment & RemoteDeploymentId> & DeployTransaction;
 export type EthersDeployment = Required<Deployment & DeployTransaction> & RemoteDeploymentId;
 export declare function deploy(hre: HardhatRuntimeEnvironment, opts: UpgradeOptions & EthersDeployOptions & DefenderDeployOptions, factory: ContractFactory, ...args: unknown[]): Promise<EthersOrDefenderDeployment>;
+export declare function deployViaCreate2Factory(hre: HardhatRuntimeEnvironment, factoryAddress: string, salt: string, proxyBytecode: string, constructorArgs: string): Promise<EthersDeployment>;
+export declare function deployViaMulticall(hre: HardhatRuntimeEnvironment, multicallAddress: string, factoryAddress: string, salt: string, proxyBytecode: string, constructorArgs: string, expectedProxyAddress: string, initData: string, deployerAddress?: string, shouldTransferOwnership?: boolean, postDeployCalls?: Array<{
+    target?: string;
+    data: string;
+    value?: string;
+}>): Promise<EthersDeployment>;
 //# sourceMappingURL=deploy.d.ts.map
\ No newline at end of file
diff --git a/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/deploy.js b/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/deploy.js
index 46c2c7f..a10f82b 100644
--- a/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/deploy.js
+++ b/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/deploy.js
@@ -1,6 +1,8 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.deploy = deploy;
+exports.deployViaCreate2Factory = deployViaCreate2Factory;
+exports.deployViaMulticall = deployViaMulticall;
 const deploy_1 = require("../defender/deploy");
 async function deploy(hre, opts, factory, ...args) {
     if (opts?.useDefenderDeploy) {
@@ -23,4 +25,99 @@ async function ethersDeploy(factory, ...args) {
     const txHash = deployTransaction.hash;
     return { address, txHash, deployTransaction };
 }
+async function deployViaCreate2Factory(hre, factoryAddress, salt, proxyBytecode, constructorArgs) {
+    const [deployer] = await hre.ethers.getSigners();
+    const initCode = hre.ethers.concat([proxyBytecode, constructorArgs]);
+    const expectedAddress = hre.ethers.getCreate2Address(factoryAddress, salt, hre.ethers.keccak256(initCode));
+    const factoryContract = await hre.ethers.getContractAt([
+        'function deploy(bytes32 salt, bytes memory initCode, bytes memory data, uint256 create2ForwardValue, uint256 callForwardValue) external payable returns (address deployed)',
+        'event Deployed(address indexed addr)',
+    ], factoryAddress, deployer);
+    const tx = await factoryContract.deploy(salt, initCode, '0x', 0, 0, { value: 0 });
+    const receipt = await tx.wait();
+    if (!receipt) {
+        throw new Error('Deployment transaction failed');
+    }
+    let actualAddress = expectedAddress;
+    const deployedEvent = receipt.logs.find((log) => {
+        try {
+            const iface = new hre.ethers.Interface(['event Deployed(address indexed addr)']);
+            const parsed = iface.parseLog(log);
+            return parsed?.name === 'Deployed';
+        }
+        catch {
+            return false;
+        }
+    });
+    if (deployedEvent) {
+        const iface = new hre.ethers.Interface(['event Deployed(address indexed addr)']);
+        const parsed = iface.parseLog(deployedEvent);
+        actualAddress = parsed?.args[0];
+    }
+    if (actualAddress.toLowerCase() !== expectedAddress.toLowerCase()) {
+        console.warn(`Warning: Actual address ${actualAddress} does not match expected address ${expectedAddress}`);
+    }
+    return {
+        address: actualAddress,
+        txHash: receipt.hash,
+        deployTransaction: tx,
+        remoteDeploymentId: '',
+    };
+}
+async function deployViaMulticall(hre, multicallAddress, factoryAddress, salt, proxyBytecode, constructorArgs, expectedProxyAddress, initData, deployerAddress, shouldTransferOwnership, postDeployCalls = []) {
+    const [deployer] = await hre.ethers.getSigners();
+    const initCode = hre.ethers.concat([proxyBytecode, constructorArgs]);
+    const factoryInterface = new hre.ethers.Interface([
+        'function deploy(bytes32 salt, bytes memory initCode, bytes memory data, uint256 create2ForwardValue, uint256 callForwardValue) external payable returns (address deployed)',
+    ]);
+    const deployCallData = factoryInterface.encodeFunctionData('deploy', [salt, initCode, '0x', 0, 0]);
+    const multicall = await hre.ethers.getContractAt([
+        'function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calldata calls) external payable returns (tuple(bool success, bytes returnData)[] memory returnData)',
+    ], multicallAddress, deployer);
+    const calls = [
+        {
+            target: factoryAddress,
+            allowFailure: false,
+            callData: deployCallData,
+        },
+    ];
+    if (initData && initData !== '0x') {
+        calls.push({
+            target: expectedProxyAddress,
+            allowFailure: false,
+            callData: initData,
+        });
+    }
+    for (const postDeployCall of postDeployCalls || []) {
+        if (postDeployCall.value && postDeployCall.value !== '0' && postDeployCall.value !== '0x0') {
+            throw new Error('create2Factory.postDeployCalls does not support non-zero value with aggregate3');
+        }
+        calls.push({
+            target: !postDeployCall.target || postDeployCall.target === '$proxy'
+                ? expectedProxyAddress
+                : postDeployCall.target,
+            allowFailure: false,
+            callData: postDeployCall.data,
+        });
+    }
+    if (shouldTransferOwnership && deployerAddress) {
+        const ownableInterface = new hre.ethers.Interface(['function transferOwnership(address newOwner)']);
+        calls.push({
+            target: expectedProxyAddress,
+            allowFailure: false,
+            callData: ownableInterface.encodeFunctionData('transferOwnership', [deployerAddress]),
+        });
+    }
+    const tx = await multicall.aggregate3(calls, { value: 0 });
+    const receipt = await tx.wait();
+    if (!receipt) {
+        throw new Error('Multicall deployment transaction failed');
+    }
+    return {
+        address: expectedProxyAddress,
+        txHash: receipt.hash,
+        deployTransaction: tx,
+        remoteDeploymentId: '',
+    };
+}
 //# sourceMappingURL=deploy.js.map
\ No newline at end of file
diff --git a/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/options.d.ts b/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/options.d.ts
index ed9dd7a..7397e31 100644
--- a/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/options.d.ts
+++ b/node_modules/@openzeppelin/hardhat-upgrades/dist/utils/options.d.ts
@@ -14,6 +14,23 @@ export type DeployFactoryOpts = {
      * Allows to customize the deploy function used instead of utils/deploy.ts:deploy
      */
     deployFunction?: () => Promise<EthersOrDefenderDeployment>;
+    /**
+     * Use a CREATE2 factory for proxy deployment.
+     */
+    create2Factory?: {
+        address: string;
+        salt: string;
+        implementationAddress?: string;
+        implSalt?: string;
+        deployImpl?: boolean;
+        multicall?: string;
+        transferOwnership?: boolean;
+        postDeployCalls?: Array<{
+            target?: string;
+            data: string;
+            value?: string;
+        }>;
+    };
 };
 /**
  * Options for functions that can deploy an implementation contract.
diff --git a/node_modules/@openzeppelin/hardhat-upgrades/src/deploy-proxy.ts b/node_modules/@openzeppelin/hardhat-upgrades/src/deploy-proxy.ts
index b912102..f70ec44 100644
--- a/node_modules/@openzeppelin/hardhat-upgrades/src/deploy-proxy.ts
+++ b/node_modules/@openzeppelin/hardhat-upgrades/src/deploy-proxy.ts
@@ -3,6 +3,7 @@ import type { ContractFactory } from 'ethers';
 
 import {
   Manifest,
+  fetchOrDeployGetDeployment,
   logWarning,
   ProxyDeployment,
   BeaconProxyUnsupportedError,
@@ -21,11 +22,15 @@ import {
   deployProxyImpl,
   getInitializerData,
   getSigner,
+  deployViaCreate2Factory,
+  deployViaMulticall,
 } from './utils';
 import { enableDefender } from './defender/utils';
 import { getContractInstance } from './utils/contract-instance';
 import { getInitialOwner } from './utils/initial-owner';
 import { ContractTypeOfFactory } from './type-extensions';
+import { getDeployData } from './utils/deploy-impl';
+import { validateProxyImpl } from './utils/validate-impl';
 
 export interface DeployFunction {
   <F extends ContractFactory>(
@@ -52,7 +57,84 @@ export function makeDeployProxy(hre: HardhatRuntimeEnvironment, defenderModule:
     const { provider } = hre.network;
     const manifest = await Manifest.forNetwork(provider);
 
-    const { impl, kind } = await deployProxyImpl(hre, ImplFactory, opts);
+    let impl: string;
+    let kind = opts.kind;
+
+    if (opts.create2Factory?.implementationAddress) {
+      const deployData = await getDeployData(hre, ImplFactory, opts);
+      await validateProxyImpl(deployData, opts);
+
+      if (opts.kind === undefined) {
+        throw new Error('Broken invariant: Proxy kind is undefined');
+      }
+      kind = opts.kind;
+      impl = opts.create2Factory.implementationAddress;
+    } else if (opts.create2Factory && opts.create2Factory.deployImpl !== false) {
+      const deployData = await getDeployData(hre, ImplFactory, opts);
+      await validateProxyImpl(deployData, opts);
+
+      if (opts.kind === undefined) {
+        throw new Error('Broken invariant: Proxy kind is undefined');
+      }
+      kind = opts.kind;
+
+      const implSalt = opts.create2Factory.implSalt;
+      if (!implSalt) {
+        throw new Error('create2Factory implementation deployment requires an implementation salt');
+      }
+
+      const implBytecode = ImplFactory.bytecode;
+      const initCode = hre.ethers.concat([implBytecode, '0x']);
+      const expectedAddress = hre.ethers.getCreate2Address(
+        opts.create2Factory.address,
+        implSalt,
+        hre.ethers.keccak256(initCode),
+      );
+      const existingCode = await hre.ethers.provider.getCode(expectedAddress);
+      const implExists = existingCode !== '0x';
+
+      const deployment = await fetchOrDeployGetDeployment(
+        deployData.version,
+        deployData.provider,
+        async () => {
+          const abi = ImplFactory.interface.format(true);
+
+          if (implExists) {
+            return {
+              abi,
+              layout: deployData.layout,
+              address: expectedAddress,
+              txHash: undefined,
+            };
+          }
+
+          const implDeployment = await deployViaCreate2Factory(
+            hre,
+            opts.create2Factory!.address,
+            implSalt,
+            implBytecode,
+            '0x',
+          );
+
+          return {
+            abi,
+            layout: deployData.layout,
+            address: implDeployment.address,
+            txHash: implDeployment.txHash,
+            deployTransaction: implDeployment.deployTransaction,
+            remoteDeploymentId: implDeployment.remoteDeploymentId || '',
+          };
+        },
+        opts,
+        false,
+      );
+
+      impl = deployment.address;
+    } else {
+      const result = await deployProxyImpl(hre, ImplFactory, opts);
+      impl = result.impl;
+      kind = result.kind;
+    }
 
     const contractInterface = ImplFactory.interface;
     const data = getInitializerData(contractInterface, args, opts.initializer);
@@ -73,6 +155,70 @@ export function makeDeployProxy(hre: HardhatRuntimeEnvironment, defenderModule:
     }
 
     const signer = getSigner(ImplFactory.runner);
+    const deployCreate2Proxy = async (
+      artifactName: string,
+      constructorTypes: string[],
+      constructorValues: unknown[],
+    ): Promise<Required<ProxyDeployment> & DeployTransaction & RemoteDeploymentId> => {
+      if (!opts.create2Factory) {
+        throw new Error('create2Factory is required');
+      }
+
+      const proxyArtifact = await hre.artifacts.readArtifact(artifactName);
+      const proxyBytecode = proxyArtifact.bytecode;
+      const constructorArgs = hre.ethers.AbiCoder.defaultAbiCoder().encode(constructorTypes, constructorValues);
+      const proxyInitCode = hre.ethers.concat([proxyBytecode, constructorArgs]);
+      const expectedProxyAddress = hre.ethers.getCreate2Address(
+        opts.create2Factory.address,
+        opts.create2Factory.salt,
+        hre.ethers.keccak256(proxyInitCode),
+      );
+      const existingProxyCode = await hre.ethers.provider.getCode(expectedProxyAddress);
+
+      if (existingProxyCode !== '0x') {
+        return {
+          kind: kind!,
+          address: expectedProxyAddress,
+          txHash: '0x0000000000000000000000000000000000000000000000000000000000000000',
+          remoteDeploymentId: '',
+        };
+      }
+
+      if (opts.create2Factory.multicall) {
+        const deployerAddress = await signer.getAddress();
+        return {
+          kind: kind!,
+          ...(await deployViaMulticall(
+            hre,
+            opts.create2Factory.multicall,
+            opts.create2Factory.address,
+            opts.create2Factory.salt,
+            proxyBytecode,
+            constructorArgs,
+            expectedProxyAddress,
+            data,
+            deployerAddress,
+            opts.create2Factory.transferOwnership === true,
+            opts.create2Factory.postDeployCalls || [],
+          )),
+        };
+      }
+
+      if (opts.create2Factory.postDeployCalls?.length) {
+        throw new Error('create2Factory.postDeployCalls requires create2Factory.multicall');
+      }
+
+      return {
+        kind: kind!,
+        ...(await deployViaCreate2Factory(
+          hre,
+          opts.create2Factory.address,
+          opts.create2Factory.salt,
+          proxyBytecode,
+          constructorArgs,
+        )),
+      };
+    };
 
     let proxyDeployment: Required<ProxyDeployment> & DeployTransaction & RemoteDeploymentId;
     switch (kind) {
@@ -86,7 +232,15 @@ export function makeDeployProxy(hre: HardhatRuntimeEnvironment, defenderModule:
         }
 
         const ProxyFactory = opts.proxyFactory || (await getProxyFactory(hre, signer));
-        proxyDeployment = Object.assign({ kind }, await deployFn(hre, opts, ProxyFactory, impl, data));
+        if (opts.create2Factory) {
+          proxyDeployment = await deployCreate2Proxy(
+            '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy',
+            ['address', 'bytes'],
+            [impl, opts.create2Factory.multicall ? '0x' : data],
+          );
+        } else {
+          proxyDeployment = Object.assign({ kind }, await deployFn(hre, opts, ProxyFactory, impl, data));
+        }
         break;
       }
 
@@ -103,10 +257,18 @@ export function makeDeployProxy(hre: HardhatRuntimeEnvironment, defenderModule:
 
         const TransparentUpgradeableProxyFactory =
           opts.proxyFactory || (await getTransparentUpgradeableProxyFactory(hre, signer));
-        proxyDeployment = Object.assign(
-          { kind },
-          await deployFn(hre, opts, TransparentUpgradeableProxyFactory, impl, initialOwner, data),
-        );
+        if (opts.create2Factory) {
+          proxyDeployment = await deployCreate2Proxy(
+            '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy',
+            ['address', 'address', 'bytes'],
+            [impl, initialOwner, opts.create2Factory.multicall ? '0x' : data],
+          );
+        } else {
+          proxyDeployment = Object.assign(
+            { kind },
+            await deployFn(hre, opts, TransparentUpgradeableProxyFactory, impl, initialOwner, data),
+          );
+        }
         break;
       }
     }
diff --git a/node_modules/@openzeppelin/hardhat-upgrades/src/utils/deploy.ts b/node_modules/@openzeppelin/hardhat-upgrades/src/utils/deploy.ts
index 9543317..28f0866 100644
--- a/node_modules/@openzeppelin/hardhat-upgrades/src/utils/deploy.ts
+++ b/node_modules/@openzeppelin/hardhat-upgrades/src/utils/deploy.ts
@@ -45,3 +45,134 @@ async function ethersDeploy(
 
   return { address, txHash, deployTransaction };
 }
+
+export async function deployViaCreate2Factory(
+  hre: HardhatRuntimeEnvironment,
+  factoryAddress: string,
+  salt: string,
+  proxyBytecode: string,
+  constructorArgs: string,
+): Promise<EthersDeployment> {
+  const [deployer] = await hre.ethers.getSigners();
+  const initCode = hre.ethers.concat([proxyBytecode, constructorArgs]);
+  const expectedAddress = hre.ethers.getCreate2Address(factoryAddress, salt, hre.ethers.keccak256(initCode));
+  const factoryContract = await hre.ethers.getContractAt(
+    [
+      'function deploy(bytes32 salt, bytes memory initCode, bytes memory data, uint256 create2ForwardValue, uint256 callForwardValue) external payable returns (address deployed)',
+      'event Deployed(address indexed addr)',
+    ],
+    factoryAddress,
+    deployer,
+  );
+  const tx = await factoryContract.deploy(salt, initCode, '0x', 0, 0, { value: 0 });
+  const receipt = await tx.wait();
+
+  if (!receipt) {
+    throw new Error('Deployment transaction failed');
+  }
+
+  let actualAddress = expectedAddress;
+  const deployedEvent = receipt.logs.find((log: any) => {
+    try {
+      const iface = new hre.ethers.Interface(['event Deployed(address indexed addr)']);
+      const parsed = iface.parseLog(log);
+      return parsed?.name === 'Deployed';
+    } catch {
+      return false;
+    }
+  });
+
+  if (deployedEvent) {
+    const iface = new hre.ethers.Interface(['event Deployed(address indexed addr)']);
+    const parsed = iface.parseLog(deployedEvent);
+    actualAddress = parsed?.args[0];
+  }
+
+  if (actualAddress.toLowerCase() !== expectedAddress.toLowerCase()) {
+    console.warn(`Warning: Actual address ${actualAddress} does not match expected address ${expectedAddress}`);
+  }
+
+  return {
+    address: actualAddress,
+    txHash: receipt.hash,
+    deployTransaction: tx,
+    remoteDeploymentId: '',
+  };
+}
+
+export async function deployViaMulticall(
+  hre: HardhatRuntimeEnvironment,
+  multicallAddress: string,
+  factoryAddress: string,
+  salt: string,
+  proxyBytecode: string,
+  constructorArgs: string,
+  expectedProxyAddress: string,
+  initData: string,
+  deployerAddress?: string,
+  shouldTransferOwnership = false,
+  postDeployCalls: Array<{ target?: string; data: string; value?: string }> = [],
+): Promise<EthersDeployment> {
+  const [deployer] = await hre.ethers.getSigners();
+  const initCode = hre.ethers.concat([proxyBytecode, constructorArgs]);
+  const factoryInterface = new hre.ethers.Interface([
+    'function deploy(bytes32 salt, bytes memory initCode, bytes memory data, uint256 create2ForwardValue, uint256 callForwardValue) external payable returns (address deployed)',
+  ]);
+  const deployCallData = factoryInterface.encodeFunctionData('deploy', [salt, initCode, '0x', 0, 0]);
+  const multicall = await hre.ethers.getContractAt(
+    [
+      'function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calldata calls) external payable returns (tuple(bool success, bytes returnData)[] memory returnData)',
+    ],
+    multicallAddress,
+    deployer,
+  );
+  const calls = [
+    {
+      target: factoryAddress,
+      allowFailure: false,
+      callData: deployCallData,
+    },
+  ];
+
+  if (initData && initData !== '0x') {
+    calls.push({
+      target: expectedProxyAddress,
+      allowFailure: false,
+      callData: initData,
+    });
+  }
+
+  for (const postDeployCall of postDeployCalls || []) {
+    if (postDeployCall.value && postDeployCall.value !== '0' && postDeployCall.value !== '0x0') {
+      throw new Error('create2Factory.postDeployCalls does not support non-zero value with aggregate3');
+    }
+    calls.push({
+      target: !postDeployCall.target || postDeployCall.target === '$proxy' ? expectedProxyAddress : postDeployCall.target,
+      allowFailure: false,
+      callData: postDeployCall.data,
+    });
+  }
+
+  if (shouldTransferOwnership && deployerAddress) {
+    const ownableInterface = new hre.ethers.Interface(['function transferOwnership(address newOwner)']);
+    calls.push({
+      target: expectedProxyAddress,
+      allowFailure: false,
+      callData: ownableInterface.encodeFunctionData('transferOwnership', [deployerAddress]),
+    });
+  }
+
+  const tx = await multicall.aggregate3(calls, { value: 0 });
+  const receipt = await tx.wait();
+
+  if (!receipt) {
+    throw new Error('Multicall deployment transaction failed');
+  }
+
+  return {
+    address: expectedProxyAddress,
+    txHash: receipt.hash,
+    deployTransaction: tx,
+    remoteDeploymentId: '',
+  };
+}
diff --git a/node_modules/@openzeppelin/hardhat-upgrades/src/utils/options.ts b/node_modules/@openzeppelin/hardhat-upgrades/src/utils/options.ts
index 3ee7954..f3e3718 100644
--- a/node_modules/@openzeppelin/hardhat-upgrades/src/utils/options.ts
+++ b/node_modules/@openzeppelin/hardhat-upgrades/src/utils/options.ts
@@ -22,6 +22,20 @@ export type DeployFactoryOpts = {
    * Allows to customize the deploy function used instead of utils/deploy.ts:deploy
    */
   deployFunction?: () => Promise<EthersOrDefenderDeployment>;
+
+  /**
+   * Use a CREATE2 factory for proxy deployment.
+   */
+  create2Factory?: {
+    address: string;
+    salt: string;
+    implementationAddress?: string;
+    implSalt?: string;
+    deployImpl?: boolean;
+    multicall?: string;
+    transferOwnership?: boolean;
+    postDeployCalls?: Array<{ target?: string; data: string; value?: string }>;
+  };
 };
 
 /**
