From e1d7f5d90f60d81df71b01ec0361c99cc8112664 Mon Sep 17 00:00:00 2001 From: Daniel Somoza Date: Tue, 15 Oct 2024 14:21:10 +0200 Subject: [PATCH] Add new safe-deployment guides --- pages/sdk/protocol-kit/guides/_meta.json | 1 + .../guides/safe-deployment/_meta.json | 4 + .../safe-deployment/address-replication.mdx | 173 ++++++++++++++++++ .../guides/safe-deployment/deploy-safe.mdx | 139 ++++++++++++++ 4 files changed, 317 insertions(+) create mode 100644 pages/sdk/protocol-kit/guides/safe-deployment/_meta.json create mode 100644 pages/sdk/protocol-kit/guides/safe-deployment/address-replication.mdx create mode 100644 pages/sdk/protocol-kit/guides/safe-deployment/deploy-safe.mdx diff --git a/pages/sdk/protocol-kit/guides/_meta.json b/pages/sdk/protocol-kit/guides/_meta.json index fbf6c77e9..8b9b21ba5 100644 --- a/pages/sdk/protocol-kit/guides/_meta.json +++ b/pages/sdk/protocol-kit/guides/_meta.json @@ -1,4 +1,5 @@ { + "safe-deployment": "Safe deployment", "execute-transactions": "Execute transactions", "signatures": "Signatures", "migrate-to-v1": "Migrate to v1", diff --git a/pages/sdk/protocol-kit/guides/safe-deployment/_meta.json b/pages/sdk/protocol-kit/guides/safe-deployment/_meta.json new file mode 100644 index 000000000..03efc3537 --- /dev/null +++ b/pages/sdk/protocol-kit/guides/safe-deployment/_meta.json @@ -0,0 +1,4 @@ +{ + "deploy-safe": "Deploy a Safe", + "address-replication": "Address replication" +} \ No newline at end of file diff --git a/pages/sdk/protocol-kit/guides/safe-deployment/address-replication.mdx b/pages/sdk/protocol-kit/guides/safe-deployment/address-replication.mdx new file mode 100644 index 000000000..6ac67eb48 --- /dev/null +++ b/pages/sdk/protocol-kit/guides/safe-deployment/address-replication.mdx @@ -0,0 +1,173 @@ +import { Steps } from "nextra/components"; + +# Safe Address Replication Across Chains + +In this guide, you will learn how to replicate a Safe address across different chains using the Protocol Kit. This process includes initializing the Protocol Kit, configuring the Safe, predicting the Safe address on different chains, and executing the deployment. + +We will demonstrate how to deploy a Safe account on both the Sepolia and Chiado chains with the same address using the Protocol Kit. + +For more detailed information, see the [Protocol Kit Reference](../../../protocol-kit/reference/safe.mdx). + +## Prerequisites + +- [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) + +## Install dependencies + +First, you need to install the Protocol Kit. + +```bash +pnpm add @safe-global/protocol-kit +``` + +## Steps + + + +### Imports + +Begin by importing the `Safe` class from the Protocol Kit and chain configuration from viem. + +{/* */} + +```typescript +import Safe, { SafeDeploymentConfig, SafeAccountConfig } from '@safe-global/protocol-kit' +import { waitForTransactionReceipt } from 'viem/actions' +import { sepolia, gnosisChiado } from 'viem/chains' +``` + +{/* */} + +### Create a signer + +Firstly, you need to get a signer to execute the deployment transaction in each chain. this example uses a private key, but any way to get an `EIP-1193` compatible signer can be used. + +{/* */} + +```typescript +const SIGNER_PRIVATE_KEY = // ... +``` + +{/* */} + +### Define the Safe Configuration + +{/* */} + +Define the configuration for your Safe. This includes the `owners`, `threshold`, deployment type, salt nonce for address predictability, and the version of the Safe. + +```typescript +// Safe account config +const safeAccountConfig: SafeAccountConfig = { + owners: ['0xOwnerAddress'], + threshold: 1 +} + +// Safe deployment config +const safeDeploymentConfig: SafeDeploymentConfig = { + deploymentType: 'canonical', + saltNonce: '12345', + safeVersion: '1.3.0' +} +``` + +{/* */} + +### Initialize the `ProtocolKit` for Sepolia and Chiado chain + +{/* */} + + +Initialize the Protocol Kit for deploying on Sepolia and Chiado. Set up the provider and signer along with the predicted Safe configuration. + +You can use the `getAddress` method to ensure that the Safe account has the same address across chains. + +```typescript + let protocolKitSepolia = await Safe.init({ + provider: sepolia.rpcUrls.default.http[0], + signer: SIGNER_PRIVATE_KEY, + predictedSafe: { + safeAccountConfig, + safeDeploymentConfig + } + }) + + let protocolKitChiado = await Safe.init({ + provider: gnosisChiado.rpcUrls.default.http[0], + signer: PRIVATE_KEY, + predictedSafe: { + safeAccountConfig, + safeDeploymentConfig + } + }) + + const safeAddressInSepolia = await protocolKitSepolia.getAddress() + const safeAddressInChiado = await protocolKitChiado.getAddress() + + console.log('safeAddressInSepolia: ', safeAddressInSepolia) + console.log('safeAddressInChiado: ', safeAddressInChiado) +``` + +{/* */} + +### Deploy the Safe on Sepolia + +Create and send the deployment transaction on Sepolia. + +{/* */} + +```typescript + const deploymentTransactionInSepolia = await protocolKitSepolia.createSafeDeploymentTransaction() + + const sepoliaClient = await protocolKitSepolia.getSafeProvider().getExternalSigner() + + const txHashSepolia = await sepoliaClient!.sendTransaction({ + to: deploymentTransactionInSepolia.to, + value: BigInt(deploymentTransactionInSepolia.value), + data: deploymentTransactionInSepolia.data as `0x${string}`, + chain: sepolia + }) + + await waitForTransactionReceipt(sepoliaClient!, { hash: txHashSepolia }) + + protocolKitSepolia = await protocolKitSepolia.connect({ safeAddress: safeAddressInSepolia }) + + // Confirm the Safe is deployed in Sepolia and fetch Safe info + console.log('Is Safe deployed:', await protocolKitSepolia.isSafeDeployed()) + console.log('Safe Address:', await protocolKitSepolia.getAddress()) +``` + +{/* */} + +### Repeat Deployment for Chiado + +Repeat the initialization and deployment for the Chiado chain using the same predictedSafe configuration to ensure the Safe address matches the one deployed on Sepolia. + +{/* */} + +```typescript + const deploymentTransactionInChiado = await protocolKitChiado.createSafeDeploymentTransaction() + + const chiadoClient = await protocolKitChiado.getSafeProvider().getExternalSigner() + + const txHashChiado = await chiadoClient!.sendTransaction({ + to: deploymentTransactionInChiado.to, + value: BigInt(deploymentTransactionInChiado.value), + data: deploymentTransactionInChiado.data as `0x${string}`, + chain: gnosisChiado + }) + + await waitForTransactionReceipt(chiadoClient!, { hash: txHashChiado }) + + protocolKitChiado = await protocolKitChiado.connect({ safeAddress: safeAddressInChiado }) + + // Confirm the Safe is deployed in Chiado and fetch properties + console.log('Is Safe deployed:', await protocolKitChiado.isSafeDeployed()) + console.log('Safe Address:', await protocolKitChiado.getAddress()) +``` + + + +## Recap and further reading + +By following this guide, you've learned how to deploy Safes with the same address on multiple chains using the Protocol Kit. diff --git a/pages/sdk/protocol-kit/guides/safe-deployment/deploy-safe.mdx b/pages/sdk/protocol-kit/guides/safe-deployment/deploy-safe.mdx new file mode 100644 index 000000000..658c42c97 --- /dev/null +++ b/pages/sdk/protocol-kit/guides/safe-deployment/deploy-safe.mdx @@ -0,0 +1,139 @@ +import { Steps } from 'nextra/components' + +# Deploy a Safe + +In this guide, you will learn how to deploy a new Safe using the Protocol Kit. This process includes initializing the Protocol Kit, setting up your Safe configuration, and executing the deployment. + +For more detailed information, see the [Protocol Kit Reference](../../../protocol-kit/reference/safe.mdx). + +## Prerequisites + +- [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) + +## Install dependencies + +First, you need to install the Protocol Kit. + +```bash +pnpm add @safe-global/protocol-kit +``` + +## Steps + + + + ### Imports + + Begin by importing the `Safe` class from the Protocol Kit. + + {/* */} + + ```typescript + import Safe from '@safe-global/protocol-kit' + ``` + + {/* */} + + ### Create a signer + + Firstly, you need to get a signer, this example uses a private key, but any way to get an `EIP-1193` compatible signer can be used. + + {/* */} + + ```typescript + const SIGNER_PRIVATE_KEY = // ... + const RPC_URL = 'https://rpc.ankr.com/eth_sepolia' + ``` + + {/* */} + + ### Initialize the `ProtocolKit` + + {/* */} + + Initialize the Protocol Kit with the `provider`, `signer`, and the `predictedSafe` configuration. + + ```typescript + // Define your Safe configuration + const predictedSafe = { + safeAccountConfig: { + owners: ['0xOwner1', '0xOwner2', '0xOwner3'], // In this example, 3 owners + threshold: 2 // Requires at least 2 signatures to approve a transaction + } + } + + // Initialize the Protocol Kit with the predictedSafe + const protocolKit = await Safe.init({ + provider: RPC_URL, + signer: SIGNER_PRIVATE_KEY, + predictedSafe + }) + ``` + + {/* */} + + ### Predict your Safe address + + you can predict your Safe address using the `getAddress` method in the Protocol Kit. + + {/* */} + + ```typescript + const safeAddress = await protocolKit.getAddress() + ``` + + {/* */} + + ### Create the deployement transaction + + Now, generate the transaction to deploy the Safe and execute it using the Protocol Kit. + + {/* */} + + ```typescript + const deploymentTransaction = await protocolKit.createSafeDeploymentTransaction() + ``` + + {/* */} + + ### Execute the deployement transaction + + You can execute the deployement transaction using the integrated signer or your preferred external Ethereum client. + + {/* */} + + ```typescript + const client = await protocolKit.getSafeProvider().getExternalSigner() + + const txHash = await client.sendTransaction({ + to: deploymentTransaction.to, + value: BigInt(deploymentTransaction.value), + data: deploymentTransaction.data as `0x${string}`, + chain: sepolia + }) + + const txReceipt = await client.waitForTransactionReceipt({ hash: txHash }) + ``` + + ### Reconnect the `protocolKit` to the newly deployed Safe + +Once the deployment transaction has been successfully executed, it's necessary to reconnect your Protocol Kit instance to the address of the newly created Safe using the `connect` Method + +```typescript +// Reconnect to the newly deployed Safe using the protocol-kit +protocolKit = await protocolKit.connect({ safeAddress }) + +// Confirm the Safe is deployed and fetch properties +console.log("Is Safe deployed:", await protocolKit.isSafeDeployed()) +console.log("Safe Address:", await protocolKit.getAddress()) +console.log("Safe Owners:", await protocolKit.getOwners()) +console.log("Safe Threshold:", await protocolKit.getThreshold()) +``` + + + + + +## Recap and further reading + +After following this guide, you are able to deploy new Safe accounts with the Protocol Kit.