The @eth-optimism/contracts package provides TypeScript utilities for interacting with Optimism smart contracts. These utilities help developers get contract artifacts, create contract instances, and access predeploy addresses.
function getContractDefinition(name: string): any;Gets the hardhat artifact for the given contract name. Returns an artifact object containing ABI and bytecode.
Parameters:
name (string): The name of the contract to get the artifact forReturns: Contract artifact with abi and bytecode properties
Throws: Error if the contract artifact is not found
Usage:
import { getContractDefinition } from "@eth-optimism/contracts";
const artifact = getContractDefinition("L1CrossDomainMessenger");
console.log(artifact.abi); // Contract ABI
console.log(artifact.bytecode); // Contract bytecodefunction getDeployedContractDefinition(
name: string,
network: string
): {
address: string;
abi: any;
};Gets the deployed contract artifact with address and ABI for a specific network.
Parameters:
name (string): The name of the deployed contractnetwork (string): The network name where the contract is deployedReturns: Object with address and abi properties
Throws: Error if the contract artifact is not found on the specified network
Usage:
import { getDeployedContractDefinition } from "@eth-optimism/contracts";
const deployed = getDeployedContractDefinition("L1CrossDomainMessenger", "mainnet");
console.log(deployed.address); // Contract address on mainnet
console.log(deployed.abi); // Contract ABIfunction getContractInterface(name: string): ethers.utils.Interface;Gets an ethers Interface instance for the given contract name. Useful for encoding/decoding function calls and parsing events.
Parameters:
name (string): The name of the contract to get the interface forReturns: ethers.utils.Interface instance
Usage:
import { getContractInterface } from "@eth-optimism/contracts";
import { ethers } from "ethers";
const interface = getContractInterface("L2CrossDomainMessenger");
// Encode function call
const calldata = interface.encodeFunctionData("sendMessage", [
targetAddress,
messageData,
gasLimit
]);
// Parse transaction receipt logs
const parsedLogs = receipt.logs.map(log => {
try {
return interface.parseLog(log);
} catch {
return null;
}
}).filter(Boolean);function getContractFactory(
name: string,
signer?: ethers.Signer
): ethers.ContractFactory;Gets an ethers ContractFactory instance for contract deployment.
Parameters:
name (string): The name of the contract to get the factory forsigner (ethers.Signer, optional): The signer to use for deployment transactionsReturns: ethers.ContractFactory instance ready for deployment
Usage:
import { getContractFactory } from "@eth-optimism/contracts";
import { ethers } from "ethers";
const signer = new ethers.Wallet(privateKey, provider);
const factory = getContractFactory("L1CrossDomainMessenger", signer);
// Deploy contract
const contract = await factory.deploy(addressManagerAddress);
await contract.deployed();
console.log("Contract deployed at:", contract.address);const predeploys: {
OVM_L2ToL1MessagePasser: "0x4200000000000000000000000000000000000000";
OVM_DeployerWhitelist: "0x4200000000000000000000000000000000000002";
L2CrossDomainMessenger: "0x4200000000000000000000000000000000000007";
OVM_GasPriceOracle: "0x420000000000000000000000000000000000000F";
L2StandardBridge: "0x4200000000000000000000000000000000000010";
OVM_SequencerFeeVault: "0x4200000000000000000000000000000000000011";
L2StandardTokenFactory: "0x4200000000000000000000000000000000000012";
OVM_L1BlockNumber: "0x4200000000000000000000000000000000000013";
WETH9: "0x4200000000000000000000000000000000000006";
OVM_ETH: "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000";
};Predefined addresses for L2 system contracts deployed at fixed locations.
Usage:
import { predeploys } from "@eth-optimism/contracts";
import { ethers } from "ethers";
// Connect to L2 Cross Domain Messenger
const l2Messenger = new ethers.Contract(
predeploys.L2CrossDomainMessenger,
messengerAbi,
l2Provider
);
// Connect to L2 Standard Bridge
const l2Bridge = new ethers.Contract(
predeploys.L2StandardBridge,
bridgeAbi,
l2Provider
);
// Access gas price oracle
const gasPriceOracle = new ethers.Contract(
predeploys.OVM_GasPriceOracle,
oracleAbi,
l2Provider
);const futurePredeploys: {
System0: "0x4200000000000000000000000000000000000042";
System1: "0x4200000000000000000000000000000000000014";
};Reserved addresses for future system contracts.
const names: {
managed: {
contracts: {
ChainStorageContainer_CTC_batches: "ChainStorageContainer-CTC-batches";
ChainStorageContainer_SCC_batches: "ChainStorageContainer-SCC-batches";
CanonicalTransactionChain: "CanonicalTransactionChain";
StateCommitmentChain: "StateCommitmentChain";
BondManager: "BondManager";
OVM_L1CrossDomainMessenger: "OVM_L1CrossDomainMessenger";
Proxy__OVM_L1CrossDomainMessenger: "Proxy__OVM_L1CrossDomainMessenger";
Proxy__OVM_L1StandardBridge: "Proxy__OVM_L1StandardBridge";
};
accounts: {
OVM_Sequencer: "OVM_Sequencer";
OVM_Proposer: "OVM_Proposer";
};
};
unmanaged: {
AddressDictator: "AddressDictator";
ChugSplashDictator: "ChugSplashDictator";
Lib_AddressManager: "Lib_AddressManager";
};
};Standard names used in the Address Manager and deployment artifacts.
interface DeployConfig {
isForkedNetwork?: boolean;
numDeployConfirmations?: number;
gasPrice?: number;
l1BlockTimeSeconds: number;
l2BlockGasLimit: number;
l2ChainId: number;
ctcL2GasDiscountDivisor: number;
ctcEnqueueGasCost: number;
sccFaultProofWindowSeconds: number;
sccFraudProofWindowSeconds: number;
l2SubmittedBlockTransactionGasLimit: number;
l1MessengerAddress: string;
l2MessengerAddress: string;
l1StandardBridgeAddress: string;
ovmSequencerAddress: string;
ovmProposerAddress: string;
bvmSequencerAddress: string;
bvmProposerAddress: string;
bvmBlockSignerAddress: string;
bvmFeeWalletAddress: string;
bvmAddressManagerOwner: string;
bvmGasPriceOracleOwner: string;
bvmWhitelistOwner: string;
bvmDeployerWhitelistOwner: string;
gasPriceOracleOverhead: number;
gasPriceOracleScalar: number;
gasPriceOracleDecimals: number;
gasPriceOracleL1BaseFee: number;
gasPriceOracleL2GasPrice: number;
l2GenesisBlockGasLimit: string;
l2GenesisBlockDifficulty: string;
l2GenesisBlockTimestamp: string;
l2GenesisRegolithTimeOffset: string;
}Configuration interface for deploying Optimism contracts with all required parameters for L1 and L2 setup.
import {
getContractInterface,
getContractFactory,
predeploys
} from "@eth-optimism/contracts";
import { ethers } from "ethers";
// Set up providers and signer
const l1Provider = new ethers.providers.JsonRpcProvider(L1_RPC_URL);
const l2Provider = new ethers.providers.JsonRpcProvider(L2_RPC_URL);
const signer = new ethers.Wallet(PRIVATE_KEY, l1Provider);
// Get contract interfaces
const l1MessengerInterface = getContractInterface("L1CrossDomainMessenger");
const l2MessengerInterface = getContractInterface("L2CrossDomainMessenger");
// Connect to deployed contracts
const l1Messenger = new ethers.Contract(
L1_MESSENGER_ADDRESS,
l1MessengerInterface,
signer
);
const l2Messenger = new ethers.Contract(
predeploys.L2CrossDomainMessenger,
l2MessengerInterface,
l2Provider
);
// Send message from L1 to L2
const tx = await l1Messenger.sendMessage(
targetL2Address,
encodedMessage,
gasLimit
);
console.log("Transaction hash:", tx.hash);import { getContractFactory, names } from "@eth-optimism/contracts";
import { ethers } from "ethers";
const signer = new ethers.Wallet(PRIVATE_KEY, provider);
// Deploy Address Manager
const addressManagerFactory = getContractFactory("Lib_AddressManager", signer);
const addressManager = await addressManagerFactory.deploy();
await addressManager.deployed();
// Deploy L1 Cross Domain Messenger
const l1MessengerFactory = getContractFactory("L1CrossDomainMessenger", signer);
const l1Messenger = await l1MessengerFactory.deploy();
await l1Messenger.deployed();
// Initialize the messenger
await l1Messenger.initialize(addressManager.address);
// Set address in manager using standard name
await addressManager.setAddress(
names.managed.contracts.OVM_L1CrossDomainMessenger,
l1Messenger.address
);