The deploy module provides utilities for computing deterministic deployment addresses using CREATE2 and working with CoW Protocol contract deployments.
Overview
CoW Protocol contracts are deployed deterministically using CREATE2, which means they have the same address across all EVM-compatible networks. This module helps compute these addresses before deployment.
Constants
SALT
The salt used for deterministic deployment.
Value: bytes32 encoding of “Mattresses in Berlin!”
This salt ensures deterministic addresses across all networks while being unique to CoW Protocol.
DEPLOYER_CONTRACT
The CREATE2 deployer contract address.
const DEPLOYER_CONTRACT = "0x4e59b44847b379578588920ca78fbf26c0b4956c";
CONTRACT_NAMES
Dictionary of deployed CoW Protocol contract names.
const CONTRACT_NAMES = {
authenticator: "GPv2AllowListAuthentication",
settlement: "GPv2Settlement",
} as const;
authenticator
string
default:"GPv2AllowListAuthentication"
The authenticator contract name.
settlement
string
default:"GPv2Settlement"
The settlement contract name.
Types
ContractName
Type representing a deployed contract name.
type ContractName = "GPv2AllowListAuthentication" | "GPv2Settlement";
DeploymentArguments
Type-safe deployment arguments for each contract.
type DeploymentArguments<T> =
T extends "GPv2AllowListAuthentication"
? never
: T extends "GPv2Settlement"
? [authenticator: string, vaultRelayer: string]
: unknown[];
This type ensures that you provide the correct constructor arguments for each contract:
GPv2AllowListAuthentication: No constructor arguments
GPv2Settlement: Requires authenticator address and vault relayer address
Abi
Allowed ABI definition types by Ethers.js.
type Abi = string | ReadonlyArray<Fragment | JsonFragment | string> | Interface;
ArtifactDeployment
Contract artifact information for deployment.
interface ArtifactDeployment {
abi: Abi;
bytecode: string;
}
The contract ABI in any format supported by Ethers.js.
The contract bytecode as a hex string.
NamedArtifactDeployment
Artifact with a contract name matching a deployed contract.
interface NamedArtifactDeployment<C extends ContractName>
extends ArtifactDeployment {
contractName: C;
}
The name of the contract being deployed.
Functions
deterministicDeploymentAddress
Computes the deterministic address where a contract will be deployed.
function deterministicDeploymentAddress<C>(
artifact: ArtifactDeployment | NamedArtifactDeployment<C>,
deploymentArguments: DeploymentArguments<C>
): string
artifact
ArtifactDeployment
required
The contract artifact containing ABI and bytecode.
deploymentArguments
DeploymentArguments<C>
required
Constructor arguments required for deployment. Type-checked based on contract name.
The deterministic address where the contract will be deployed. This address is the same across all networks.
Examples
Compute Settlement Contract Address
import {
deterministicDeploymentAddress,
CONTRACT_NAMES,
DeploymentArguments,
} from "@cowprotocol/contracts";
import settlementArtifact from "./artifacts/GPv2Settlement.json";
const authenticatorAddress = "0x1234567890123456789012345678901234567890";
const vaultRelayerAddress = "0x0987654321098765432109876543210987654321";
const settlementAddress = deterministicDeploymentAddress(
{
abi: settlementArtifact.abi,
bytecode: settlementArtifact.bytecode,
contractName: CONTRACT_NAMES.settlement,
},
[authenticatorAddress, vaultRelayerAddress]
);
console.log("Settlement will be deployed at:", settlementAddress);
Compute Authenticator Address
import {
deterministicDeploymentAddress,
CONTRACT_NAMES,
} from "@cowprotocol/contracts";
import authenticatorArtifact from "./artifacts/GPv2AllowListAuthentication.json";
// Authenticator has no constructor arguments
const authenticatorAddress = deterministicDeploymentAddress(
{
abi: authenticatorArtifact.abi,
bytecode: authenticatorArtifact.bytecode,
contractName: CONTRACT_NAMES.authenticator,
},
undefined as never // No arguments needed
);
console.log("Authenticator will be deployed at:", authenticatorAddress);
Compute Address for Custom Contract
import { deterministicDeploymentAddress } from "@cowprotocol/contracts";
import customContractArtifact from "./artifacts/CustomContract.json";
// For contracts not in CONTRACT_NAMES
const customAddress = deterministicDeploymentAddress(
{
abi: customContractArtifact.abi,
bytecode: customContractArtifact.bytecode,
},
[arg1, arg2, arg3] // Constructor arguments
);
console.log("Custom contract will be deployed at:", customAddress);
Verify Deployment Address
import {
deterministicDeploymentAddress,
CONTRACT_NAMES,
} from "@cowprotocol/contracts";
import { ethers } from "ethers";
// Compute expected address
const expectedAddress = deterministicDeploymentAddress(
settlementArtifact,
[authenticatorAddress, vaultRelayerAddress]
);
// Check if contract is deployed
const provider = new ethers.providers.JsonRpcProvider(rpcUrl);
const code = await provider.getCode(expectedAddress);
if (code === "0x") {
console.log("Contract not yet deployed at:", expectedAddress);
} else {
console.log("Contract already deployed at:", expectedAddress);
}
Deploy with Hardhat
import { deterministicDeploymentAddress } from "@cowprotocol/contracts";
import { ethers } from "hardhat";
async function deploy() {
// Get contract factory
const Settlement = await ethers.getContractFactory("GPv2Settlement");
// Compute expected address
const expectedAddress = deterministicDeploymentAddress(
{
abi: Settlement.interface.format(ethers.utils.FormatTypes.json),
bytecode: Settlement.bytecode,
},
[authenticatorAddress, vaultRelayerAddress]
);
console.log("Will deploy to:", expectedAddress);
// Deploy using CREATE2
const settlement = await Settlement.deploy(
authenticatorAddress,
vaultRelayerAddress
);
await settlement.deployed();
console.log("Deployed to:", settlement.address);
console.log("Matches expected:", settlement.address === expectedAddress);
}
How It Works
The deterministic address is computed using the CREATE2 formula:
address = keccak256(0xff ++ deployerAddress ++ salt ++ keccak256(initCode))[12:]
Where:
deployerAddress is the CREATE2 deployer contract
salt is the CoW Protocol deployment salt
initCode is the contract bytecode + encoded constructor arguments
Because the deployer address and salt are constant, and the bytecode is deterministic, the same contract with the same constructor arguments will always deploy to the same address on any EVM network.
Deployed Addresses
CoW Protocol contracts are deployed at the same addresses across all supported networks:
Mainnet, Gnosis Chain, Görli, etc.
- GPv2Settlement:
0x9008D19f58AAbD9eD0D60971565AA8510560ab41
- GPv2AllowListAuthentication: Address varies by network
Best Practices
- Always verify the computed address matches the expected deployment address
- Use the same bytecode and constructor arguments across all networks
- Test deployment on testnets before mainnet
- Keep track of deployed addresses for each network
Deterministic deployment makes it easier to:
- Maintain consistent addresses across networks
- Simplify multi-chain integration
- Predict contract addresses before deployment
- Verify deployment correctness
- Domain - Learn about creating domain objects with contract addresses
- Settlement - Learn about the settlement contract