Set Up EVM Keyring
Overview
The Ethereum Virtual Machine (EVM) keyring system enables you to create unified wallets and addresses across multiple EVM-compatible blockchains using a single set of cryptographic keys (user, backup, and BitGo). The base address of the wallet and the derived receive addresses are all cryptographically identical on every supported EVM blockchain.
EVM keyrings use a reference model for creating linked wallets and addresses. A reference wallet is the foundational MPC wallet that acts as the cryptographic source for all other wallets linked in the EVM keyring. The keys to the reference wallet are the source keys that you use across all linked wallets. In addition, all linked addresses match their reference addresses.
Use Cases
The main use cases for EVM keyrings are:
- Cross-Chain Recovery - If you accidentally send assets to the wrong EVM blockchain, you can recover them by linking the receiving wallets and addresses to your EVM keyring. Once linked, the stuck assets automatically flush to a wallet on the correct EVM blockchain.
- Unified Identity - You can have the same addresses across all supported EVM chains.
- Simplified Management - Manage only a single set of keys (user, backup, and BitGo) for wallets across multiple EVM blockchains.
Creating a unified identity and simplifying your key management are proactive measures you can take to utilize EVM keyrings. In contrast, cross-chain recoveries are reactive measures that you only have to take if a transaction accidentally sends assets to the wrong blockchain.
Prerequisites
- Get Started
- Create Wallets
- MPC hot wallet
walletVersion: 5
- Any EVM blockchain (except Core)
1. Select Reference Wallet
Choose an existing EVM wallet to serve as your reference wallet.
Endpoints:
1 2 3 4 5 6
export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>" curl -X GET \ https://app.bitgo-test.com/api/v2/wallets \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ACCESS_TOKEN"
Step Result
Select the wallet you want to use as the reference wallet and save the wallet id
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
{ "wallets": [ { "id": "63bd84ea4512c10007ce54a47743f93d", "users": [ { "user": "62ab90e06dfda30007974f0a52a12995", "permissions": ["admin", "view", "spend"] } ], "coin": "hteth", "label": "My Ethereum Testnet Wallet", "m": 2, "n": 3, "keys": [ "63bd84ea4b81a4000748b540f63580d9", "63bd84ea77fe2100070aef91ce0e2b47", "62c5ae7f74ac860007aff0cb9bcf93a6" ], "keySignatures": { "backupPub": "20c89b7e0da32c8e3060b548d47e309f0cb8629a4563a564996421fd57c60a3aa751f4d265551520bf92e1e4328f5584456c815b9a46ea5180c655032757524764", "bitgoPub": "2087ffd8dfad9b53cf1fe1ccf563cff90899424743d761ec6b727122e7493cb0a946424eeb3edac624270542035239b66757d608c8885ff0830f47a7d3e5598163" }, "enterprise": "62c5ae8174ac860007aff138a2d74df7" ... } ] }
2. Link Wallets to Keyring
Once you have a reference wallet ID, you can link wallets to the EVM keyring by creating wallets on other blockchains. Pass the wallet id
of the reference wallet in the evmKeyRingReferenceWalletId
field.
Repeat this step for each EVM-compatible blockchain you want to add to your keyring.
Endpoint: Generate Wallet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
export BITGO_EXPRESS_HOST="<YOUR_LOCAL_HOST>" export COIN="<ASSET_ID>" export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>" export LABEL="<YOUR_WALLET_NAME>" export REFERENCE_WALLET_ID="<YOUR_REFERENCE_WALLET_ID>" curl -X POST \ http://$BITGO_EXPRESS_HOST/api/v2/$COIN/wallet/generate \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d '{ "label": "'"$LABEL"'", # (Optional) If absent, uses the label of the reference wallet "evmKeyRingReferenceWalletId": "'"$REFERENCE_WALLET_ID"'", ... }'
Step Result
Your new EVM wallets have the same base address as the reference wallet, enabling cross-chain operations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
{ "id": "68c3f553f62546c8e364ad785896b81f", "users": [ { "user": "5cae3130f8f4561d51dfcbfdaafba9b9", "permissions": [ "admin", "spend", "view" ] } ], "coin": "tpolygon", "label": "POLYGON EVM MPC W1", "m": 2, "n": 3, "keys": [ "689a571fc2a2ca9dc5fb114f8708be32", "689a571f3a7b477d8dff80535499dc61", "689a571ec4e260bc28136c2f66666c2b" ], "keySignatures": {}, "enterprise": "65a66817a7f6736078ab85afed6033d3", "organization": "65a66818a7f6736078ab864f0042ff3d", "bitgoOrg": "BitGo Trust", "tags": [ "68c3f553f62546c8e364ad785896b81f", "65a66817a7f6736078ab85afed6033d3" ], "disableTransactionNotifications": false, "freeze": {}, "deleted": false, "approvalsRequired": 1, "isCold": false, "coinSpecific": { "deployedInBlock": false, "lastChainIndex": { "0": -1, "1": -1 }, "baseAddress": "0x67000269cdddf7e3220d9e81b0b2aa54ccc4b008", "feeAddress": "0xff45beb151901ef6cde8166fa025d595905f7e39", "pendingChainInitialization": false, "pendingEcdsaTssInitialization": false, "creationFailure": [], "gasPriceTier": "fast", "tokenFlushThresholds": {}, "lowPriorityFeeAddress": "0xff45beb151901ef6cde8166fa025d595905f7e39", "salt": "0xf", "walletVersion": 5, "pendingDeployment": false, "deployForwardersManually": false, "flushForwardersManually": false, "enableMMI": false, "enableNFT": false, "sendManyTokens": [] }, "admin": { "policy": { "date": "2025-09-12T10:26:27.263Z", "id": "68c3f553f62546c8e364ad89bcc3e662", "label": "default", "rules": [], "version": 0, "latest": true } }, "clientFlags": [], "walletFlags": [], "allowBackupKeySigning": false, "evmKeyRingevmKeyRingReferenceWalletId": "689a575960b27cc44f82733b8a26cf1d", "recoverable": true, "startDate": "2025-09-12T10:26:27.000Z", "type": "hot", "buildDefaults": {}, "customChangeKeySignatures": {}, "hasLargeNumberOfAddresses": false, "multisigType": "tss", "multisigTypeVersion": "MPCv2", "hasReceiveTransferPolicy": false, "creator": "5cae3130f8f4561d51dfcbfdaafba9b9", "walletFullyCreated": true, "config": {}, "balanceString": "0", "confirmedBalanceString": "0", "spendableBalanceString": "0", "lockedBalanceString": "0", "stakedBalanceString": "0", "receiveAddress": { "id": "68c3f553f62546c8e364ad93a8811c8e", "address": "0x67000269cdddf7e3220d9e81b0b2aa54ccc4b008", "chain": 0, "index": 0, "coin": "tpolygon", "wallet": "68c3f553f62546c8e364ad785896b81f", "coinSpecific": { "nonce": -1, "txCount": 0, "pendingChainInitialization": false, "creationFailure": [], "pendingDeployment": false, "forwarderVersion": 4, "isTss": true, "isNonceLocked": false, "updateTime": "2025-09-12T10:26:27.394Z" } }, "pendingApprovals": [] }
3. Link Addresses to Keyring
Once you have wallets in the EVM keyring that share the same base address, you can create linked addresses. Use a reference address from any existing wallet in your keyring to create an identical address in a linked wallet on different blockchain.
Note the following address initialization differences:
- Reference Address - The smart contract deploys only upon receiving the first transaction.
- EVM Keyring Address - The smart contract deploys upon creation, enabling immediate cross-chain recovery.
1 2 3 4 5 6 7 8 9 10 11 12
export COIN="<ASSET_ID>" export WALLET_ID="<YOUR_WALLET_ID>" export ACCESS_TOKEN="<YOUR_ACCESS_TOKEN>" export REFERENCE_ADDRESS="<YOUR_REFERENCE_ADDRESS>" curl -X POST \ "https://app.bitgo.com/api/v2/$COIN/wallet/$WALLET_ID/address" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "evmKeyRingReferenceAddress": "'"$REFERENCE_ADDRESS"'" }'
Step Result
Your new address is the same as the reference address, enabling cross-chain operations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
{ "id": "68c42570b9c05fcdd3f0c53b5261259f", "address": "0x9eaa84c52cd8649395c62b3ac982f00ad317df2b", "chain": 0, "index": 3, "coin": "tpolygon", "lastNonce": 0, "wallet": "68c3fd5e9384c89efe35dda0eefc8402", "needsConsolidation": false, "coinSpecific": { "nonce": -1, "updateTime": "2025-09-12T13:51:44.694Z", "txCount": 0, "pendingChainInitialization": true, "creationFailure": [], "salt": "0x3", "pendingDeployment": false, "forwarderVersion": 4 }, "addressType": "p2sh", "keychains": [ { "id": "68c3fd5bc20920edd2ceec194611dc7b", "source": "user", "type": "tss", "commonKeychain": "02f22ee8420903c0f57fca647c9c08da9e3ba48cebe43a0c4df8673369830d67dd5fe5ab4557e8447ebab88db4e9b56099549303ea14005dc9f78358986d987c85", "encryptedPrv": "..." }, { "id": "68c3fd5c74f8b62d58168c51addb8e87", "source": "backup", "type": "tss", "commonKeychain": "02f22ee8420903c0f57fca647c9c08da9e3ba48cebe43a0c4df8673369830d67dd5fe5ab4557e8447ebab88db4e9b56099549303ea14005dc9f78358986d987c85", "encryptedPrv": "..." }, { "id": "68c3fd5be4dbc6d15a832b89d62ff1f6", "source": "bitgo", "type": "tss", "commonKeychain": "02f22ee8420903c0f57fca647c9c08da9e3ba48cebe43a0c4df8673369830d67dd5fe5ab4557e8447ebab88db4e9b56099549303ea14005dc9f78358986d987c85", "isBitGo": true, "isTrust": false, "hsmType": "institutional" } ], "baseAddress": "0xaf34750bcf93ccbb22569c06af40558dfcd3e717", "format": undefined }
4. Fund Gas Tank
The gas tank address is automatically inherited from the reference wallet and is therefore the same across all blockchains in your EVM keyring. Fund your gas tank with the native assets of each blockchain in your keyring. During a cross-chain recovery, the gas tank pays for the deployment of a forwarder smart contract using the native asset of the target blockchain.
To learn more, see Fund Gas Tanks.
Next Steps
Any address in your EVM keyring is set up for automatic cross-chain recovery. If you have assets that were sent to an EVM wallet on the wrong blockchain, or if you receive future transactions as such, BitGo automatically:
- Deploys the forwarder contract for the address on the target EVM network.
- Automatically syncs the balance.
- Makes the previously stuck assets available in your target EVM wallet, fully recovered and accessible for withdrawal.