> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cosmos.network/llms.txt
> Use this file to discover all available pages before exploring further.

# 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
**Repository**: [github.com/safe-global/safe-singleton-factory](https://github.com/safe-global/safe-singleton-factory)

<Warning>
  **Known Issue - Bytecode Verification Required**

  The Safe Singleton Factory bytecode in the current `DefaultPreinstalls` ([x/vm/types/preinstall.go:30-32](https://github.com/cosmos/evm/blob/main/x/vm/types/preinstall.go#L30-L32)) is currently **identical to the Create2 factory bytecode**, which is incorrect.

  Before deploying this contract in production:

  1. Verify the correct Safe Singleton Factory bytecode from the [official repository](https://github.com/safe-global/safe-singleton-factory)
  2. Update your genesis configuration with the correct bytecode
  3. Test the deployment on a testnet first

  This issue is tracked and will be addressed in a future release. For now, you should manually verify and update the bytecode if you need Safe Factory functionality.
</Warning>

## 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

```solidity theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
function deploy(bytes memory data, bytes32 salt)
    returns (address deploymentAddress)
```

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

## Usage Examples

### Deploy a Safe Wallet

<CodeGroup>
  ```javascript "Ethers.js Safe SDK Implementation" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  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;
  }
  ```

  ```solidity "Solidity Safe Deployer Contract" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
  // SPDX-License-Identifier: MIT
  pragma solidity ^0.8.0;

  interface ISafeFactory {
      function deploy(bytes memory code, bytes32 salt)
          external returns (address);
  }

  contract SafeDeployer {
      ISafeFactory constant factory = ISafeFactory(
          0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7
      );

      function deploySafe(
          address safeSingleton,
          bytes memory initializer,
          uint256 saltNonce
      ) external returns (address safe) {
          // Prepare proxy creation code
          bytes memory deploymentData = abi.encodePacked(
              getProxyCreationCode(),
              uint256(uint160(safeSingleton))
          );

          // Calculate salt
          bytes32 salt = keccak256(abi.encodePacked(
              keccak256(initializer),
              saltNonce
          ));

          // Deploy via factory
          safe = factory.deploy(deploymentData, salt);

          // Initialize the Safe
          (bool success,) = safe.call(initializer);
          require(success, "Safe initialization failed");
      }

      function getProxyCreationCode() pure returns (bytes memory) {
          // Safe proxy bytecode
          return hex"608060405234801561001057600080fd5b50...";
      }
  }
  ```
</CodeGroup>

### Predict Safe Address

Calculate the deployment address before deploying:

```javascript theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
function predictSafeAddress(owners, threshold, saltNonce) {
  const initializer = encodeSafeSetup(owners, threshold);
  const salt = ethers.solidityPackedKeccak256(
    ["bytes32", "uint256"],
    [ethers.keccak256(initializer), saltNonce]
  );

  const initCode = ethers.concat([
    PROXY_CREATION_CODE,
    ethers.AbiCoder.defaultAbiCoder().encode(["address"], [SAFE_SINGLETON])
  ]);

  const deploymentAddress = ethers.getCreate2Address(
    FACTORY_ADDRESS,
    salt,
    ethers.keccak256(initCode)
  );

  return deploymentAddress;
}
```

### Deploy with Custom Configuration

```javascript "Deploy Safe with Custom Configuration" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
async function deployCustomSafe(config, signer) {
  const {
    owners,
    threshold,
    modules = [],
    guards = [],
    fallbackHandler
  } = config;

  // Encode initialization data
  const setupData = safeSingleton.interface.encodeFunctionData("setup", [
    owners,
    threshold,
    ethers.ZeroAddress, // to
    "0x",               // data
    fallbackHandler,
    ethers.ZeroAddress, // paymentToken
    0,                  // payment
    ethers.ZeroAddress  // paymentReceiver
  ]);

  // Deploy proxy pointing to singleton
  const proxyFactory = new ethers.Contract(
    PROXY_FACTORY_ADDRESS,
    proxyFactoryAbi,
    signer
  );

  const tx = await proxyFactory.createProxyWithNonce(
    SAFE_SINGLETON_ADDRESS,
    setupData,
    Date.now() // saltNonce
  );

  const receipt = await tx.wait();
  const safeAddress = getSafeAddressFromReceipt(receipt);

  // Enable modules if specified
  for (const module of modules) {
    await enableModule(safeAddress, module, signer);
  }

  return safeAddress;
}
```

## Deployment Patterns

### Organization Wallets

Deploy consistent treasury addresses across chains:

```javascript "Deploy Organization Treasury Across Chains" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
async function deployOrgTreasury(orgId, chains) {
  const salt = ethers.id(`org-treasury-${orgId}`);
  const results = {};

  for (const chain of chains) {
    const provider = new ethers.JsonRpcProvider(chain.rpc);
    const signer = new ethers.Wallet(deployerKey, provider);

    // Same salt = same address on all chains
    const address = await deploySafeWithSalt(salt, signer);
    results[chain.name] = address;
  }

  return results;
}
```

### Counterfactual Wallets

Create wallets that can receive funds before deployment:

```javascript "Counterfactual Safe Class Implementation" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
class CounterfactualSafe {
  constructor(owners, threshold) {
    this.owners = owners;
    this.threshold = threshold;
    this.address = this.predictAddress();
  }

  predictAddress() {
    // Calculate address without deploying
    return predictSafeAddress(
      this.owners,
      this.threshold,
      0 // saltNonce
    );
  }

  async deploy(signer) {
    // Only deploy when needed
    const code = await signer.provider.getCode(this.address);
    if (code !== "0x") {
      console.log("Already deployed");
      return this.address;
    }

    return deploySafeWallet(
      this.owners,
      this.threshold,
      signer
    );
  }
}
```

## Integration with Safe Ecosystem

### Safe Modules

Deploy and enable Safe modules:

```javascript "Safe Module Deployment and Configuration" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// Deploy module via factory
async function deployModule(moduleCode, salt) {
  const tx = await factory.deploy(moduleCode, salt);
  const receipt = await tx.wait();
  return receipt.contractAddress;
}

// Enable module on Safe
async function enableModule(safeAddress, moduleAddress, signer) {
  const safe = new ethers.Contract(safeAddress, safeAbi, signer);
  const tx = await safe.enableModule(moduleAddress);
  await tx.wait();
}
```

### Safe Guards

Deploy transaction guards for additional security:

```javascript "Deploy and Set Safe Transaction Guard" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
async function deployAndSetGuard(safeAddress, guardCode, signer) {
  // Deploy guard
  const salt = ethers.id(`guard-${safeAddress}`);
  const guardAddress = await factory.deploy(guardCode, salt);

  // Set as Safe guard
  const safe = new ethers.Contract(safeAddress, safeAbi, signer);
  const tx = await safe.setGuard(guardAddress);
  await tx.wait();

  return guardAddress;
}
```

## Best Practices

### Salt Management

```javascript "Structured Salt Generation Patterns" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// Structured salt generation
function generateSalt(context, nonce) {
  return ethers.solidityPackedKeccak256(
    ["string", "uint256"],
    [context, nonce]
  );
}

// Examples
const userSalt = generateSalt(`user-${userId}`, 0);
const orgSalt = generateSalt(`org-${orgId}`, iteration);
const appSalt = generateSalt(`app-${appId}-${version}`, 0);
```

### Version Control

```javascript "Safe Version Management" expandable theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
const SAFE_VERSIONS = {
  "1.3.0": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552",
  "1.4.0": "0x41675C099F32341bf84BFc5382aF534df5C7461a",
  "1.4.1": "0x29fcB43b46531BcA003ddC8FCB67FFE91900C762"
};

async function deploySafeVersion(version, owners, threshold) {
  const singleton = SAFE_VERSIONS[version];
  if (!singleton) throw new Error(`Unknown version: ${version}`);

  return deployWithSingleton(singleton, owners, threshold);
}
```

### 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           |

## Related Contracts

### Safe Infrastructure

```javascript theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
const SAFE_CONTRACTS = {
  factory: "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7",
  singleton_1_4_1: "0x29fcB43b46531BcA003ddC8FCB67FFE91900C762",
  proxyFactory: "0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67",
  multiSend: "0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526",
  fallbackHandler: "0xfd0732Dc9E303f09fCEf3a7388Ad10A83459Ec99"
};
```

## Further Reading

* [Safe Documentation](https://docs.safe.global/)
* [Safe Singleton Factory](https://github.com/safe-global/safe-singleton-factory)
* [Safe Contracts](https://github.com/safe-global/safe-contracts)
* [Safe SDK](https://github.com/safe-global/safe-core-sdk)
