Safe Singleton Factory

Factory contract for deploying Safe multisig wallets at deterministic addresses

The Safe Singleton Factory is a minimal proxy factory that enables deterministic deployment of Safe (formerly Gnosis Safe) multisig wallets and related contracts. It uses CREATE2 to ensure the same wallet addresses across all EVM chains.

Contract Address: 0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7 Deployment Status: Default preinstall

Key Features

  • Deterministic Deployment: Same Safe addresses across all chains

  • Minimal Implementation: Simple factory pattern using CREATE2

  • Version Agnostic: Deploy any version of Safe contracts

  • Gas Efficient: Optimized proxy deployment pattern

  • Ecosystem Standard: Used by Safe infrastructure globally

How It Works

The factory uses a two-step deployment process:

  1. Deploy Singleton: Deploy the Safe master copy (implementation)

  2. Deploy Proxy: Deploy minimal proxies pointing to the singleton

This pattern enables gas-efficient deployment of multiple Safe wallets sharing the same implementation.

Core Method

The factory has a single method that deploys contracts using CREATE2.

Usage Examples

Deploy a Safe Wallet

```javascript "Ethers.js Safe SDK Implementation" expandable import { ethers } from "ethers"; import { SafeFactory } from "@safe-global/safe-core-sdk";

const FACTORY_ADDRESS = "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7";

// Using Safe SDK async function deploySafeWallet(owners, threshold, signer) { const safeFactory = await SafeFactory.create({ ethAdapter: new EthersAdapter({ ethers, signer }), safeVersion: '1.4.1' }); const safeAccountConfig = { owners: owners, threshold: threshold, // Optional parameters fallbackHandler: "0x...", // Fallback handler address paymentToken: ethers.ZeroAddress, payment: 0, paymentReceiver: ethers.ZeroAddress }; // Predict address before deployment const predictedAddress = await safeFactory.predictSafeAddress(safeAccountConfig); console.log("Safe will be deployed to:", predictedAddress); // Deploy the Safe const safeSdk = await safeFactory.deploySafe({ safeAccountConfig }); const safeAddress = await safeSdk.getAddress(); console.log("Safe deployed to:", safeAddress); return safeSdk;

}

// Manual deployment without SDK async function deployManually(signer) { const factory = new ethers.Contract( FACTORY_ADDRESS, ["function deploy(bytes,bytes32) returns (address)"], signer ); // Prepare Safe proxy bytecode with initialization const proxyBytecode = "0x..."; // Safe proxy bytecode const salt = ethers.id("my-safe-v1"); // Deploy const tx = await factory.deploy(proxyBytecode, salt); const receipt = await tx.wait(); // Get deployed address from events const deployedAddress = receipt.logs[0].address; return deployedAddress;

}

Predict Safe Address

Calculate the deployment address before deploying:

Deploy with Custom Configuration

Deployment Patterns

Organization Wallets

Deploy consistent treasury addresses across chains:

Counterfactual Wallets

Create wallets that can receive funds before deployment:

Integration with Safe Ecosystem

Safe Modules

Deploy and enable Safe modules:

Safe Guards

Deploy transaction guards for additional security:

Best Practices

Salt Management

Version Control

Gas Optimization

  • Deploy singleton once per chain

  • Reuse proxy bytecode

  • Batch deployments when possible

  • Use minimal initializers

Security Considerations

  • Initialization: Ensure Safes are properly initialized after deployment

  • Salt Uniqueness: Use unique salts to prevent address collisions

  • Singleton Verification: Verify singleton contract before deployment

  • Access Control: The factory itself has no access control - anyone can deploy

Troubleshooting

Issue
Solution

Address mismatch

Verify salt and bytecode are identical

Deployment fails

Check sufficient gas and valid bytecode

Safe not working

Ensure proper initialization after deployment

Cross-chain inconsistency

Verify same singleton and salt used

Safe Infrastructure

Further Reading