Predeployed contracts (also called preinstalls) are EVM contracts that exist in chain state at a specific address from genesis. Because the address is fixed and known in advance, the same contract can exist at the same address across every chain that includes it, making them useful for infrastructure that needs to be reliably reachable everywhere.Documentation Index
Fetch the complete documentation index at: https://cosmos-docs-evm-upgrade-7.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Default contracts
Cosmos EVM includes five default preinstalls (x/vm/types/preinstall.go):
| Contract | Address | Purpose | Docs |
|---|---|---|---|
| Create2 | 0x4e59b44847b379578588920ca78fbf26c0b4956c | Deterministic contract deployment using CREATE2 | EIP-1014 |
| Multicall3 | 0xcA11bde05977b3631167028862bE2a173976CA11 | Batch multiple contract calls in one transaction | Repo · Site |
| Permit2 | 0x000000000022D473030F116dDEE9F6B43aC78BA3 | Signature-based token approvals for any ERC20 | Repo · Docs |
| Safe Singleton Factory | 0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7 | Deploy Safe multisig wallets at deterministic addresses | Repo · Docs |
| EIP-2935 | 0x0000F90827F1C53a10cb7A02335B175320002935 | Historical block hash storage | EIP-2935 |
Enabling at genesis
Preinstalls are set in theapp_state.evm.preinstalls array of genesis.json. How you populate that array depends on how you generate genesis for your chain.
-
Using
local_node.sh:evmd initdoes not populate preinstalls automatically. you will need to updatelocal_node.shto write the default preinstalls intogenesis.jsonbefore the node starts. Each entry requires the contract name, address, and compiled bytecode:Bytecodes are defined inlocal_node.shx/vm/types/preinstall.go. -
Using programmatic genesis (e.g.,
evmd testnet): Preinstalls are set inNewEVMGenesisState()inevmd/genesis.go. The reference chain already setsevmGenState.Preinstalls = evmtypes.DefaultPreinstallsthere, so all five defaults are included automatically. -
Custom genesis generation: Include the
preinstallsarray directly in yourgenesis.jsonunderapp_state.evm, with each entry specifyingname,address, and hex-encodedcode. Example:genesis.json
Add custom contracts
- To deploy a contract beyond the defaults, open
evmd/genesis.goand updateNewEVMGenesisState. The example below uses a minimal 10-byte contract (0x600160005260206000f3) that returns1on any call — replace the name, address, and code with your own:
evmd/genesis.go
- Add a
jqpatch tolocal_node.shafter the last genesis customization line (.consensus.params.block.max_gas), before the# Change proposal periodscomment. Use+=to append without overwriting any previously set preinstalls:
local_node.sh
- Valid Ethereum address (0x prefix, 40 hex characters)
- Must not conflict with existing contracts or precompile addresses (0x1–0x9FF)
- Non-empty, valid EVM bytecode (hex encoded)
- Rebuild the binary and start the chain:
-y flag wipes any existing chain data and reinitializes from genesis, which is required for the preinstall to take effect.
- Once the chain is running, open a new terminal and confirm the contract is installed by running the following commands:
code:
0x600160005260206000f3, which is the bytecode set in genesis.go and local_node.sh. A non-empty value confirms the code was written to state.
Expected output for account:
code_hash: a non-empty hash confirms the contract exists at this addressbalance: "0": preinstalls are deployed with no native token balance, which is expectednonce: "0": preinstalls are not deployed via a transaction, so the nonce starts at 0
Add contracts after launch
The following methods are examples of ways to deploy predeployed contracts after the chain is running.Deploy via governance proposal
UseMsgRegisterPreinstalls to deploy contracts on a running chain via governance:
proposal.json
Deploy via chain upgrade handler
Include preinstalls in a coordinated chain upgrade:app/upgrades/v2/upgrades.go