Skip to content

Latest commit

 

History

History
209 lines (139 loc) · 6.6 KB

multichain-safe-deployment.mdx

File metadata and controls

209 lines (139 loc) · 6.6 KB

import { Steps } from 'nextra/components'

Multichain Safe Deployment

This guide will teach you how to replicate a Safe address across different chains using the Protocol Kit. This process includes initializing the Protocol Kit, configuring the Safes to deploy, predicting its address on different chains, and executing the deployment transactions.

Prerequisites

Install dependencies

First, you need to install the Protocol Kit.

{/* */}

pnpm add @safe-global/protocol-kit viem

{/* */}

Steps

Imports

Here are all the necessary imports for this guide.

{/* */}

import Safe, {
  PredictedSafeProps,
  SafeAccountConfig,
  SafeDeploymentConfig
} from '@safe-global/protocol-kit'
import { waitForTransactionReceipt } from 'viem/actions'
import { gnosisChiado, sepolia } from 'viem/chains'

{/* */}

Create a signer

You need a signer to instantiate the Protocol Kit. This example uses a private key to obtain a signer, but other EIP-1193 compatible signers are also supported. For detailed information about signers, please refer to the Protocol Kit reference.

{/* */}

const SIGNER_PRIVATE_KEY = // ...

{/* */}

Configure the Safe deployment

Define the predictedSafe object with the configuration for all the Safe accounts you will deploy. Check the reference to learn about all the different configuration options.

{/* */}

const safeAccountConfig: SafeAccountConfig = {
  owners: ['0x...', '0x...', '0x...'],
  threshold: 2
  // More optional properties
}

const predictedSafe: PredictedSafeProps = {
  safeAccountConfig
  // More optional properties
}

{/* */}

Initialize the Protocol Kit

Initialize an instance of the Protocol Kit for each network where you want to deploy a new Safe smart account by calling the init method. Pass the provider with its corresponding value depending on the network, the signer executing the deployment, and the predictedSafe with the Safe account configuration.

{/* */}

const protocolKitSepolia = await Safe.init({
  provider: sepolia.rpcUrls.default.http[0],
  signer: SIGNER_PRIVATE_KEY,
  predictedSafe
})

const protocolKitChiado = await Safe.init({
  provider: gnosisChiado.rpcUrls.default.http[0],
  signer: PRIVATE_KEY,
  predictedSafe
})

{/* */}

Predict the Safe addresses

You can predict the Safe addresses by calling the getAddress method from each Protocol Kit instance and ensure that the result addresses are the same.

{/* */}

const sepoliaPredictedSafeAddress = await protocolKitSepolia.getAddress()
const chiadoPredictedSafeAddress = await protocolKitChiado.getAddress()

{/* */}

Deployment on Sepolia

Create the deployment transaction to deploy a new Safe account in Sepolia by calling the createSafeDeploymentTransaction method.

{/* */}

const sepoliaDeploymentTransaction =
  await protocolKitSepolia.createSafeDeploymentTransaction()

{/* */}

Call the sendTransaction method from your Sepolia client instance and wait for the transaction to be executed.

{/* */}

const sepoliaClient =
  await protocolKitSepolia.getSafeProvider().getExternalSigner()

const transactionHashSepolia = await sepoliaClient!.sendTransaction({
  to: sepoliaDeploymentTransaction.to,
  value: BigInt(sepoliaDeploymentTransaction.value),
  data: sepoliaDeploymentTransaction.data as `0x${string}`,
  chain: sepolia
})

await waitForTransactionReceipt(
  sepoliaClient!,
  { hash: transactionHashSepolia }
)

{/* */}

Once the deployment transaction is executed, connect the new Safe address to the Protocol Kit instance by calling the connect method.

{/* */}

const newProtocolKitSepolia = await protocolKitSepolia.connect({
  safeAddress: sepoliaPredictedSafeAddress
})

const isSepoliaSafeDeployed = await newProtocolKitSepolia.isSafeDeployed() // True
const sepoliaDeployedSafeAddress = await newProtocolKitSepolia.getAddress()

{/* */}

If everything went well, isSepoliaSafeDeployed should be true, and the sepoliaDeployedSafeAddress should equal the sepoliaPredictedSafeAddress.

Deployment on Chiado

Repeat the same steps to deploy a Safe with the same configuration on Chiado testnet.

{/* */}

const chiadoDeploymentTransaction =
  await protocolKitChiado.createSafeDeploymentTransaction()

const chiadoClient =
  await protocolKitChiado.getSafeProvider().getExternalSigner()

const transactionHashChiado = await chiadoClient!.sendTransaction({
  to: chiadoDeploymentTransaction.to,
  value: BigInt(chiadoDeploymentTransaction.value),
  data: chiadoDeploymentTransaction.data as `0x${string}`,
  chain: gnosisChiado
})

await waitForTransactionReceipt(
  chiadoClient!,
  { hash: transactionHashChiado }
)

const newProtocolKitChiado = await protocolKitChiado.connect({
  safeAddress: chiadoPredictedSafeAddress
})

const isChiadoSafeDeployed = await newProtocolKitChiado.isSafeDeployed() // True
const chiadoDeployedSafeAddress = await newProtocolKitChiado.getAddress()

{/* */}

If everything went well, isChiadoSafeDeployed should be true, and the chiadoDeployedSafeAddress should equal the chiadoPredictedSafeAddress.

In addition, chiadoDeployedSafeAddress and sepoliaDeployedSafeAddress should have the same value.

Recap and further reading

After following this guide, you are able to deploy multiple Safe accounts with the same address on different chains using the Protocol Kit.