The proxy module provides utilities for working with EIP-1967 and EIP-173 proxy contracts used by the CoW Protocol deployment system.
Functions
implementationAddress
Retrieves the implementation address from an EIP-1967 compatible proxy contract.
provider
ethers.providers.Provider
required
Ethers.js provider for reading blockchain state
Address of the proxy contract to inspect
The address of the implementation contract
import { implementationAddress } from "@cowprotocol/contracts" ;
import { ethers } from "ethers" ;
const provider = new ethers . providers . JsonRpcProvider ( "https://rpc.gnosis.gateway.fm" );
const proxyAddress = "0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE" ;
const implementation = await implementationAddress ( provider , proxyAddress );
console . log ( "Implementation:" , implementation );
ownerAddress
Retrieves the admin/owner address from an EIP-1967 compatible proxy contract.
provider
ethers.providers.Provider
required
Ethers.js provider for reading blockchain state
Address of the proxy contract to inspect
The address of the proxy administrator
import { ownerAddress } from "@cowprotocol/contracts" ;
const owner = await ownerAddress ( provider , proxyAddress );
console . log ( "Proxy owner:" , owner );
Constants
EIP173_PROXY_ABI
Human-readable ABI for EIP-173 proxy contracts. This ABI includes the ownership management interface.
export const EIP173_PROXY_ABI = [
"event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)" ,
"function owner() view external returns(address)" ,
"function transferOwnership(address newOwner) external" ,
"function supportsInterface(bytes4 interfaceID) external view returns (bool)" ,
];
Utility Functions
proxyInterface
Creates an Ethers.js contract instance for interacting with the proxy admin interface.
An Ethers.js contract instance for the proxy
Contract instance with EIP-173 proxy ABI attached
import { proxyInterface } from "@cowprotocol/contracts" ;
import { ethers } from "ethers" ;
// Get the implementation contract
const authenticator = new ethers . Contract (
"0x2c4c28DDBdAc9C5E7055b4C863b72eA0149D8aFE" ,
authenticatorAbi ,
signer
);
// Get the proxy interface for admin operations
const proxy = proxyInterface ( authenticator );
// Check current owner
const currentOwner = await proxy . owner ();
// Transfer ownership (requires current owner signer)
await proxy . transferOwnership ( "0xNewOwnerAddress..." );
EIP-1967 Storage Slots
The module internally uses EIP-1967 standard storage slots:
Implementation slot : keccak256("eip1967.proxy.implementation") - 1
Admin slot : keccak256("eip1967.proxy.admin") - 1
These slots are used to read the implementation and admin addresses from proxy contract storage without requiring function calls.
Use Cases
Verify Proxy Configuration
import { implementationAddress , ownerAddress } from "@cowprotocol/contracts" ;
import { ethers } from "ethers" ;
async function verifyProxy ( provider : ethers . providers . Provider , proxyAddr : string ) {
const implementation = await implementationAddress ( provider , proxyAddr );
const owner = await ownerAddress ( provider , proxyAddr );
console . log ( `Proxy: ${ proxyAddr } ` );
console . log ( `Implementation: ${ implementation } ` );
console . log ( `Owner: ${ owner } ` );
return { implementation , owner };
}
Transfer Proxy Ownership
import { proxyInterface } from "@cowprotocol/contracts" ;
import { ethers } from "ethers" ;
async function transferProxyOwnership (
proxyContract : ethers . Contract ,
newOwner : string
) {
const proxy = proxyInterface ( proxyContract );
// Verify current ownership
const currentOwner = await proxy . owner ();
console . log ( "Current owner:" , currentOwner );
// Transfer ownership (requires signer to be current owner)
const tx = await proxy . transferOwnership ( newOwner );
await tx . wait ();
console . log ( "Ownership transferred to:" , newOwner );
}
Deploy Module Deterministic deployment utilities
Authentication Contract Proxy-based authenticator contract