Contract deployment functionality supporting both JSON artifacts and TypeChain factories with full type safety, flexible deployment options, and comprehensive contract format support.
Main deployment function that handles both JSON contract artifacts and TypeChain factory classes with full type safety and deployment option customization.
/**
* Deploy smart contracts from JSON artifacts or TypeChain factories
* @param wallet - Wallet or Signer to deploy the contract with
* @param factoryOrContractJson - Contract factory class or JSON artifact
* @param args - Constructor arguments for the contract
* @param overrideOptions - Transaction options to override defaults
* @returns Promise resolving to deployed contract instance
*/
function deployContract<T extends ContractFactoryOrJSON>(
wallet: Wallet | Signer,
factoryOrContractJson: T,
args?: DeployArgumentsOf<T>,
overrideOptions?: providers.TransactionRequest
): Promise<ContractTypeOf<T>>;Usage Examples:
import { deployContract } from "ethereum-waffle";
import { ethers } from "ethers";
// Deploy from JSON artifact
const tokenJson = require("./artifacts/Token.json");
const token = await deployContract(wallet, tokenJson, [
"Test Token", // name
"TEST", // symbol
1000 // initial supply
]);
// Deploy with custom transaction options
const contract = await deployContract(
wallet,
contractJson,
[constructorArg],
{
gasLimit: 2000000,
gasPrice: ethers.utils.parseUnits("20", "gwei")
}
);
// Deploy from TypeChain factory (when available)
import { MyContract__factory } from "./typechain";
const factory = new MyContract__factory(wallet);
const contract = await deployContract(wallet, factory, [arg1, arg2]);Type definitions supporting multiple contract artifact formats from different Solidity compilers and tools.
/**
* Standard contract JSON format from solc output
*/
interface StandardContractJSON {
abi: any;
evm: {
bytecode: {
object: any;
};
};
}
/**
* Simple contract JSON format with direct abi and bytecode
*/
interface SimpleContractJSON {
abi: any[];
bytecode: string;
}
/**
* Union type supporting both contract JSON formats
*/
type ContractJSON = StandardContractJSON | SimpleContractJSON;
/**
* Type guard to check if contract JSON is standard format
* @param data - Contract JSON to check
* @returns True if data is StandardContractJSON
*/
function isStandard(data: ContractJSON): data is StandardContractJSON;
/**
* Check if contract has deployment bytecode
* @param bytecode - Bytecode object or string to check
* @returns True if bytecode is not empty
*/
function hasByteCode(bytecode: {object: any} | string): boolean;Usage Examples:
import { isStandard, hasByteCode } from "ethereum-waffle";
// Check contract format
const contractJson = require("./artifacts/Contract.json");
if (isStandard(contractJson)) {
console.log("Standard solc format");
const bytecode = contractJson.evm.bytecode;
} else {
console.log("Simple format");
const bytecode = contractJson.bytecode;
}
// Verify contract can be deployed
if (!hasByteCode(contractJson.bytecode)) {
throw new Error("Cannot deploy contract with empty bytecode");
}Advanced TypeScript types that provide full type safety when deploying contracts with different input formats.
/**
* Type for constructor arguments based on input type
*/
type DeployArgumentsOf<T> = T extends Newable<infer U>
? (U extends ContractFactory ? Parameters<U['deploy']> : never)
: any[];
/**
* Type for deployed contract based on input type
*/
type ContractTypeOf<T> = T extends Newable<infer U>
? (U extends ContractFactory ? ReturnType<U['deploy']> : never)
: Contract;
/**
* Union type for deployment input
*/
type ContractFactoryOrJSON = Newable<ContractFactory> | ContractJSON;
/**
* Type constructor interface
*/
type Newable<T> = { new(...args: any): T };Usage Examples:
import { deployContract, ContractJSON } from "ethereum-waffle";
import { MyContract__factory } from "./typechain";
// TypeScript infers correct types automatically
const tokenJson: ContractJSON = require("./Token.json");
const token = await deployContract(wallet, tokenJson, ["name", "symbol"]);
// token is typed as Contract
const factory = new MyContract__factory(wallet);
const typedContract = await deployContract(wallet, factory, [42]);
// typedContract is typed as MyContract (return type of factory.deploy())
// Constructor arguments are type-checked
const wrongArgs = await deployContract(wallet, factory, ["string"]); // TS Error!The deployment function handles different input types and deployment scenarios automatically:
Internal Process Examples:
// For JSON artifacts
async function deployFromJson(
wallet: Signer,
contractJson: ContractJSON,
args: any[],
overrideOptions: providers.TransactionRequest
) {
const bytecode = isStandard(contractJson)
? contractJson.evm.bytecode
: contractJson.bytecode;
if (!hasByteCode(bytecode)) {
throw new Error('Cannot deploy contract with empty bytecode');
}
const factory = new ContractFactory(
contractJson.abi,
bytecode,
wallet
);
const contract = await factory.deploy(...args, overrideOptions);
await contract.deployed();
return contract;
}
// For TypeChain factories
if (isFactory(factoryOrContractJson)) {
const Factory = factoryOrContractJson;
const contractFactory = new Factory(wallet);
const contract = await contractFactory.deploy(...args, overrideOptions);
await contract.deployed();
return contract;
}