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

# Implementation Guide

> Deploying and managing predeployed contracts on Cosmos EVM

<Note>
  For conceptual understanding of predeployed contracts and how they differ from precompiles, see the [Predeployed Contracts concept page](/evm/v0.4.x/documentation/concepts/predeployed-contracts).
</Note>

## Activation Methods

There are three primary methods to deploy preinstalled contracts on a Cosmos EVM chain:

### 1. Genesis Configuration

The most straightforward method for new chains or testnets. Contracts are deployed when the chain is first initialized.

#### Default Configuration

Using the evmd example application automatically includes default preinstalls:

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// evmd/genesis.go
func NewEVMGenesisState() *evmtypes.GenesisState {
    evmGenState := evmtypes.DefaultGenesisState()
    evmGenState.Params.ActiveStaticPrecompiles = evmtypes.AvailableStaticPrecompiles
    evmGenState.Preinstalls = evmtypes.DefaultPreinstalls
    return evmGenState
}
```

#### Custom Genesis Configuration

To customize which contracts are deployed:

```json theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// genesis.json
{
  "app_state": {
    "evm": {
      "preinstalls": [
        {
          "name": "Create2",
          "address": "0x4e59b44847b379578588920ca78fbf26c0b4956c",
          "code": "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"
        },
        {
          "name": "Multicall3",
          "address": "0xcA11bde05977b3631167028862bE2a173976CA11",
          "code": "0x6080604052..." // Full bytecode
        }
      ]
    }
  }
}
```

#### Local Development

The `local_node.sh` script automatically configures default preinstalls:

```bash theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
./local_node.sh
# Automatically deploys all default preinstalls
```

### 2. Governance Proposal

For chains already in production, use the `MsgRegisterPreinstalls` governance proposal:

#### Proposal Structure

<Note>
  The `authority` field must be set to the governance module account address, which is typically derived from the gov module name. This is usually something like `cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn` for the standard gov module.
</Note>

```json theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
{
  "messages": [
    {
      "@type": "/cosmos.evm.vm.v1.MsgRegisterPreinstalls",
      "authority": "[gov module account address]",
      "preinstalls": [
        {
          "name": "Multicall3",
          "address": "0xcA11bde05977b3631167028862bE2a173976CA11",
          "code": "0x6080604052..."
        }
      ]
    }
  ],
  "metadata": "ipfs://CID",
  "deposit": "10000000stake",
  "title": "Deploy Multicall3 Contract",
  "summary": "Deploy the Multicall3 contract to enable batched calls"
}
```

#### Submission Process

```bash theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
# Submit proposal
evmd tx gov submit-proposal proposal.json \
  --from mykey \
  --chain-id cosmosevm_9001-1 \
  --gas auto

# Vote on proposal
evmd tx gov vote 1 yes --from mykey
```

### 3. Chain Upgrade Handler

Include predeployed contracts as part of a coordinated chain upgrade:

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
func CreateUpgradeHandler(
    mm *module.Manager,
    configurator module.Configurator,
    evmKeeper *evmkeeper.Keeper,
) upgradetypes.UpgradeHandler {
    return func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
        // Add preinstalls during upgrade
        if err := evmKeeper.AddPreinstalls(ctx, evmtypes.DefaultPreinstalls); err != nil {
            return nil, err
        }

        return mm.RunMigrations(ctx, configurator, fromVM)
    }
}
```

## Implementation Details

### Validation Process

All preinstall deployments undergo strict validation:

1. **Address Validation**
   * Must be valid Ethereum address format (40 hex characters)
   * Cannot conflict with existing contracts
   * Should not overlap with precompile reserved addresses (typically 0x1-0x9FF)

2. **Code Validation**
   * Must be valid EVM bytecode (hex encoded)
   * Cannot have empty code hash
   * Must pass bytecode verification

3. **Conflict Prevention**
   * Checks for existing contracts at target address
   * Validates against account keeper for existing accounts
   * Ensures no code hash conflicts with different bytecode

### Storage and State

Predeployed contracts are stored in the chain state like regular contracts:

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// Actual deployment process from x/vm/keeper/preinstalls.go
func (k *Keeper) AddPreinstalls(ctx sdk.Context, preinstalls []types.Preinstall) error {
    for _, preinstall := range preinstalls {
        address := common.HexToAddress(preinstall.Address)
        accAddress := sdk.AccAddress(address.Bytes())

        if len(preinstall.Code) == 0 {
            return errorsmod.Wrapf(types.ErrInvalidPreinstall,
                "preinstall %s has no code", preinstall.Address)
        }

        codeHash := crypto.Keccak256Hash(common.FromHex(preinstall.Code)).Bytes()
        if types.IsEmptyCodeHash(codeHash) {
            return errorsmod.Wrapf(types.ErrInvalidPreinstall,
                "preinstall %s has empty code hash", preinstall.Address)
        }

        // Check for existing code hash conflicts
        existingCodeHash := k.GetCodeHash(ctx, address)
        if !types.IsEmptyCodeHash(existingCodeHash.Bytes()) &&
           !bytes.Equal(existingCodeHash.Bytes(), codeHash) {
            return errorsmod.Wrapf(types.ErrInvalidPreinstall,
                "preinstall %s already has a different code hash", preinstall.Address)
        }

        // Check that the account is not already set
        if acc := k.accountKeeper.GetAccount(ctx, accAddress); acc != nil {
            return errorsmod.Wrapf(types.ErrInvalidPreinstall,
                "preinstall %s already has an account in account keeper", preinstall.Address)
        }

        // Create account and store code
        account := k.accountKeeper.NewAccountWithAddress(ctx, accAddress)
        k.accountKeeper.SetAccount(ctx, account)
        k.SetCodeHash(ctx, address.Bytes(), codeHash)
        k.SetCode(ctx, codeHash, common.FromHex(preinstall.Code))
    }
    return nil
}
```

## Verification and Testing

### Verify Deployment

After deployment, verify contracts are properly installed:

```bash theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
# Query contract code via CLI
evmd query evm code 0x4e59b44847b379578588920ca78fbf26c0b4956c

# Check account exists
evmd query evm account 0x4e59b44847b379578588920ca78fbf26c0b4956c
```

```javascript theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// Verify via Web3
const code = await provider.getCode("0x4e59b44847b379578588920ca78fbf26c0b4956c");
console.log("Deployed:", code !== "0x");
```

### Testing Strategy

1. **Local Testing**: Deploy on local node first
2. **Testnet Validation**: Test governance proposal process
3. **Integration Testing**: Verify interactions with other contracts
4. **Gas Analysis**: Monitor gas consumption patterns
5. **Security Audit**: Review bytecode before mainnet deployment

## Best Practices

### Security Considerations

* **Bytecode Verification**: Always verify that bytecode matches official releases
* **Address Selection**: Ensure addresses don't conflict with future plans
* **Audit Requirements**: Even well-known contracts should be reviewed
* **Immutability**: Remember that predeployed contracts cannot be upgraded

### Deployment Recommendations

1. **Start with Defaults**: Use `evmtypes.DefaultPreinstalls` unless you have specific requirements
2. **Test Thoroughly**: Validate on testnet before mainnet deployment
3. **Document Changes**: Clearly communicate any non-standard deployments to developers
4. **Monitor Usage**: Track contract interactions to understand adoption

### Common Pitfalls to Avoid

* Don't deploy to addresses that could conflict with precompiles (typically 0x1-0x9FF)
* Don't assume contracts are deployed - always check first
* Don't modify standard contract addresses without strong justification
* Don't deploy untested or unaudited bytecode

## Known Issues

<Warning>
  The Safe Singleton Factory bytecode in the current DefaultPreinstalls may be incorrect (appears to be duplicate of Create2 bytecode). Verify the correct bytecode before deploying this contract in production.
</Warning>

## Adding Custom Preinstalls

To add custom contracts beyond the defaults:

```go theme={"theme":{"light":"github-light-high-contrast","dark":"github-dark-high-contrast"}}
// Define custom preinstall
customPreinstall := types.Preinstall{
    Name:    "MyCustomContract",
    Address: "0xYourChosenAddress",
    Code:    "0xCompiledBytecode",
}

// Validate before deployment
if err := customPreinstall.Validate(); err != nil {
    return err
}

// Add via appropriate method (genesis, governance, or upgrade)
preinstalls := append(evmtypes.DefaultPreinstalls, customPreinstall)
```

## Troubleshooting

### Common Issues

| Issue                                                 | Cause                     | Solution                               |
| ----------------------------------------------------- | ------------------------- | -------------------------------------- |
| "preinstall already has an account in account keeper" | Address collision         | Choose different address               |
| "preinstall has empty code hash"                      | Invalid or empty bytecode | Verify bytecode hex string is valid    |
| "preinstall address is not a valid hex address"       | Malformed address         | Ensure 0x prefix and 40 hex chars      |
| "invalid authority"                                   | Wrong governance address  | Use correct gov module account address |
| Contract not found after deployment                   | Wrong network             | Verify chain ID and RPC endpoint       |

### Debugging Steps

1. Check chain genesis configuration
2. Verify proposal passed and executed
3. Query contract code directly
4. Test with simple contract interaction
5. Review chain logs for errors

## Further Resources

* [EIP-1014: CREATE2 Specification](https://eips.ethereum.org/EIPS/eip-1014) - Understanding deterministic deployment
* [Multicall3 Documentation](https://github.com/mds1/multicall) - Official Multicall3 repository
* [Permit2 Introduction](https://blog.uniswap.org/permit2-and-universal-router) - Uniswap's Permit2 design
* [Safe Contracts](https://github.com/safe-global/safe-contracts) - Safe multisig implementation
