feat: detangle chainId / domainId EVM assumptions (#4798)

### Description

Detangle assumption that chainId == domainId for EVM chains.
- required to support new domain IDs for sept26 chain deploy batch
https://github.com/hyperlane-xyz/hyperlane-registry/pull/352

Domain IDs and Chain Names are still unique, but chainId is no longer
guaranteed to be a unique identifier.
- required to support shadow lumia (current deployment) + prod lumia
(new deployment with different domain id)

Touches:
- evm core/ism/hook/warp modules
- multiprovider + chain metadata manager
- safe service
- renaming `ChainNameOrId` to `ChainNameOrDomain` (where bulk of the
diff comes from)

### Drive-by changes

- ~~add name of a `chain` to `Annotated` types, since chain ID on a
populated transaction is a looser tie to a chain than `domainId` or
`chain`~~
- ~~simplify multiprovider.sendtransaction, since `chain` is provided
with the annotated transaction~~

- ensure domainId is not optional in the chain metadata schema
- requires registry fix
https://github.com/hyperlane-xyz/hyperlane-registry/pull/357
- update ethers v5 json rpc submitter to require a `chain` as well

### Related issues

- mostly redoes work from
https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/4599
- will have to be rechecked after zksync changes are also in

### Backward compatibility

no

### Testing

ci, manual

---------

Signed-off-by: pbio <10051819+paulbalaji@users.noreply.github.com>
pull/4828/head
Paul Balaji 2 weeks ago committed by GitHub
parent 30d92c3197
commit e3b97c4555
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      .changeset/thirty-adults-camp.md
  2. 2
      .registryrc
  3. 134
      rust/main/config/mainnet_config.json
  4. 1
      typescript/cli/examples/submit/strategy/impersonated-account-strategy.yaml
  5. 2
      typescript/cli/examples/submit/strategy/json-rpc-chain-strategy.yaml
  6. 1
      typescript/cli/examples/submit/strategy/json-rpc-strategy.yaml
  7. 28
      typescript/cli/src/config/submit.ts
  8. 13
      typescript/cli/src/deploy/warp.ts
  9. 4
      typescript/cli/src/submit/submit.ts
  10. 8
      typescript/cli/src/tests/commands/helpers.ts
  11. 18
      typescript/cli/src/tests/warp-apply.e2e-test.ts
  12. 7
      typescript/infra/scripts/funding/fund-keys-from-deployer.ts
  13. 5
      typescript/infra/scripts/generate-scraper-add-domain-sql.sh
  14. 16
      typescript/infra/scripts/helloworld/kathy.ts
  15. 4
      typescript/infra/src/utils/safe.ts
  16. 3
      typescript/sdk/src/contracts/contracts.ts
  17. 2
      typescript/sdk/src/core/AbstractHyperlaneModule.ts
  18. 2
      typescript/sdk/src/core/EvmCoreModule.hardhat-test.ts
  19. 17
      typescript/sdk/src/core/EvmCoreModule.ts
  20. 40
      typescript/sdk/src/hook/EvmHookModule.ts
  21. 1
      typescript/sdk/src/index.ts
  22. 15
      typescript/sdk/src/ism/EvmIsmModule.ts
  23. 21
      typescript/sdk/src/ism/HyperlaneIsmFactory.ts
  24. 100
      typescript/sdk/src/metadata/ChainMetadataManager.ts
  25. 4
      typescript/sdk/src/metadata/chainMetadataTypes.ts
  26. 16
      typescript/sdk/src/providers/MultiProvider.ts
  27. 6
      typescript/sdk/src/providers/ProviderType.ts
  28. 4
      typescript/sdk/src/providers/transactions/submitter/TxSubmitterInterface.ts
  29. 4
      typescript/sdk/src/providers/transactions/submitter/builder/TxSubmitterBuilder.ts
  30. 3
      typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxBuilder.ts
  31. 8
      typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5GnosisSafeTxSubmitter.ts
  32. 2
      typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5ImpersonatedAccountTxSubmitter.ts
  33. 16
      typescript/sdk/src/providers/transactions/submitter/ethersV5/EV5JsonRpcTxSubmitter.ts
  34. 4
      typescript/sdk/src/providers/transactions/submitter/ethersV5/schemas.test.ts
  35. 9
      typescript/sdk/src/providers/transactions/submitter/ethersV5/schemas.ts
  36. 4
      typescript/sdk/src/providers/transactions/submitter/ethersV5/types.ts
  37. 2
      typescript/sdk/src/providers/transactions/submitter/schemas.ts
  38. 6
      typescript/sdk/src/providers/transactions/transformer/TxTransformerInterface.ts
  39. 21
      typescript/sdk/src/providers/transactions/transformer/ethersV5/EV5InterchainAccountTxTransformer.ts
  40. 19
      typescript/sdk/src/token/EvmERC20WarpModule.ts
  41. 6
      typescript/sdk/src/types.ts
  42. 15
      typescript/sdk/src/utils/gnosisSafe.js
  43. 26
      typescript/sdk/src/utils/transactions.ts
  44. 1
      typescript/utils/src/index.ts
  45. 1
      typescript/utils/src/types.ts
  46. 9
      typescript/widgets/src/chains/ChainAddMenu.tsx
  47. 2
      typescript/widgets/src/chains/ChainSearchMenu.tsx

@ -0,0 +1,8 @@
---
'@hyperlane-xyz/utils': major
'@hyperlane-xyz/cli': major
'@hyperlane-xyz/sdk': major
'@hyperlane-xyz/widgets': major
---
Detangle assumption that chainId == domainId for EVM chains. Domain IDs and Chain Names are still unique, but chainId is no longer guaranteed to be a unique identifier. Domain ID is no longer an optional field and is now required for all chain metadata.

@ -1 +1 @@
14836804e543a64cd3747cd6bbea6e245b6353b1
1ea2849e2fc1e750bac67e35827c9d682c7fd4bf

@ -34,7 +34,7 @@
"interchainAccountIsm": "0xd766e7C7517f2d0D92754b2fe4aE7AdEf7bDEC3e",
"interchainAccountRouter": "0x25C87e735021F72d8728438C2130b02E3141f2cb",
"interchainGasPaymaster": "0x8F1E22d309baa69D398a03cc88E9b46037e988AA",
"interchainSecurityModule": "0x4e1d2cdB48A2C2912b11801Eb1F1d5007474cA43",
"interchainSecurityModule": "0x259Da872714f84B74B4473fab45e9839f3453a40",
"isTestnet": false,
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x811808Dd29ba8B0FC6C0ec0b5537035E59745162",
@ -100,7 +100,7 @@
"interchainAccountIsm": "0x2A7574358Ec53522CE2452887661AB4c86F7d400",
"interchainAccountRouter": "0x91874Dbed74925dFe6059B90385EEb90DdE0B2E6",
"interchainGasPaymaster": "0x3b6044acd6767f017e99318AA6Ef93b7B06A5a22",
"interchainSecurityModule": "0x50d0b0E27B8B93119618f053A623886116dd3b6d",
"interchainSecurityModule": "0xDeeE785e0b3De36A7F1aF5d0A0a1F86e7c356a58",
"mailbox": "0x979Ca5202784112f4738403dBec5D0F3B9daabB9",
"merkleTreeHook": "0x748040afB89B8FdBb992799808215419d36A0930",
"name": "arbitrum",
@ -172,7 +172,7 @@
"interchainAccountIsm": "0x27a3233c05C1Df7c163123301D14bE9349E3Cb48",
"interchainAccountRouter": "0xa82a0227e6d6db53AF4B264A852bfF91C6504a51",
"interchainGasPaymaster": "0x95519ba800BBd0d34eeAE026fEc620AD978176C0",
"interchainSecurityModule": "0xbc803Da34A88E5f6B50dfc0CC9D924d9865c91C5",
"interchainSecurityModule": "0x8Ea008E1E39D9770312b9b516D1f0C41DD3feCb3",
"mailbox": "0xFf06aFcaABaDDd1fb08371f9ccA15D73D51FeBD6",
"merkleTreeHook": "0x84eea61D679F42D92145fA052C89900CBAccE95A",
"name": "avalanche",
@ -245,7 +245,7 @@
"interchainAccountIsm": "0x223F7D3f27E6272266AE4B5B91Fd5C7A2d798cD8",
"interchainAccountRouter": "0x4767D22117bBeeb295413000B620B93FD8522d53",
"interchainGasPaymaster": "0xc3F23848Ed2e04C0c6d41bd7804fa8f89F940B94",
"interchainSecurityModule": "0xB7fcb4665ace2B0d36fd92D26b4a8B516c0bFe5F",
"interchainSecurityModule": "0x875a788e4A887848ac0B5d4431125Ecd5cdB3dAe",
"mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"merkleTreeHook": "0x19dc38aeae620380430C200a6E990D5Af5480117",
"name": "base",
@ -316,7 +316,7 @@
"interchainAccountIsm": "0xe93f2f409ad8B5000431D234472973fe848dcBEC",
"interchainAccountRouter": "0x2f4Eb04189e11Af642237Da62d163Ab714614498",
"interchainGasPaymaster": "0xB3fCcD379ad66CED0c91028520C64226611A48c9",
"interchainSecurityModule": "0xECa4a584E91867a72cd036DB7Db22Ad894a197B7",
"interchainSecurityModule": "0x518C62D6771b7a6b393E429ba5f9025a6F485301",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0xC9B8ea6230d6687a4b13fD3C0b8f0Ec607B26465",
"name": "blast",
@ -384,7 +384,7 @@
"interchainAccountIsm": "0x451dF8AB0936D85526D816f0b4dCaDD934A034A4",
"interchainAccountRouter": "0x5C02157068a52cEcfc98EDb6115DE6134EcB4764",
"interchainGasPaymaster": "0x62B7592C1B6D1E43f4630B8e37f4377097840C05",
"interchainSecurityModule": "0x93E3e6CA295803417212421785606B1F7dDeaD8f",
"interchainSecurityModule": "0x28Df661E61e2f4e7a35F3a554094191e64cd6E5A",
"mailbox": "0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147",
"merkleTreeHook": "0x781bE492F1232E66990d83a9D3AC3Ec26f56DAfB",
"name": "bob",
@ -450,7 +450,7 @@
"interchainAccountIsm": "0x9e22945bE593946618383B108CC5bce09eBA4C26",
"interchainAccountRouter": "0x32A07c1B7a7fe8D4A0e44B0181873aB9d64C16c1",
"interchainGasPaymaster": "0x78E25e7f84416e69b9339B0A6336EB6EFfF6b451",
"interchainSecurityModule": "0xA0506B5b12770494740A4a7cc86C9A36Dc1Fc6Dc",
"interchainSecurityModule": "0x5BC506C2C04dfDe5b45cbF47f05b4373D65832e4",
"mailbox": "0x2971b9Aec44bE4eb673DF1B88cDB57b96eefe8a4",
"merkleTreeHook": "0xFDb9Cd5f9daAA2E4474019405A328a88E7484f26",
"name": "bsc",
@ -531,7 +531,7 @@
"interchainAccountIsm": "0xB732c83aeE29596E3163Da2260710eAB67Bc0B29",
"interchainAccountRouter": "0x27a6cAe33378bB6A6663b382070427A01fc9cB37",
"interchainGasPaymaster": "0x571f1435613381208477ac5d6974310d88AC7cB7",
"interchainSecurityModule": "0xa6f4835940dbA46E295076D0CD0411349C33789f",
"interchainSecurityModule": "0xB9aD1ccE862444B5C3bad009ef500AD3680940Da",
"mailbox": "0x50da3B3907A08a24fe4999F4Dcf337E8dC7954bb",
"merkleTreeHook": "0x04dB778f05854f26E67e0a66b740BBbE9070D366",
"name": "celo",
@ -596,7 +596,7 @@
"interchainAccountIsm": "0x4Eb82Ee35b0a1c1d776E3a3B547f9A9bA6FCC9f2",
"interchainAccountRouter": "0xEF9A332Ec1fD233Bf9344A58be56ff9E104B4f60",
"interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503",
"interchainSecurityModule": "0x05f6BAa16F1aCf7b19c4A09E019D856c10ab8355",
"interchainSecurityModule": "0x77e9F81405DBC1eBeDA93f23aB4a339452d2AD9D",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD",
"name": "cheesechain",
@ -659,7 +659,7 @@
"from": 4842212
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0x9A746C4BC2bE7E657A3469f0a0DAA1dE517b8514",
"interchainSecurityModule": "0xcC5534C4665D9BD93B377F56eC4c09Fdee87AD30",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "cyber",
@ -726,7 +726,7 @@
"from": 23783929
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0x168E9C1481F50E66Cc5F5E24b04eBf7071629c4E",
"interchainSecurityModule": "0xF6C78dDeeb0Ef1682bC020787ecA835C5F353701",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "degenchain",
@ -839,7 +839,7 @@
"interchainAccountIsm": "0xCeafc098e5c3c7768b9229Be2FEC275862A81Abd",
"interchainAccountRouter": "0xed9a722c543883FB7e07E78F3879762DE09eA7D5",
"interchainGasPaymaster": "0xB30EAB08aa87138D57168D0e236850A530f49921",
"interchainSecurityModule": "0x094120BaC576aD7D88ec6893C9B220a0e64923E9",
"interchainSecurityModule": "0x702A7e81b3625AA02b365Aa95A7123a9EB31012f",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xC831271c1fB212012811a91Dd43e5926C1020563",
"name": "endurance",
@ -910,7 +910,7 @@
"interchainAccountIsm": "0x292C614ED53DaaDBf971521bc2C652d1ca51cB47",
"interchainAccountRouter": "0x5E532F7B610618eE73C2B462978e94CB1F7995Ce",
"interchainGasPaymaster": "0x9e6B1022bE9BBF5aFd152483DAD9b88911bC8611",
"interchainSecurityModule": "0x23d160e4474Ce011829c71Bf1bCaA40F0b5612D5",
"interchainSecurityModule": "0xc7b5BA9EcedcFd7D250Cf7df19558D7dd0d06ECc",
"mailbox": "0xc005dc82818d67AF737725bD4bf75435d065D239",
"merkleTreeHook": "0x48e6c30B97748d1e2e03bf3e9FbE3890ca5f8CCA",
"name": "ethereum",
@ -979,7 +979,7 @@
"interchainAccountIsm": "0x7C012DCA02C42cfA3Fd7Da3B0ED7234B52AE68eF",
"interchainAccountRouter": "0xbed53B5C5BCE9433f25A2A702e6df13E22d84Ae9",
"interchainGasPaymaster": "0x2Fca7f6eC3d4A0408900f2BB30004d4616eE985E",
"interchainSecurityModule": "0x8B497dff421844Bb0882E0C495d0851D4461675C",
"interchainSecurityModule": "0xC8e75e117E1dBC43880ac6c85e820844Dd5f527a",
"mailbox": "0x2f9DB5616fa3fAd1aB06cB2C906830BA63d135e3",
"merkleTreeHook": "0x8358D8291e3bEDb04804975eEa0fe9fe0fAfB147",
"name": "fraxtal",
@ -1047,7 +1047,7 @@
"interchainAccountIsm": "0x9629c28990F11c31735765A6FD59E1E1bC197DbD",
"interchainAccountRouter": "0x2351FBe24C1212F253b7a300ff0cBCFd97952a19",
"interchainGasPaymaster": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainSecurityModule": "0x69b33D67B9C51D45E23d22E727FF186DD6298ECA",
"interchainSecurityModule": "0xf0b1EC4228c0F26B7225851f940c625e4Be12226",
"mailbox": "0x3071D4DA6020C956Fe15Bfd0a9Ca8D4574f16696",
"merkleTreeHook": "0xfBc08389224d23b79cb21cDc16c5d42F0ad0F57f",
"name": "fusemainnet",
@ -1121,7 +1121,7 @@
"interchainAccountIsm": "0x07E2062A1bC66a2C1d05cb5C3870a4AF86e0056E",
"interchainAccountRouter": "0xBE70Ab882D1F7E37e04a70CDd9Ec23b37a234064",
"interchainGasPaymaster": "0xDd260B99d302f0A3fF885728c086f729c06f227f",
"interchainSecurityModule": "0x00533a5F14B3a0632C86f99E4e20a10b73C4AE0D",
"interchainSecurityModule": "0xcfA4D90A43AAB0dE6a07c33A0614606b5Fbf71eC",
"mailbox": "0xaD09d78f4c6b9dA2Ae82b1D34107802d380Bb74f",
"merkleTreeHook": "0x2684C6F89E901987E1FdB7649dC5Be0c57C61645",
"name": "gnosis",
@ -1192,7 +1192,7 @@
"interchainAccountIsm": "0x708E002637792FDC031E6B62f23DD60014AC976a",
"interchainAccountRouter": "0xfB8cea1c7F45608Da30655b50bbF355D123A4358",
"interchainGasPaymaster": "0x19dc38aeae620380430C200a6E990D5Af5480117",
"interchainSecurityModule": "0xB8F85B879775adF156Dd4AFa43e97DeB880d99D4",
"interchainSecurityModule": "0x5f39C3f0d9c74a667C177795b769CC22aE0A200d",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x0972954923a1e2b2aAb04Fa0c4a0797e5989Cd65",
"name": "inevm",
@ -1320,7 +1320,7 @@
"from": 14616307
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xE2968dAb74541184Ad95651b1e5Cf34Ab1bBEc97",
"interchainSecurityModule": "0xa078A84FCB5d53BCe9529DcF96635794951116Ba",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "kroma",
@ -1393,7 +1393,7 @@
"interchainAccountIsm": "0xdcA646C56E7768DD11654956adE24bfFf9Ba4893",
"interchainAccountRouter": "0xD59dA396F162Ed93a41252Cebb8d5DD4F093238C",
"interchainGasPaymaster": "0x8105a095368f1a184CceA86cCe21318B5Ee5BE28",
"interchainSecurityModule": "0x0EEF1e64646EE01DeED4850074Cd4B97C0A630a9",
"interchainSecurityModule": "0x3902B990C5DC30D6CeeFf8b8B6Ad0cb6466b7d45",
"mailbox": "0x02d16BC51af6BfD153d67CA61754cF912E82C4d9",
"merkleTreeHook": "0xC077A0Cc408173349b1c9870C667B40FE3C01dd7",
"name": "linea",
@ -1464,7 +1464,7 @@
"from": 4195553
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0x63Bb509b9CA644609B15Ea55E56f0Acbbb9dB02E",
"interchainSecurityModule": "0xcee06f87aC789615B0BF989B54fb36De334af5bC",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "lisk",
@ -1528,7 +1528,7 @@
"from": 3088760
},
"interchainGasPaymaster": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"interchainSecurityModule": "0x609ad94304896607A6D81DB00d882245045B79da",
"interchainSecurityModule": "0x351621b2fbfe92193304A8e4DD97E04108883Ac8",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x062200d92dF6bB7bA89Ce4D6800110450f94784e",
"name": "lukso",
@ -1602,7 +1602,7 @@
"interchainAccountIsm": "0x8Ea50255C282F89d1A14ad3F159437EE5EF0507f",
"interchainAccountRouter": "0x693A4cE39d99e46B04cb562329e3F0141cA17331",
"interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4",
"interchainSecurityModule": "0xC012e8E3cBeB6295E1E4837FBA5DB8E077EBc549",
"interchainSecurityModule": "0x4110577c0970e591b3DC6D8FfCbE8FA499b4cD14",
"isTestnet": false,
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112",
@ -1672,7 +1672,7 @@
"interchainAccountIsm": "0xe039DA3A0071BEd087A12660D7b03cf669c7776E",
"interchainAccountRouter": "0x45285463352c53a481e882cD5E2AF2E25BBdAd0D",
"interchainGasPaymaster": "0x8105a095368f1a184CceA86cCe21318B5Ee5BE28",
"interchainSecurityModule": "0x8722328A5Ed815965F9B5eBAA21d04f0F9BFDd35",
"interchainSecurityModule": "0xAb7DdE83cf33e0B305624462A6B9D7D06A32A699",
"mailbox": "0x398633D19f4371e1DB5a8EFE90468eB70B1176AA",
"merkleTreeHook": "0x5332D1AC0A626D265298c14ff681c0A8D28dB86d",
"name": "mantle",
@ -1734,7 +1734,7 @@
"from": 13523607
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xE8176Fc70f129255aA83d3db242C2246Ad77Af7D",
"interchainSecurityModule": "0xc0dc69896334eD2f3Af2666d5EEF70e062a4636e",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "merlin",
@ -1801,7 +1801,7 @@
"from": 17966274
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xA9309228762699D5c81A4b0BAfd06Da21589746b",
"interchainSecurityModule": "0xA04202E77957f7451c0a2F2CA9eF54FFC334BcF3",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "metis",
@ -1866,7 +1866,7 @@
"from": 3752032
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0xA9309228762699D5c81A4b0BAfd06Da21589746b",
"interchainSecurityModule": "0x120bbFe296f11Dd653Cd6aC4F93106d9e6ADe5Bc",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "mint",
@ -1933,7 +1933,7 @@
"interchainAccountIsm": "0xa377b8269e0A47cdd2fD5AAeAe860b45623c6d82",
"interchainAccountRouter": "0x6e1B9f776bd415d7cC3C7458A5f0d801016918f8",
"interchainGasPaymaster": "0x931dFCc8c1141D6F532FD023bd87DAe0080c835d",
"interchainSecurityModule": "0x0777dFffcEd18EE416e35401E0e5e0413b7D43be",
"interchainSecurityModule": "0x0ab4853f2104C8f8e0b4Da4028601D999c7dFCF5",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xE2ee936bEa8e42671c400aC96dE198E06F2bA2A6",
"name": "mode",
@ -2001,7 +2001,7 @@
"interchainAccountIsm": "0x79b3730CE3685f65802aF1771319992bA960EB9D",
"interchainAccountRouter": "0xc4482f66191754a8629D35289043C4EB0285F10E",
"interchainGasPaymaster": "0x14760E32C0746094cF14D97124865BC7F0F7368F",
"interchainSecurityModule": "0xad1Ad827035eDe500aFd0ff122c53f6eA607Eb5C",
"interchainSecurityModule": "0x11cC5Ac8F65e337Db6E95a542e87Af630cd0b1CD",
"mailbox": "0x094d03E751f49908080EFf000Dd6FD177fd44CC3",
"merkleTreeHook": "0x87403b85f6f316e7ba91ba1fa6C3Fb7dD4095547",
"name": "moonbeam",
@ -2143,7 +2143,7 @@
"interchainAccountIsm": "0x2c46BF14641d00549ECa4779BF5CBf91602C1DEd",
"interchainAccountRouter": "0x03D6cC17d45E9EA27ED757A8214d1F07F7D901aD",
"interchainGasPaymaster": "0xD8A76C4D91fCbB7Cc8eA795DFDF870E48368995C",
"interchainSecurityModule": "0x3878aB31B2426A92E8a1E0AE758d848879F7F5E8",
"interchainSecurityModule": "0x5E04bA55C08456562f7e1BF9E2b46628b81593c8",
"mailbox": "0xd4C1905BB1D26BC93DAC913e13CaCC278CdCC80D",
"merkleTreeHook": "0x68eE9bec9B4dbB61f69D9D293Ae26a5AACb2e28f",
"name": "optimism",
@ -2278,7 +2278,7 @@
"interchainAccountIsm": "0xBAC4529cdfE7CCe9E858BF706e41F8Ed096C1BAd",
"interchainAccountRouter": "0xF163949AD9F88977ebF649D0461398Ca752E64B9",
"interchainGasPaymaster": "0x0071740Bf129b05C4684abfbBeD248D80971cce2",
"interchainSecurityModule": "0x9fFC02BfB5C7260C985b005C0cF40d7EC601aac2",
"interchainSecurityModule": "0x0c3fE398595235A3163b39E5C6443aa1f7e145c4",
"mailbox": "0x5d934f4e2f797775e53561bB72aca21ba36B96BB",
"merkleTreeHook": "0x73FbD25c3e817DC4B4Cd9d00eff6D83dcde2DfF6",
"name": "polygon",
@ -2355,7 +2355,7 @@
"interchainAccountIsm": "0xc1198e241DAe48BF5AEDE5DCE49Fe4A6064cF7a7",
"interchainAccountRouter": "0x20a0A32a110362920597F72974E1E0d7e25cA20a",
"interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4",
"interchainSecurityModule": "0xc6c475184F197FA65f233dFc22FA6bD4cE48B4fE",
"interchainSecurityModule": "0x3351FC009ccb309C367787ff9f3040FDee0Dcf66",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112",
"name": "polygonzkevm",
@ -2423,7 +2423,7 @@
"from": 32018468
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0x70e8beCE806914959c1B5D8F75d2217058D31437",
"interchainSecurityModule": "0x37282B7505DA332Fc57FAb1623C73A4AeDb49165",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "proofofplay",
@ -2487,7 +2487,7 @@
"from": 363159
},
"interchainGasPaymaster": "0x3071D4DA6020C956Fe15Bfd0a9Ca8D4574f16696",
"interchainSecurityModule": "0x43346a54445BBdf8241062904E8A13AA62842a02",
"interchainSecurityModule": "0x14551EfDB6c29c8fC61D469627255E5f2c8Bf981",
"mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"merkleTreeHook": "0x55E4F0bc6b7Bb493D50839A8592e7ad8d5e93cf7",
"name": "real",
@ -2554,7 +2554,7 @@
"interchainAccountIsm": "0x5DA60220C5dDe35b7aE91c042ff5979047FA0785",
"interchainAccountRouter": "0x7a4d31a686A36285d68e14EDD53631417eB19603",
"interchainGasPaymaster": "0x2Fa570E83009eaEef3a1cbd496a9a30F05266634",
"interchainSecurityModule": "0xd8b6B632526834D8192860e6B6CE47165Fd02a42",
"interchainSecurityModule": "0x5fe5b8f20437336a74fA53e553472f6fF048e73A",
"mailbox": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"merkleTreeHook": "0x8F1E22d309baa69D398a03cc88E9b46037e988AA",
"name": "redstone",
@ -2616,7 +2616,7 @@
"from": 937117
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0x6A2748201F66647ad6D164CB3340A893881A4bb2",
"interchainSecurityModule": "0xcC5534C4665D9BD93B377F56eC4c09Fdee87AD30",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "sanko",
@ -2684,7 +2684,7 @@
"interchainAccountIsm": "0x32af5Df81fEd5E26119F6640FBB13f3d63a94CDe",
"interchainAccountRouter": "0x0B48a744698ba8dFa514742dFEB6728f52fD66f7",
"interchainGasPaymaster": "0xBF12ef4B9f307463D3FB59c3604F294dDCe287E2",
"interchainSecurityModule": "0xAd1a987BfE0D6fbD92089628daC7C7e4bA9a6AAF",
"interchainSecurityModule": "0x41D5dbBe3a6B5d3937f03e82C23d1EDF9D4d0B6C",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x6119E37Bd66406A1Db74920aC79C15fB8411Ba76",
"name": "scroll",
@ -2752,7 +2752,7 @@
"interchainAccountIsm": "0xf35dc7B9eE4Ebf0cd3546Bd6EE3b403dE2b9F5D6",
"interchainAccountRouter": "0xBcaedE97a98573A88242B3b0CB0A255F3f90d4d5",
"interchainGasPaymaster": "0xFC62DeF1f08793aBf0E67f69257c6be258194F72",
"interchainSecurityModule": "0x494028EA206642e4c60Ec3d12e96B4549E5e1800",
"interchainSecurityModule": "0x42Aa14207b41A7c2b1692DFC4927a32Caaa52b24",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xca1b69fA4c4a7c7fD839bC50867c589592bcfe49",
"name": "sei",
@ -2867,7 +2867,7 @@
"interchainAccountIsm": "0xAE557e108b3336130370aC74836f1356B4b30Cf2",
"interchainAccountRouter": "0x1F8CF09F060A2AE962c0Bb1F92e209a1E7b0E10B",
"interchainGasPaymaster": "0x273Bc6b01D9E88c064b6E5e409BdF998246AEF42",
"interchainSecurityModule": "0xC93F2796A17Ee4580c039aeB7b0c923b10ce79C2",
"interchainSecurityModule": "0x2faB8c35cd093904F3d9a9f022996103d4bb7A85",
"mailbox": "0x28EFBCadA00A7ed6772b3666F3898d276e88CAe3",
"merkleTreeHook": "0x6A55822cf11f9fcBc4c75BC2638AfE8Eb942cAdd",
"name": "taiko",
@ -2929,7 +2929,7 @@
"from": 1678063
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0x70e8beCE806914959c1B5D8F75d2217058D31437",
"interchainSecurityModule": "0xcC5534C4665D9BD93B377F56eC4c09Fdee87AD30",
"isTestnet": false,
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
@ -2997,7 +2997,7 @@
"interchainAccountIsm": "0x551BbEc45FD665a8C95ca8731CbC32b7653Bc59B",
"interchainAccountRouter": "0xc11f8Cf2343d3788405582F65B8af6A4F7a6FfC8",
"interchainGasPaymaster": "0x0D63128D887159d63De29497dfa45AFc7C699AE4",
"interchainSecurityModule": "0x3465AccC39AE5e6C344184013a57cDCe546834d6",
"interchainSecurityModule": "0x87Fb0665D25aC674D4d1494a13cA60E378f7536F",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x149db7afD694722747035d5AEC7007ccb6F8f112",
"name": "viction",
@ -3065,7 +3065,7 @@
"interchainAccountIsm": "0xCB9f90EE5d83Ea52ABd922BD70898f0155D54798",
"interchainAccountRouter": "0x473884010F0C1742DA8Ad01E7E295624B931076b",
"interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503",
"interchainSecurityModule": "0x05f6BAa16F1aCf7b19c4A09E019D856c10ab8355",
"interchainSecurityModule": "0xb936B97837C4158DEA65CBaBCcC55bAE24134108",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD",
"name": "worldchain",
@ -3127,7 +3127,7 @@
"from": 24395308
},
"interchainGasPaymaster": "0x9844aFFaBE17c37F791ff99ABa58B0FbB75e22AF",
"interchainSecurityModule": "0x4886ed96bcdba2ad85Bf518C3171C39e256ac840",
"interchainSecurityModule": "0xf61ee4520B7b316a34cdB31F4B95d8ad1808F919",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"name": "xai",
@ -3195,7 +3195,7 @@
"interchainAccountIsm": "0x29B37088724B745C0ABcE591449Cf042772160C2",
"interchainAccountRouter": "0x03cF708E42C89623bd83B281A56935cB562b9258",
"interchainGasPaymaster": "0x7E27456a839BFF31CA642c060a2b68414Cb6e503",
"interchainSecurityModule": "0x59B0ec92522F164b72c9BE473382197c564B92dc",
"interchainSecurityModule": "0x59Dcbb486F91561acC3500cdc378104AaE27e94a",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0x0054D19613f20dD72721A146ED408971a2CCA9BD",
"name": "xlayer",
@ -3263,7 +3263,7 @@
"interchainAccountIsm": "0x2b6d3F7d28B5EC8C3C028fBCAdcf774D9709Dd29",
"interchainAccountRouter": "0x3AdCBc94ab8C48EC52D06dc65Bb787fD1981E3d5",
"interchainGasPaymaster": "0x931dFCc8c1141D6F532FD023bd87DAe0080c835d",
"interchainSecurityModule": "0xd32353Ae5719ac4f8f24AeD81A2A6898d2632D26",
"interchainSecurityModule": "0x3DFD05cc42F1B5370e688520e65C8fb909418471",
"mailbox": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"merkleTreeHook": "0xE2ee936bEa8e42671c400aC96dE198E06F2bA2A6",
"name": "zetachain",
@ -3329,7 +3329,7 @@
"from": 1511458
},
"interchainGasPaymaster": "0x03cF708E42C89623bd83B281A56935cB562b9258",
"interchainSecurityModule": "0xFFec270FE3D0e3B9348B3664BE73A5d4906BA620",
"interchainSecurityModule": "0x6C5288BBdFBfED98aE3e2C4201a53A9bBcC24fCE",
"mailbox": "0xc2FbB9411186AB3b1a6AFCCA702D1a80B48b197c",
"merkleTreeHook": "0x4C97D35c668EE5194a13c8DE8Afc18cce40C9F28",
"name": "zircuit",
@ -3402,7 +3402,7 @@
"interchainAccountIsm": "0xb2674E213019972f937CCFc5e23BF963D915809e",
"interchainAccountRouter": "0x11b76D93a9D39Eb51F54eBf5566308640cDe882b",
"interchainGasPaymaster": "0x18B0688990720103dB63559a3563f7E8d0f63EDb",
"interchainSecurityModule": "0xED5fD1715A0885a3C7B908BAd5c8C64Ba5166265",
"interchainSecurityModule": "0x10455742E8D25b3FC2b19D41A006E91594D05Cd5",
"mailbox": "0xF5da68b2577EF5C0A0D98aA2a58483a68C2f232a",
"merkleTreeHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F",
"name": "zoramainnet",
@ -3473,7 +3473,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"interchainSecurityModule": "0xed2b47397954E0a56ca7C2a862dba4027da0f595",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3540,7 +3540,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0xa18979d2e5b8A64f62E0f9e9523d28E934F1104c",
"interchainSecurityModule": "0x73b3A13eA8084C9BeAd07eD867cEe1E8F5cceF9e",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3610,7 +3610,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"interchainSecurityModule": "0x0fFD49C8ae6f5DdC20124B92c4b4048EbeF71830",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3686,7 +3686,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"interchainSecurityModule": "0x6dCfEB77d5801DCC76C0EDd1F44E32D6dEcAD2A2",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3750,7 +3750,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"interchainSecurityModule": "0x119b3dFBef304b07BBCb08D5182459f35808bfF2",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3823,7 +3823,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"interchainSecurityModule": "0x7954Da9003180D64B9Eb7dE5E23fC83Fd7673047",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3891,7 +3891,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0x8Ad4d573D7EafC4Ca58f1dB704B8Db804814D674",
"interchainSecurityModule": "0xE96E34b0e66A5FAe90Be8f5FE41B6adB86D84A8b",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -3954,7 +3954,7 @@
"domainRoutingIsmFactory": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"fallbackRoutingHook": "0xc401e251CCa7A364114504A994D6fC7cb1c243AB",
"interchainGasPaymaster": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
"interchainSecurityModule": "0xf08b7F859966ed27286Fe7d924A42b40e2DB80Bd",
"interchainSecurityModule": "0x6CECA24Ebc20183B17fbA17f2856d5B3f97659Db",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x441a01Fca2eD731C0Fc4633998332f9FEDB17575",
"pausableHook": "0x5Ed813B8b41f25c8002B01A72bbDBe6A0232Fe27",
@ -4024,7 +4024,7 @@
"interchainAccountIsm": "0xcd9D3744512F07AE844c40E27912092d7c503565",
"interchainAccountRouter": "0x92cdbF0Ccdf8E93467FA858fb986fa650A02f2A8",
"interchainGasPaymaster": "0xb58257cc81E47EC72fD38aE16297048de23163b4",
"interchainSecurityModule": "0xcC5C35a6214982d9018B95e9684D5b4dA626237e",
"interchainSecurityModule": "0x6B38f93e9145BF8b09B127e20F0275E92E29E4F5",
"mailbox": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39",
"merkleTreeHook": "0xCC3D1659D50461d27a2F025dDb2c9B06B584B7e1",
"pausableHook": "0x4E55aDA3ef1942049EA43E904EB01F4A0a9c39bd",
@ -4084,7 +4084,7 @@
"interchainAccountIsm": "0xc23BaF5Eb5848D19701BbE7f139645e6bd58a319",
"interchainAccountRouter": "0x7c58Cadcc2b60ACF794eE1843488d6f5703f76BE",
"interchainGasPaymaster": "0xb4fc9B5fD57499Ef6FfF3995728a55F7A618ef86",
"interchainSecurityModule": "0x50B5Edd94A1C7ad18Fa2CA667A30Dc051a695aEe",
"interchainSecurityModule": "0x0d242364057129d99Fca35BA8Ed2d9Ae90956F63",
"mailbox": "0xb129828B9EDa48192D0B2db35D0E40dCF51B3594",
"merkleTreeHook": "0x3E969bA938E6A993eeCD6F65b0dd8712B07dFe59",
"pausableHook": "0x6Fb36672365C7c797028C400A61c58c0ECc53cD2",
@ -4889,7 +4889,7 @@
"interchainAccountIsm": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1",
"interchainAccountRouter": "0x9eaaC366BFD70430cFee6E70265fefFf1CfC9E47",
"interchainGasPaymaster": "0x18B0688990720103dB63559a3563f7E8d0f63EDb",
"interchainSecurityModule": "0x9FF3f38DED52D74EF4b666A7A09BcB5F38d6D272",
"interchainSecurityModule": "0x70196Ec5e193dC07CFDC7AeC583DF9aeC20f4939",
"mailbox": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39",
"merkleTreeHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F",
"pausableHook": "0x2F619Ac5122689180AeBB930ADccdae215d538a9",
@ -4953,7 +4953,7 @@
"interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451",
"interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754",
"interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424",
"interchainSecurityModule": "0x8FBFF0cF2920c4deFfd8EAE6a51BB55E1d40eFFc",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D",
"pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7",
@ -5014,7 +5014,7 @@
"interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451",
"interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754",
"interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424",
"interchainSecurityModule": "0xCC95B2978F65B2f358dD4A8B428Dd442AB37f478",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D",
"pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7",
@ -5093,7 +5093,7 @@
"interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451",
"interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754",
"interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424",
"interchainSecurityModule": "0xeD0fc456143f761614478D170bf12403638DDa1e",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D",
"pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7",
@ -5160,7 +5160,7 @@
"interchainAccountIsm": "0x783EC5e105234a570eB90f314284E5dBe53bdd90",
"interchainAccountRouter": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563",
"interchainGasPaymaster": "0xf3dFf6747E7FC74B431C943961054B7BF6309d8a",
"interchainSecurityModule": "0xfa19BfEcB4fed2e0268ee5008a11cD946DcC13c3",
"interchainSecurityModule": "0xFbDfEE404a9DFA413fF8B587aDad4B7979Db28a0",
"mailbox": "0x3a464f746D23Ab22155710f44dB16dcA53e0775E",
"merkleTreeHook": "0x5090dF2FBDa7127c7aDa41f60B79F5c55D380Dd8",
"pausableHook": "0x886BB0f329781b98f98FDeb1ce7a8957F2d43B9F",
@ -5231,7 +5231,7 @@
"interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451",
"interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754",
"interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424",
"interchainSecurityModule": "0x2D92EeB56FbEB258d918485200aC1C2e010547b8",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D",
"pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7",
@ -5296,7 +5296,7 @@
"interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451",
"interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754",
"interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424",
"interchainSecurityModule": "0xCC95B2978F65B2f358dD4A8B428Dd442AB37f478",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D",
"pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7",
@ -5360,7 +5360,7 @@
"interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451",
"interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754",
"interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424",
"interchainSecurityModule": "0x8FBFF0cF2920c4deFfd8EAE6a51BB55E1d40eFFc",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D",
"pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7",
@ -5427,7 +5427,7 @@
"interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451",
"interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754",
"interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424",
"interchainSecurityModule": "0x8FBFF0cF2920c4deFfd8EAE6a51BB55E1d40eFFc",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D",
"pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7",
@ -5491,7 +5491,7 @@
"interchainAccountIsm": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"interchainAccountRouter": "0xeE8C0E1EeBfFCC451a013336386eA53E42a44451",
"interchainGasPaymaster": "0x145566181A18E23bB6a8A3eC6D87765542A7F754",
"interchainSecurityModule": "0x92772a801db50044a9D5078CC35CD63CEcD7B424",
"interchainSecurityModule": "0xC7a2a8103dF4bdE8c78C2C5C03389ee9337A9942",
"mailbox": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"merkleTreeHook": "0x6963480b05EB58f4d624B014ab92e9aD4d21df6D",
"pausableHook": "0xD0dca420feFda68537695A8D887080eeF4030AF7",
@ -5580,7 +5580,7 @@
}
],
"blocks": {
"confirmations": 1,
"confirmations": 2,
"estimateBlockTime": 1,
"reorgPeriod": 0
},

@ -1,3 +1,4 @@
submitter:
chain: anvil2
type: impersonatedAccount
userAddress: '0x16F4898F47c085C41d7Cc6b1dc72B91EA617dcBb'

@ -1,6 +1,8 @@
anvil2:
submitter:
chain: anvil2
type: jsonRpc
anvil3:
submitter:
chain: anvil3
type: jsonRpc

@ -1,2 +1,3 @@
submitter:
chain: anvil2
type: jsonRpc

@ -3,8 +3,8 @@ import { stringify as yamlStringify } from 'yaml';
import {
AnnotatedEV5Transaction,
SubmissionStrategy,
getChainIdFromTxs,
} from '@hyperlane-xyz/sdk';
import { MultiProvider } from '@hyperlane-xyz/sdk';
import { assert, errorToString } from '@hyperlane-xyz/utils';
import { WriteCommandContext } from '../context/types.js';
@ -34,9 +34,9 @@ export async function runSubmit({
'Submission strategy required to submit transactions.\nPlease create a submission strategy. See examples in cli/examples/submit/strategy/*.',
);
const transactions = getTransactions(transactionsFilepath);
const chain = getChainFromTxs(multiProvider, transactions);
const chainId = getChainIdFromTxs(transactions);
const protocol = chainMetadata[chain].protocol;
const protocol = chainMetadata[chainId].protocol;
const submitterBuilder = await getSubmitterBuilder<typeof protocol>({
submissionStrategy,
multiProvider,
@ -60,28 +60,6 @@ export async function runSubmit({
}
}
/**
* Retrieves the chain name from transactions[0].
*
* @param multiProvider - The MultiProvider instance to use for chain name lookup.
* @param transactions - The list of populated transactions.
* @returns The name of the chain that the transactions are submitted on.
* @throws If the transactions are not all on the same chain or chain is not found
*/
function getChainFromTxs(
multiProvider: MultiProvider,
transactions: AnnotatedEV5Transaction[],
) {
const firstTransaction = transactions[0];
assert(firstTransaction.chainId, 'Invalid transaction: chainId is required');
const sameChainIds = transactions.every(
(t: AnnotatedEV5Transaction) => t.chainId === firstTransaction.chainId,
);
assert(sameChainIds, 'Transactions must be submitted on the same chains');
return multiProvider.getChainName(firstTransaction.chainId);
}
function getTransactions(
transactionsFilepath: string,
): AnnotatedEV5Transaction[] {

@ -885,12 +885,20 @@ async function submitWarpApplyTransactions(
params: WarpApplyParams,
chainTransactions: Record<string, AnnotatedEV5Transaction[]>,
): Promise<void> {
const { multiProvider } = params.context;
// Create mapping of chain ID to chain name for all chains in warpDeployConfig
const chains = Object.keys(params.warpDeployConfig);
const chainIdToName = Object.fromEntries(
chains.map((chain) => [
params.context.multiProvider.getChainId(chain),
chain,
]),
);
await promiseObjAll(
objMap(chainTransactions, async (chainId, transactions) => {
await retryAsync(
async () => {
const chain = multiProvider.getChainName(chainId);
const chain = chainIdToName[chainId];
const submitter: TxSubmitterBuilder<ProtocolType> =
await getWarpApplySubmitter({
chain,
@ -935,6 +943,7 @@ async function getWarpApplySubmitter({
? readChainSubmissionStrategy(strategyUrl)[chain]
: {
submitter: {
chain,
type: TxSubmitterType.JSON_RPC,
},
};

@ -39,7 +39,9 @@ async function getSubmitter<TProtocol extends ProtocolType>(
): Promise<TxSubmitterInterface<TProtocol>> {
switch (submitterMetadata.type) {
case TxSubmitterType.JSON_RPC:
return new EV5JsonRpcTxSubmitter(multiProvider);
return new EV5JsonRpcTxSubmitter(multiProvider, {
...submitterMetadata,
});
case TxSubmitterType.IMPERSONATED_ACCOUNT:
return new EV5ImpersonatedAccountTxSubmitter(multiProvider, {
...submitterMetadata,

@ -119,14 +119,18 @@ export async function deployOrUseExistingCore(
return addresses;
}
export async function getChainId(chainName: string, key: string) {
export async function getDomainId(
chainName: string,
key: string,
): Promise<string> {
const { registry } = await getContext({
registryUri: REGISTRY_PATH,
registryOverrideUri: '',
key,
});
const chainMetadata = await registry.getChainMetadata(chainName);
return String(chainMetadata?.chainId);
return String(chainMetadata?.domainId);
}
export async function deployToken(privateKey: string, chain: string) {

@ -15,7 +15,7 @@ import {
REGISTRY_PATH,
deployOrUseExistingCore,
extendWarpConfig,
getChainId,
getDomainId,
updateOwner,
} from './commands/helpers.js';
import {
@ -128,7 +128,7 @@ describe('WarpApply e2e tests', async function () {
warpConfigPath,
);
const chain2Id = await getChainId(CHAIN_NAME_3, ANVIL_KEY);
const chain2Id = await getDomainId(CHAIN_NAME_3, ANVIL_KEY);
const remoteRouterKeys1 = Object.keys(
updatedWarpDeployConfig1[CHAIN_NAME_2].remoteRouters!,
);
@ -141,7 +141,7 @@ describe('WarpApply e2e tests', async function () {
warpConfigPath,
);
const chain1Id = await getChainId(CHAIN_NAME_2, ANVIL_KEY);
const chain1Id = await getDomainId(CHAIN_NAME_2, ANVIL_KEY);
const remoteRouterKeys2 = Object.keys(
updatedWarpDeployConfig2[CHAIN_NAME_3].remoteRouters!,
);
@ -182,7 +182,7 @@ describe('WarpApply e2e tests', async function () {
warpConfigPath,
);
const chain2Id = await getChainId(CHAIN_NAME_3, ANVIL_KEY);
const chain2Id = await getDomainId(CHAIN_NAME_3, ANVIL_KEY);
const remoteRouterKeys1 = Object.keys(
updatedWarpDeployConfig1[CHAIN_NAME_2].remoteRouters!,
);
@ -195,7 +195,7 @@ describe('WarpApply e2e tests', async function () {
warpConfigPath,
);
const chain1Id = await getChainId(CHAIN_NAME_2, ANVIL_KEY);
const chain1Id = await getDomainId(CHAIN_NAME_2, ANVIL_KEY);
const remoteRouterKeys2 = Object.keys(
updatedWarpDeployConfig2[CHAIN_NAME_3].remoteRouters!,
);
@ -247,8 +247,8 @@ describe('WarpApply e2e tests', async function () {
expect(updatedWarpDeployConfig_3.anvil3.owner).to.equal(randomOwner);
// Check that both chains enrolled
const chain2Id = await getChainId(CHAIN_NAME_2, ANVIL_KEY);
const chain3Id = await getChainId(CHAIN_NAME_3, ANVIL_KEY);
const chain2Id = await getDomainId(CHAIN_NAME_2, ANVIL_KEY);
const chain3Id = await getDomainId(CHAIN_NAME_3, ANVIL_KEY);
const remoteRouterKeys2 = Object.keys(
updatedWarpDeployConfig_2[CHAIN_NAME_2].remoteRouters!,
@ -295,8 +295,8 @@ describe('WarpApply e2e tests', async function () {
warpConfigPath,
);
const chain2Id = await getChainId(CHAIN_NAME_2, ANVIL_KEY);
const chain3Id = await getChainId(CHAIN_NAME_3, ANVIL_KEY);
const chain2Id = await getDomainId(CHAIN_NAME_2, ANVIL_KEY);
const chain3Id = await getDomainId(CHAIN_NAME_3, ANVIL_KEY);
// Destination gas should be set in the existing chain (chain2) to include the extended chain (chain3)
const destinationGas_2 =

@ -5,7 +5,6 @@ import { BigNumber, ethers } from 'ethers';
import { Gauge, Registry } from 'prom-client';
import { format } from 'util';
import { eclipsemainnet } from '@hyperlane-xyz/registry';
import {
ChainMap,
ChainName,
@ -818,8 +817,8 @@ class ContextFunder {
) {
const l1Chain = L2ToL1[l2Chain];
const crossChainMessenger = new CrossChainMessenger({
l1ChainId: this.multiProvider.getDomainId(l1Chain),
l2ChainId: this.multiProvider.getDomainId(l2Chain),
l1ChainId: this.multiProvider.getEvmChainId(l1Chain),
l2ChainId: this.multiProvider.getEvmChainId(l2Chain),
l1SignerOrProvider: this.multiProvider.getSignerOrProvider(l1Chain),
l2SignerOrProvider: this.multiProvider.getSignerOrProvider(l2Chain),
});
@ -832,7 +831,7 @@ class ContextFunder {
private async bridgeToArbitrum(l2Chain: ChainName, amount: BigNumber) {
const l1Chain = L2ToL1[l2Chain];
const l2Network = await getL2Network(
this.multiProvider.getDomainId(l2Chain),
this.multiProvider.getEvmChainId(l2Chain),
);
const ethBridger = new EthBridger(l2Network);
return ethBridger.deposit({

@ -10,6 +10,7 @@ cd "$(dirname "$0")/../../../"
# Generate the SQL command for inserting domains into the scraper database
echo "insert into domain (id, time_created, time_updated, name, native_token, chain_id, is_test_net, is_deprecated) values"
for name in "$@"; do
chain_id=$(yq e ".$name.chainId" ../hyperlane-registry/chains/metadata.yaml)
domain_id=$(yq e ".$name.domainId" ../hyperlane-registry/chains/metadata.yaml)
if [ -z "$domain_id" ]; then
echo "Error: domain_id for $name not found" >&2
@ -22,8 +23,8 @@ for name in "$@"; do
fi
is_testnet=$(yq e ".$name.isTestnet" ../hyperlane-registry/chains/metadata.yaml)
if [ "$is_testnet" = "true" ]; then
echo "($domain_id, current_timestamp, current_timestamp, '$name', '$native_token_symbol', $domain_id, true, false)"
echo "($domain_id, current_timestamp, current_timestamp, '$name', '$native_token_symbol', $chain_id, true, false)"
else
echo "($domain_id, current_timestamp, current_timestamp, '$name', '$native_token_symbol', $domain_id, false, false)"
echo "($domain_id, current_timestamp, current_timestamp, '$name', '$native_token_symbol', $chain_id, false, false)"
fi
done | paste -sd, -

@ -232,13 +232,15 @@ async function main(): Promise<boolean> {
messageReceiptSeconds.labels({ origin, remote }).inc(0);
}
chains.map(async (chain) => {
return updateWalletBalanceMetricFor(
app,
chain,
coreConfig.owners[chain].owner,
);
});
await Promise.all(
chains.map(async (chain) => {
return updateWalletBalanceMetricFor(
app,
chain,
coreConfig.owners[chain].owner,
);
}),
);
// Incremented each time an entire cycle has occurred
let currentCycle = 0;

@ -122,7 +122,7 @@ export async function deleteSafeTx(
safeTxHash: string,
): Promise<void> {
const signer = multiProvider.getSigner(chain);
const domainId = multiProvider.getDomainId(chain);
const chainId = multiProvider.getEvmChainId(chain);
const txServiceUrl =
multiProvider.getChainMetadata(chain).gnosisSafeTransactionServiceUrl;
@ -179,7 +179,7 @@ export async function deleteSafeTx(
domain: {
name: 'Safe Transaction Service',
version: '1.0',
chainId: domainId,
chainId: chainId,
verifyingContract: safeAddress,
},
primaryType: 'DeleteRequest',

@ -3,6 +3,7 @@ import { Contract } from 'ethers';
import { Ownable, Ownable__factory } from '@hyperlane-xyz/core';
import {
Address,
EvmChainId,
ProtocolType,
ValueOf,
eqAddress,
@ -262,7 +263,7 @@ export function appFromAddressesMapHelper<F extends HyperlaneFactories>(
}
export function transferOwnershipTransactions(
chainId: number,
chainId: EvmChainId,
contract: Address,
actual: OwnableConfig,
expected: OwnableConfig,

@ -32,7 +32,7 @@ export abstract class HyperlaneModule<
public abstract read(): Promise<TConfig>;
public abstract update(
config: TConfig,
): Promise<Annotated<ProtocolTypedTransaction<TProtocol>['transaction'][]>>;
): Promise<Annotated<ProtocolTypedTransaction<TProtocol>['transaction']>[]>;
// /*
// Types and static methods can be challenging. Ensure each implementation includes a static create function.

@ -130,7 +130,7 @@ describe('EvmCoreModule', async () => {
// Check that it's actually a mailbox by calling one of it's methods
expect(await mailboxContract.localDomain()).to.equal(
multiProvider.getChainId(CHAIN),
multiProvider.getDomainId(CHAIN),
);
});

@ -2,6 +2,7 @@ import { Mailbox, Mailbox__factory } from '@hyperlane-xyz/core';
import {
Address,
Domain,
EvmChainId,
ProtocolType,
eqAddress,
rootLogger,
@ -31,7 +32,7 @@ import { HyperlaneIsmFactory } from '../ism/HyperlaneIsmFactory.js';
import { IsmConfig } from '../ism/types.js';
import { MultiProvider } from '../providers/MultiProvider.js';
import { AnnotatedEV5Transaction } from '../providers/ProviderType.js';
import { ChainNameOrId } from '../types.js';
import { ChainName, ChainNameOrId } from '../types.js';
import {
HyperlaneModule,
@ -50,10 +51,9 @@ export class EvmCoreModule extends HyperlaneModule<
> {
protected logger = rootLogger.child({ module: 'EvmCoreModule' });
protected coreReader: EvmCoreReader;
public readonly chainName: string;
public readonly chainName: ChainName;
// We use domainId here because MultiProvider.getDomainId() will always
// return a number, and EVM the domainId and chainId are the same.
public readonly chainId: EvmChainId;
public readonly domainId: Domain;
constructor(
@ -61,8 +61,9 @@ export class EvmCoreModule extends HyperlaneModule<
args: HyperlaneModuleParams<CoreConfig, DeployedCoreAddresses>,
) {
super(args);
this.coreReader = new EvmCoreReader(multiProvider, this.args.chain);
this.chainName = this.multiProvider.getChainName(this.args.chain);
this.coreReader = new EvmCoreReader(multiProvider, args.chain);
this.chainName = multiProvider.getChainName(args.chain);
this.chainId = multiProvider.getEvmChainId(args.chain);
this.domainId = multiProvider.getDomainId(args.chain);
}
@ -133,7 +134,7 @@ export class EvmCoreModule extends HyperlaneModule<
);
updateTransactions.push({
annotation: `Setting default ISM for Mailbox ${mailbox} to ${deployedIsm}`,
chainId: this.domainId,
chainId: this.chainId,
to: contractToUpdate.address,
data: contractToUpdate.interface.encodeFunctionData('setDefaultIsm', [
deployedIsm,
@ -203,7 +204,7 @@ export class EvmCoreModule extends HyperlaneModule<
expectedConfig: CoreConfig,
): AnnotatedEV5Transaction[] {
return transferOwnershipTransactions(
this.domainId,
this.chainId,
this.args.addresses.mailbox,
actualConfig,
expectedConfig,

@ -26,6 +26,8 @@ import {
} from '@hyperlane-xyz/core';
import {
Address,
Domain,
EvmChainId,
ProtocolType,
addressToBytes32,
deepEquals,
@ -95,10 +97,9 @@ export class EvmHookModule extends HyperlaneModule<
protected readonly deployer: HookDeployer;
// Adding these to reduce how often we need to grab from MultiProvider.
public readonly chain: string;
// We use domainId here because MultiProvider.getDomainId() will always
// return a number, and EVM the domainId and chainId are the same.
public readonly domainId: number;
public readonly chain: ChainName;
public readonly chainId: EvmChainId;
public readonly domainId: Domain;
// Transaction overrides for the chain
protected readonly txOverrides: Partial<ethers.providers.TransactionRequest>;
@ -121,10 +122,11 @@ export class EvmHookModule extends HyperlaneModule<
);
this.deployer = new HookDeployer(multiProvider, hookFactories);
this.chain = this.multiProvider.getChainName(this.args.chain);
this.domainId = this.multiProvider.getDomainId(this.chain);
this.chain = multiProvider.getChainName(this.args.chain);
this.chainId = multiProvider.getEvmChainId(this.chain);
this.domainId = multiProvider.getDomainId(this.chain);
this.txOverrides = this.multiProvider.getTransactionOverrides(this.chain);
this.txOverrides = multiProvider.getTransactionOverrides(this.chain);
}
public async read(): Promise<HookConfig> {
@ -217,7 +219,7 @@ export class EvmHookModule extends HyperlaneModule<
if (!eqAddress(targetConfig.owner, owner)) {
updateTxs.push({
annotation: 'Transferring ownership of ownable Hook...',
chainId: this.domainId,
chainId: this.chainId,
to: this.args.addresses.deployedHook,
data: Ownable__factory.createInterface().encodeFunctionData(
'transferOwnership(address)',
@ -319,7 +321,7 @@ export class EvmHookModule extends HyperlaneModule<
updateTxs.push({
annotation: `Updating paused state to ${targetConfig.paused}`,
chainId: this.domainId,
chainId: this.chainId,
to: this.args.addresses.deployedHook,
data,
});
@ -342,7 +344,7 @@ export class EvmHookModule extends HyperlaneModule<
if (!eqAddress(currentConfig.beneficiary, targetConfig.beneficiary)) {
updateTxs.push({
annotation: `Updating beneficiary from ${currentConfig.beneficiary} to ${targetConfig.beneficiary}`,
chainId: this.domainId,
chainId: this.chainId,
to: this.args.addresses.deployedHook,
data: igpInterface.encodeFunctionData('setBeneficiary(address)', [
targetConfig.beneficiary,
@ -443,7 +445,7 @@ export class EvmHookModule extends HyperlaneModule<
annotation: `Updating overhead for domains ${Object.keys(
targetOverheads,
).join(', ')}...`,
chainId: this.domainId,
chainId: this.chainId,
to: interchainGasPaymaster,
data: InterchainGasPaymaster__factory.createInterface().encodeFunctionData(
'setDestinationGasConfigs((uint32,(address,uint96))[])',
@ -509,7 +511,7 @@ export class EvmHookModule extends HyperlaneModule<
annotation: `Updating gas oracle config for domains ${Object.keys(
targetOracleConfig,
).join(', ')}...`,
chainId: this.domainId,
chainId: this.chainId,
to: gasOracle,
data: StorageGasOracle__factory.createInterface().encodeFunctionData(
'setRemoteGasDataConfigs((uint32,uint128,uint128)[])',
@ -540,7 +542,7 @@ export class EvmHookModule extends HyperlaneModule<
if (currentConfig.protocolFee !== targetConfig.protocolFee) {
updateTxs.push({
annotation: `Updating protocol fee from ${currentConfig.protocolFee} to ${targetConfig.protocolFee}`,
chainId: this.domainId,
chainId: this.chainId,
to: this.args.addresses.deployedHook,
data: protocolFeeInterface.encodeFunctionData(
'setProtocolFee(uint256)',
@ -553,7 +555,7 @@ export class EvmHookModule extends HyperlaneModule<
if (currentConfig.beneficiary !== targetConfig.beneficiary) {
updateTxs.push({
annotation: `Updating beneficiary from ${currentConfig.beneficiary} to ${targetConfig.beneficiary}`,
chainId: this.domainId,
chainId: this.chainId,
to: this.args.addresses.deployedHook,
data: protocolFeeInterface.encodeFunctionData(
'setBeneficiary(address)',
@ -601,7 +603,7 @@ export class EvmHookModule extends HyperlaneModule<
return [
{
annotation: 'Updating routing hooks...',
chainId: this.domainId,
chainId: this.chainId,
to: this.args.addresses.deployedHook,
data: DomainRoutingHook__factory.createInterface().encodeFunctionData(
'setHooks((uint32,address)[])',
@ -828,17 +830,17 @@ export class EvmHookModule extends HyperlaneModule<
const chain = this.chain;
const mailbox = this.args.addresses.mailbox;
const destinationChain = this.multiProvider.getChainId(
const destinationChainId = this.multiProvider.tryGetEvmChainId(
config.destinationChain,
);
if (typeof destinationChain !== 'number') {
if (!destinationChainId) {
throw new Error(
`Only ethereum chains supported for deploying Arbitrum L2 hook, given: ${config.destinationChain}`,
`Only ethereum chains supported for deploying Arbitrum L2 hook, given: ${config.destinationChain}`,
);
}
const bridge =
config.bridge ?? getArbitrumNetwork(destinationChain).ethBridge.bridge;
config.bridge ?? getArbitrumNetwork(destinationChainId).ethBridge.bridge;
const ismConfig: ArbL2ToL1IsmConfig = {
type: IsmType.ARB_L2_TO_L1,

@ -498,6 +498,7 @@ export {
SealevelInstructionWrapper,
getSealevelAccountDataSchema,
} from './utils/sealevelSerialization.js';
export { getChainIdFromTxs } from './utils/transactions.js';
export { chainMetadataToWagmiChain } from './utils/wagmi.js';
export {
FeeConstantConfig,

@ -5,6 +5,7 @@ import { DomainRoutingIsm__factory } from '@hyperlane-xyz/core';
import {
Address,
Domain,
EvmChainId,
ProtocolType,
assert,
deepEquals,
@ -54,8 +55,7 @@ export class EvmIsmModule extends HyperlaneModule<
// Adding these to reduce how often we need to grab from MultiProvider.
public readonly chain: ChainName;
// We use domainId here because MultiProvider.getDomainId() will always
// return a number, and EVM the domainId and chainId are the same.
public readonly chainId: EvmChainId;
public readonly domainId: Domain;
constructor(
@ -78,8 +78,9 @@ export class EvmIsmModule extends HyperlaneModule<
this.mailbox = params.addresses.mailbox;
this.chain = this.multiProvider.getChainName(this.args.chain);
this.domainId = this.multiProvider.getDomainId(this.chain);
this.chain = multiProvider.getChainName(this.args.chain);
this.chainId = multiProvider.getEvmChainId(this.chain);
this.domainId = multiProvider.getDomainId(this.chain);
}
public async read(): Promise<IsmConfig> {
@ -169,7 +170,7 @@ export class EvmIsmModule extends HyperlaneModule<
// Lastly, check if the resolved owner is different from the current owner
updateTxs.push(
...transferOwnershipTransactions(
this.domainId,
this.chainId,
this.args.addresses.deployedIsm,
currentConfig,
targetConfig,
@ -252,9 +253,9 @@ export class EvmIsmModule extends HyperlaneModule<
const domainId = this.multiProvider.getDomainId(origin);
const tx = await contract.populateTransaction.set(domainId, ism.address);
updateTxs.push({
chainId: this.chainId,
annotation: `Setting new ISM for origin ${origin}...`,
...tx,
chainId: this.domainId,
});
}
@ -268,9 +269,9 @@ export class EvmIsmModule extends HyperlaneModule<
const domainId = this.multiProvider.getDomainId(origin);
const tx = await contract.populateTransaction.remove(domainId);
updateTxs.push({
chainId: this.chainId,
annotation: `Unenrolling originDomain ${domainId} from preexisting routing ISM at ${this.args.addresses.deployedIsm}...`,
...tx,
chainId: this.domainId,
});
}

@ -281,18 +281,15 @@ export class HyperlaneIsmFactory extends HyperlaneApp<ProxyFactoryFactories> {
this.getContracts(destination).domainRoutingIsmFactory;
let routingIsm: DomainRoutingIsm | DefaultFallbackRoutingIsm;
// filtering out domains which are not part of the multiprovider
config.domains = objFilter(
config.domains,
(domain, config): config is IsmConfig => {
const domainId = this.multiProvider.tryGetDomainId(domain);
if (domainId === null) {
logger.warn(
`Domain ${domain} doesn't have chain metadata provided, skipping ...`,
);
}
return domainId !== null;
},
);
config.domains = objFilter(config.domains, (domain, _): _ is IsmConfig => {
const domainId = this.multiProvider.tryGetDomainId(domain);
if (domainId === null) {
logger.warn(
`Domain ${domain} doesn't have chain metadata provided, skipping ...`,
);
}
return domainId !== null;
});
const safeConfigDomains = Object.keys(config.domains).map((domain) =>
this.multiProvider.getDomainId(domain),
);

@ -1,6 +1,12 @@
import { Logger } from 'pino';
import { ProtocolType, exclude, pick, rootLogger } from '@hyperlane-xyz/utils';
import {
EvmChainId,
ProtocolType,
exclude,
pick,
rootLogger,
} from '@hyperlane-xyz/utils';
import { ChainMap, ChainName, ChainNameOrId } from '../types.js';
@ -56,31 +62,25 @@ export class ChainMetadataManager<MetaExt = {}> {
/**
* Add a chain to the MultiProvider
* @throws if chain's name or domain/chain ID collide
* @throws if chain's name or domain ID collide
*/
addChain(metadata: ChainMetadata<MetaExt>): void {
ChainMetadataSchema.parse(metadata);
// Ensure no two chains have overlapping names/domainIds/chainIds
// Ensure no two chains have overlapping names/domainIds
for (const chainMetadata of Object.values(this.metadata)) {
const { name, chainId, domainId } = chainMetadata;
const { name, domainId } = chainMetadata;
if (name == metadata.name)
throw new Error(`Duplicate chain name: ${name}`);
// Chain and Domain Ids should be globally unique
const idCollision =
chainId == metadata.chainId ||
domainId == metadata.chainId ||
(metadata.domainId &&
(chainId == metadata.domainId || domainId == metadata.domainId));
// Domain Ids should be globally unique
const idCollision = metadata.domainId && domainId == metadata.domainId;
if (idCollision)
throw new Error(
`Chain/Domain id collision: ${name} and ${metadata.name}`,
);
throw new Error(`Domain id collision: ${name} and ${metadata.name}`);
}
this.metadata[metadata.name] = metadata;
}
/**
* Get the metadata for a given chain name, chain id, or domain id
* Get the metadata for a given chain name or domain id
* @throws if chain's metadata has not been set
*/
tryGetChainMetadata(
@ -88,15 +88,15 @@ export class ChainMetadataManager<MetaExt = {}> {
): ChainMetadata<MetaExt> | null {
// First check if it's a chain name
if (this.metadata[chainNameOrId]) return this.metadata[chainNameOrId];
// Otherwise search by chain id and domain id
// Otherwise search by domain id
const chainMetadata = Object.values(this.metadata).find(
(m) => m.chainId == chainNameOrId || m.domainId == chainNameOrId,
(m) => m.domainId == chainNameOrId,
);
return chainMetadata || null;
}
/**
* Get the metadata for a given chain name, chain id, or domain id
* Get the metadata for a given chain name or domain id
* @throws if chain's metadata has not been set
*/
getChainMetadata(chainNameOrId: ChainNameOrId): ChainMetadata<MetaExt> {
@ -119,22 +119,22 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Returns true if the given chain name, chain id, or domain id is
* include in this manager's metadata, false otherwise
* Returns true if the given chain name or domain id is
* included in this manager's metadata, false otherwise
*/
hasChain(chainNameOrId: ChainNameOrId): boolean {
return !!this.tryGetChainMetadata(chainNameOrId);
}
/**
* Get the name for a given chain name, chain id, or domain id
* Get the name for a given chain name or domain id
*/
tryGetChainName(chainNameOrId: ChainNameOrId): string | null {
return this.tryGetChainMetadata(chainNameOrId)?.name ?? null;
}
/**
* Get the name for a given chain name, chain id, or domain id
* Get the name for a given chain name or domain id
* @throws if chain's metadata has not been set
*/
getChainName(chainNameOrId: ChainNameOrId): string {
@ -149,14 +149,14 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get the id for a given chain name, chain id, or domain id
* Get the id for a given chain name or domain id
*/
tryGetChainId(chainNameOrId: ChainNameOrId): number | string | null {
return this.tryGetChainMetadata(chainNameOrId)?.chainId ?? null;
}
/**
* Get the id for a given chain name, chain id, or domain id
* Get the id for a given chain name or domain id
* @throws if chain's metadata has not been set
*/
getChainId(chainNameOrId: ChainNameOrId): number | string {
@ -164,14 +164,34 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get the ids for all chains known to this MultiProvider
* Get the id for a given EVM chain name or domain id
* Returns null if chain's metadata has not been set or is not an EVM chain
*/
getKnownChainIds(): Array<number | string> {
return Object.values(this.metadata).map((c) => c.chainId);
tryGetEvmChainId(chainNameOrId: ChainNameOrId): number | null {
const metadata = this.tryGetChainMetadata(chainNameOrId);
if (!metadata) return null;
if (metadata.protocol !== ProtocolType.Ethereum) return null;
if (typeof metadata.chainId !== 'number') return null;
return metadata.chainId;
}
/**
* Get the id for a given EVM chain name or domain id
* @throws if chain's metadata has not been set
*/
getEvmChainId(chainNameOrId: ChainNameOrId): EvmChainId {
const { protocol, chainId } = this.getChainMetadata(chainNameOrId);
if (protocol !== ProtocolType.Ethereum) {
throw new Error(`Chain is not an EVM chain: ${chainNameOrId}`);
}
if (typeof chainId !== 'number') {
throw new Error(`Chain ID is not a number: ${chainId}`);
}
return chainId;
}
/**
* Get the domain id for a given chain name, chain id, or domain id
* Get the domain id for a given chain name or domain id
*/
tryGetDomainId(chainNameOrId: ChainNameOrId): number | null {
const metadata = this.tryGetChainMetadata(chainNameOrId);
@ -180,7 +200,7 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get the domain id for a given chain name, chain id, or domain id
* Get the domain id for a given chain name or domain id
* @throws if chain's metadata has not been set
*/
getDomainId(chainNameOrId: ChainNameOrId): number {
@ -190,14 +210,14 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get the protocol type for a given chain name, chain id, or domain id
* Get the protocol type for a given chain name or domain id
*/
tryGetProtocol(chainNameOrId: ChainNameOrId): ProtocolType | null {
return this.tryGetChainMetadata(chainNameOrId)?.protocol ?? null;
}
/**
* Get the protocol type for a given chain name, chain id, or domain id
* Get the protocol type for a given chain name or domain id
* @throws if chain's metadata or protocol has not been set
*/
getProtocol(chainNameOrId: ChainNameOrId): ProtocolType {
@ -205,7 +225,7 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get the domain ids for a list of chain names, chain ids, or domain ids
* Get the domain ids for a list of chain names or domain ids
* @throws if any chain's metadata has not been set
*/
getDomainIds(chainNamesOrIds: Array<ChainName | number>): number[] {
@ -240,7 +260,7 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get the RPC details for a given chain name, chain id, or domain id.
* Get the RPC details for a given chain name or domain id.
* Optional index for metadata containing more than one RPC.
* @throws if chain's metadata has not been set
*/
@ -257,7 +277,7 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get an RPC URL for a given chain name, chain id, or domain id
* Get an RPC URL for a given chain name or domain id
* @throws if chain's metadata has not been set
*/
getRpcUrl(chainNameOrId: ChainNameOrId, index = 0): string {
@ -267,7 +287,7 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get an RPC concurrency level for a given chain name, chain id, or domain id
* Get an RPC concurrency level for a given chain name or domain id
*/
tryGetRpcConcurrency(chainNameOrId: ChainNameOrId, index = 0): number | null {
const { concurrency } = this.getRpc(chainNameOrId, index);
@ -275,7 +295,7 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get a block explorer URL for a given chain name, chain id, or domain id
* Get a block explorer URL for a given chain name or domain id
*/
tryGetExplorerUrl(chainNameOrId: ChainNameOrId): string | null {
const metadata = this.tryGetChainMetadata(chainNameOrId);
@ -284,7 +304,7 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get a block explorer URL for a given chain name, chain id, or domain id
* Get a block explorer URL for a given chain name or domain id
* @throws if chain's metadata or block explorer data has no been set
*/
getExplorerUrl(chainNameOrId: ChainNameOrId): string {
@ -294,7 +314,7 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get a block explorer's API for a given chain name, chain id, or domain id
* Get a block explorer's API for a given chain name or domain id
*/
tryGetExplorerApi(chainNameOrId: ChainName | number): {
apiUrl: string;
@ -307,7 +327,7 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get a block explorer API for a given chain name, chain id, or domain id
* Get a block explorer API for a given chain name or domain id
* @throws if chain's metadata or block explorer data has no been set
*/
getExplorerApi(chainNameOrId: ChainName | number): {
@ -322,7 +342,7 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get a block explorer's API URL for a given chain name, chain id, or domain id
* Get a block explorer's API URL for a given chain name or domain id
*/
tryGetExplorerApiUrl(chainNameOrId: ChainNameOrId): string | null {
const metadata = this.tryGetChainMetadata(chainNameOrId);
@ -331,7 +351,7 @@ export class ChainMetadataManager<MetaExt = {}> {
}
/**
* Get a block explorer API URL for a given chain name, chain id, or domain id
* Get a block explorer API URL for a given chain name or domain id
* @throws if chain's metadata or block explorer data has no been set
*/
getExplorerApiUrl(chainNameOrId: ChainNameOrId): string {

@ -187,8 +187,8 @@ export const ChainMetadataSchemaObject = z.object({
'A shorter human-readable name of the chain for use in user interfaces.',
),
domainId: ZNzUint.optional().describe(
'The domainId of the chain, should generally default to `chainId`. Consumer of `ChainMetadata` should use this value if present, but otherwise fallback to `chainId`.',
domainId: ZNzUint.describe(
'The domainId of the chain, should generally default to `chainId`. Consumer of `ChainMetadata` should use this value or `name` as a unique identifier.',
),
gasCurrencyCoinGeckoId: z

@ -84,7 +84,7 @@ export class MultiProvider<MetaExt = {}> extends ChainMetadataManager<MetaExt> {
}
/**
* Get an Ethers provider for a given chain name, chain id, or domain id
* Get an Ethers provider for a given chain name or domain id
*/
tryGetProvider(chainNameOrId: ChainNameOrId): Provider | null {
const metadata = this.tryGetChainMetadata(chainNameOrId);
@ -108,7 +108,7 @@ export class MultiProvider<MetaExt = {}> extends ChainMetadataManager<MetaExt> {
}
/**
* Get an Ethers provider for a given chain name, chain id, or domain id
* Get an Ethers provider for a given chain name or domain id
* @throws if chain's metadata has not been set
*/
getProvider(chainNameOrId: ChainNameOrId): Provider {
@ -119,7 +119,7 @@ export class MultiProvider<MetaExt = {}> extends ChainMetadataManager<MetaExt> {
}
/**
* Sets an Ethers provider for a given chain name, chain id, or domain id
* Sets an Ethers provider for a given chain name or domain id
* @throws if chain's metadata has not been set
*/
setProvider(chainNameOrId: ChainNameOrId, provider: Provider): Provider {
@ -144,7 +144,7 @@ export class MultiProvider<MetaExt = {}> extends ChainMetadataManager<MetaExt> {
}
/**
* Get an Ethers signer for a given chain name, chain id, or domain id
* Get an Ethers signer for a given chain name or domain id
* If signer is not yet connected, it will be connected
*/
tryGetSigner(chainNameOrId: ChainNameOrId): Signer | null {
@ -159,7 +159,7 @@ export class MultiProvider<MetaExt = {}> extends ChainMetadataManager<MetaExt> {
}
/**
* Get an Ethers signer for a given chain name, chain id, or domain id
* Get an Ethers signer for a given chain name or domain id
* If signer is not yet connected, it will be connected
* @throws if chain's metadata or signer has not been set
*/
@ -170,7 +170,7 @@ export class MultiProvider<MetaExt = {}> extends ChainMetadataManager<MetaExt> {
}
/**
* Get an Ethers signer for a given chain name, chain id, or domain id
* Get an Ethers signer for a given chain name or domain id
* @throws if chain's metadata or signer has not been set
*/
async getSignerAddress(chainNameOrId: ChainNameOrId): Promise<Address> {
@ -180,7 +180,7 @@ export class MultiProvider<MetaExt = {}> extends ChainMetadataManager<MetaExt> {
}
/**
* Sets an Ethers Signer for a given chain name, chain id, or domain id
* Sets an Ethers Signer for a given chain name or domain id
* @throws if chain's metadata has not been set or shared signer has already been set
*/
setSigner(chainNameOrId: ChainNameOrId, signer: Signer): Signer {
@ -295,7 +295,7 @@ export class MultiProvider<MetaExt = {}> extends ChainMetadataManager<MetaExt> {
}
/**
* Get the transaction overrides for a given chain name, chain id, or domain id
* Get the transaction overrides for a given chain name or domain id
* @throws if chain's metadata has not been set
*/
getTransactionOverrides(

@ -22,7 +22,7 @@ import type {
TransactionReceipt as VTransactionReceipt,
} from 'viem';
import { ProtocolType } from '@hyperlane-xyz/utils';
import { Annotated, ProtocolType } from '@hyperlane-xyz/utils';
export enum ProviderType {
EthersV5 = 'ethers-v5',
@ -192,9 +192,7 @@ export interface EthersV5Transaction
transaction: EV5Transaction;
}
export interface AnnotatedEV5Transaction extends EV5Transaction {
annotation?: string;
}
export type AnnotatedEV5Transaction = Annotated<EV5Transaction>;
export interface ViemTransaction extends TypedTransactionBase<VTransaction> {
type: ProviderType.Viem;

@ -1,4 +1,4 @@
import { ProtocolType } from '@hyperlane-xyz/utils';
import { Annotated, ProtocolType } from '@hyperlane-xyz/utils';
import {
ProtocolTypedProvider,
@ -22,7 +22,7 @@ export interface TxSubmitterInterface<TProtocol extends ProtocolType> {
* @param txs The array of transactions to execute
*/
submit(
...txs: ProtocolTypedTransaction<TProtocol>['transaction'][]
...txs: Annotated<ProtocolTypedTransaction<TProtocol>['transaction']>[]
): Promise<
| ProtocolTypedReceipt<TProtocol>['receipt']
| ProtocolTypedReceipt<TProtocol>['receipt'][]

@ -1,6 +1,6 @@
import { Logger } from 'pino';
import { rootLogger } from '@hyperlane-xyz/utils';
import { Annotated, rootLogger } from '@hyperlane-xyz/utils';
import { ProtocolType } from '@hyperlane-xyz/utils';
import {
@ -73,7 +73,7 @@ export class TxSubmitterBuilder<TProtocol extends ProtocolType>
* @param txs The transactions to submit
*/
public async submit(
...txs: ProtocolTypedTransaction<TProtocol>['transaction'][]
...txs: Annotated<ProtocolTypedTransaction<TProtocol>['transaction']>[]
): Promise<
| ProtocolTypedReceipt<TProtocol>['receipt']
| ProtocolTypedReceipt<TProtocol>['receipt'][]

@ -59,6 +59,7 @@ export class EV5GnosisSafeTxBuilder extends EV5GnosisSafeTxSubmitter {
* @param txs - An array of populated transactions
*/
public async submit(...txs: AnnotatedEV5Transaction[]): Promise<any> {
const chainId = this.multiProvider.getChainId(this.props.chain);
const transactions: SafeTransactionData[] = await Promise.all(
txs.map(
async (tx: AnnotatedEV5Transaction) =>
@ -69,7 +70,7 @@ export class EV5GnosisSafeTxBuilder extends EV5GnosisSafeTxSubmitter {
);
return {
version: this.props.version,
chainId: this.multiProvider.getChainId(this.props.chain).toString(),
chainId: chainId.toString(),
meta: {},
transactions,
};

@ -72,11 +72,11 @@ export class EV5GnosisSafeTxSubmitter implements EV5TxSubmitterInterface {
const nextNonce: number = await this.safeService.getNextNonce(
this.props.safeAddress,
);
assert(chainId, 'Invalid PopulatedTransaction: chainId is required');
const txChain = this.multiProvider.getChainName(chainId);
const submitterChainId = this.multiProvider.getChainId(this.props.chain);
assert(chainId, 'Invalid AnnotatedEV5Transaction: chainId is required');
assert(
txChain === this.props.chain,
`Invalid PopulatedTransaction: Cannot submit ${txChain} tx to ${this.props.chain} submitter.`,
chainId === submitterChainId,
`Invalid AnnotatedEV5Transaction: Cannot submit tx for chain ID ${chainId} to submitter for chain ID ${submitterChainId}.`,
);
return this.safe.createTransaction({
safeTransactionData: [{ to, data, value: value?.toString() ?? '0' }],

@ -26,7 +26,7 @@ export class EV5ImpersonatedAccountTxSubmitter extends EV5JsonRpcTxSubmitter {
multiProvider: MultiProvider,
public readonly props: EV5ImpersonatedAccountTxSubmitterProps,
) {
super(multiProvider);
super(multiProvider, props);
}
public async submit(

@ -9,6 +9,7 @@ import { AnnotatedEV5Transaction } from '../../../ProviderType.js';
import { TxSubmitterType } from '../TxSubmitterTypes.js';
import { EV5TxSubmitterInterface } from './EV5TxSubmitterInterface.js';
import { EV5JsonRpcTxSubmitterProps } from './types.js';
export class EV5JsonRpcTxSubmitter implements EV5TxSubmitterInterface {
public readonly txSubmitterType: TxSubmitterType = TxSubmitterType.JSON_RPC;
@ -17,21 +18,28 @@ export class EV5JsonRpcTxSubmitter implements EV5TxSubmitterInterface {
module: 'json-rpc-submitter',
});
constructor(public readonly multiProvider: MultiProvider) {}
constructor(
public readonly multiProvider: MultiProvider,
public readonly props: EV5JsonRpcTxSubmitterProps,
) {}
public async submit(
...txs: AnnotatedEV5Transaction[]
): Promise<TransactionReceipt[]> {
const receipts: TransactionReceipt[] = [];
const submitterChainId = this.multiProvider.getChainId(this.props.chain);
for (const tx of txs) {
assert(tx.chainId, 'Invalid PopulatedTransaction: Missing chainId field');
const txChain = this.multiProvider.getChainName(tx.chainId);
assert(
tx.chainId === submitterChainId,
`Transaction chainId ${tx.chainId} does not match submitter chainId ${submitterChainId}`,
);
const receipt: ContractReceipt = await this.multiProvider.sendTransaction(
txChain,
this.props.chain,
tx,
);
this.logger.debug(
`Submitted PopulatedTransaction on ${txChain}: ${receipt.transactionHash}`,
`Submitted PopulatedTransaction on ${this.props.chain}: ${receipt.transactionHash}`,
);
receipts.push(receipt);
}

@ -42,7 +42,8 @@ describe('ethersV5 submitter props schemas', () => {
describe('EV5ImpersonatedAccountTxSubmitterPropsSchema', () => {
it('should parse valid props', () => {
const validProps: EV5ImpersonatedAccountTxSubmitterProps = {
userAddress: '0x1234567890123456789012345678901234567890',
chain: CHAIN_MOCK,
userAddress: ADDRESS_MOCK,
};
const result =
EV5ImpersonatedAccountTxSubmitterPropsSchema.safeParse(validProps);
@ -51,6 +52,7 @@ describe('ethersV5 submitter props schemas', () => {
it('should fail parsing invalid props', () => {
const invalidProps: EV5ImpersonatedAccountTxSubmitterProps = {
chain: CHAIN_MOCK,
userAddress: INVALID_ADDRESS,
};
const result =

@ -13,6 +13,11 @@ export const EV5GnosisSafeTxBuilderPropsSchema = z.object({
safeAddress: ZHash,
});
export const EV5ImpersonatedAccountTxSubmitterPropsSchema = z.object({
userAddress: ZHash,
export const EV5JsonRpcTxSubmitterPropsSchema = z.object({
chain: ZChainName,
});
export const EV5ImpersonatedAccountTxSubmitterPropsSchema =
EV5JsonRpcTxSubmitterPropsSchema.extend({
userAddress: ZHash,
});

@ -4,6 +4,7 @@ import {
EV5GnosisSafeTxBuilderPropsSchema,
EV5GnosisSafeTxSubmitterPropsSchema,
EV5ImpersonatedAccountTxSubmitterPropsSchema,
EV5JsonRpcTxSubmitterPropsSchema,
} from './schemas.js';
export type EV5GnosisSafeTxSubmitterProps = z.infer<
@ -12,6 +13,9 @@ export type EV5GnosisSafeTxSubmitterProps = z.infer<
export type EV5GnosisSafeTxBuilderProps = z.infer<
typeof EV5GnosisSafeTxBuilderPropsSchema
>;
export type EV5JsonRpcTxSubmitterProps = z.infer<
typeof EV5JsonRpcTxSubmitterPropsSchema
>;
export type EV5ImpersonatedAccountTxSubmitterProps = z.infer<
typeof EV5ImpersonatedAccountTxSubmitterPropsSchema
>;

@ -5,11 +5,13 @@ import {
EV5GnosisSafeTxBuilderPropsSchema,
EV5GnosisSafeTxSubmitterPropsSchema,
EV5ImpersonatedAccountTxSubmitterPropsSchema,
EV5JsonRpcTxSubmitterPropsSchema,
} from './ethersV5/schemas.js';
export const SubmitterMetadataSchema = z.discriminatedUnion('type', [
z.object({
type: z.literal(TxSubmitterType.JSON_RPC),
...EV5JsonRpcTxSubmitterPropsSchema.shape,
}),
z.object({
type: z.literal(TxSubmitterType.IMPERSONATED_ACCOUNT),

@ -1,4 +1,4 @@
import { ProtocolType } from '@hyperlane-xyz/utils';
import { Annotated, ProtocolType } from '@hyperlane-xyz/utils';
import { ProtocolTypedTransaction } from '../../ProviderType.js';
@ -14,6 +14,6 @@ export interface TxTransformerInterface<TProtocol extends ProtocolType> {
* @param txs The array of transactions to transform
*/
transform(
...txs: ProtocolTypedTransaction<TProtocol>['transaction'][]
): Promise<ProtocolTypedTransaction<TProtocol>['transaction'][]>;
...txs: Annotated<ProtocolTypedTransaction<TProtocol>['transaction']>[]
): Promise<Annotated<ProtocolTypedTransaction<TProtocol>['transaction']>[]>;
}

@ -1,4 +1,3 @@
import { ethers } from 'ethers';
import { Logger } from 'pino';
import { assert, objMap, rootLogger } from '@hyperlane-xyz/utils';
@ -37,18 +36,22 @@ export class EV5InterchainAccountTxTransformer
public async transform(
...txs: AnnotatedEV5Transaction[]
): Promise<ethers.PopulatedTransaction[]> {
): Promise<AnnotatedEV5Transaction[]> {
const transformerChainId = this.multiProvider.getChainId(this.props.chain);
const txChainsToInnerCalls: Record<ChainName, CallData[]> = txs.reduce(
(
txChainToInnerCalls: Record<ChainName, CallData[]>,
{ to, data, chainId }: AnnotatedEV5Transaction,
) => {
assert(chainId, 'Invalid PopulatedTransaction: chainId is required');
assert(to, 'Invalid PopulatedTransaction: to is required');
assert(data, 'Invalid PopulatedTransaction: data is required');
const txChain = this.multiProvider.getChainName(chainId);
txChainToInnerCalls[txChain] ||= [];
txChainToInnerCalls[txChain].push({ to, data });
assert(chainId, 'Invalid PopulatedTransaction: "chainId" is required');
assert(to, 'Invalid PopulatedTransaction: "to" is required');
assert(data, 'Invalid PopulatedTransaction: "data" is required');
assert(
chainId === transformerChainId,
`Transaction chainId ${chainId} does not match transformer chainId ${transformerChainId}`,
);
txChainToInnerCalls[chainId] ||= [];
txChainToInnerCalls[chainId].push({ to, data });
return txChainToInnerCalls;
},
{},
@ -60,7 +63,7 @@ export class EV5InterchainAccountTxTransformer
this.props.config,
);
const transformedTxs: ethers.PopulatedTransaction[] = [];
const transformedTxs: AnnotatedEV5Transaction[] = [];
objMap(txChainsToInnerCalls, async (destination, innerCalls) => {
transformedTxs.push(
await interchainAccountApp.getCallRemote({

@ -10,6 +10,7 @@ import { ContractVerifier, ExplorerLicenseType } from '@hyperlane-xyz/sdk';
import {
Address,
Domain,
EvmChainId,
ProtocolType,
addressToBytes32,
assert,
@ -29,7 +30,7 @@ import { EvmIsmModule } from '../ism/EvmIsmModule.js';
import { DerivedIsmConfig } from '../ism/EvmIsmReader.js';
import { MultiProvider } from '../providers/MultiProvider.js';
import { AnnotatedEV5Transaction } from '../providers/ProviderType.js';
import { ChainNameOrId } from '../types.js';
import { ChainName, ChainNameOrId } from '../types.js';
import { normalizeConfig } from '../utils/ism.js';
import { EvmERC20WarpRouteReader } from './EvmERC20WarpRouteReader.js';
@ -47,8 +48,8 @@ export class EvmERC20WarpModule extends HyperlaneModule<
module: 'EvmERC20WarpModule',
});
reader: EvmERC20WarpRouteReader;
// We use domainId here because MultiProvider.getDomainId() will always
// return a number, and EVM the domainId and chainId are the same.
public readonly chainName: ChainName;
public readonly chainId: EvmChainId;
public readonly domainId: Domain;
constructor(
@ -63,6 +64,8 @@ export class EvmERC20WarpModule extends HyperlaneModule<
) {
super(args);
this.reader = new EvmERC20WarpRouteReader(multiProvider, args.chain);
this.chainName = this.multiProvider.getChainName(args.chain);
this.chainId = multiProvider.getEvmChainId(args.chain);
this.domainId = multiProvider.getDomainId(args.chain);
this.contractVerifier ??= new ContractVerifier(
multiProvider,
@ -149,8 +152,8 @@ export class EvmERC20WarpModule extends HyperlaneModule<
);
updateTransactions.push({
chainId: this.chainId,
annotation: `Enrolling Router ${this.args.addresses.deployedTokenRoute} on ${this.args.chain}`,
chainId: this.domainId,
to: contractToUpdate.address,
data: contractToUpdate.interface.encodeFunctionData(
'enrollRemoteRouters',
@ -205,8 +208,8 @@ export class EvmERC20WarpModule extends HyperlaneModule<
});
updateTransactions.push({
chainId: this.chainId,
annotation: `Setting destination gas for ${this.args.addresses.deployedTokenRoute} on ${this.args.chain}`,
chainId: this.domainId,
to: contractToUpdate.address,
data: contractToUpdate.interface.encodeFunctionData(
'setDestinationGas((uint32,uint256)[])',
@ -254,8 +257,8 @@ export class EvmERC20WarpModule extends HyperlaneModule<
this.multiProvider.getProvider(this.domainId),
);
updateTransactions.push({
chainId: this.chainId,
annotation: `Setting ISM for Warp Route to ${expectedDeployedIsm}`,
chainId: this.domainId,
to: contractToUpdate.address,
data: contractToUpdate.interface.encodeFunctionData(
'setInterchainSecurityModule',
@ -280,7 +283,7 @@ export class EvmERC20WarpModule extends HyperlaneModule<
expectedConfig: TokenRouterConfig,
): AnnotatedEV5Transaction[] {
return transferOwnershipTransactions(
this.multiProvider.getDomainId(this.args.chain),
this.multiProvider.getEvmChainId(this.args.chain),
this.args.addresses.deployedTokenRoute,
actualConfig,
expectedConfig,
@ -310,7 +313,7 @@ export class EvmERC20WarpModule extends HyperlaneModule<
// Internally the createTransferOwnershipTx method already checks if the
// two owner values are the same and produces an empty tx batch if they are
...transferOwnershipTransactions(
this.domainId,
this.chainId,
actualProxyAdmin.address!,
actualProxyAdmin,
expectedConfig.proxyAdmin,

@ -1,12 +1,12 @@
import type { ethers } from 'ethers';
import type { ChainId, Domain } from '@hyperlane-xyz/utils';
import type { Domain } from '@hyperlane-xyz/utils';
// An alias for string to clarify type is a chain name
export type ChainName = string;
// A map of chain names to a value type
export type ChainMap<Value> = Record<string, Value>;
export type ChainMap<Value> = Record<ChainName, Value>;
export type ChainNameOrId = ChainName | ChainId | Domain;
export type ChainNameOrId = ChainName | Domain;
export type Connection = ethers.providers.Provider | ethers.Signer;

@ -48,8 +48,8 @@ export async function getSafe(chain, multiProvider, safeAddress) {
const signer = multiProvider.getSigner(chain);
const ethAdapter = new EthersAdapter({ ethers, signerOrProvider: signer });
// Get the domain id for the given chain
const domainId = multiProvider.getDomainId(chain);
// Get the chain id for the given chain
const chainId = multiProvider.getChainId(chain);
// Get the safe version
const safeService = getSafeService(chain, multiProvider);
@ -66,11 +66,11 @@ export async function getSafe(chain, multiProvider, safeAddress) {
safeDeploymentsVersions[safeVersion];
multiSend = getMultiSendDeployment({
version: multiSendVersion,
network: domainId,
network: chainId,
});
multiSendCallOnly = getMultiSendCallOnlyDeployment({
version: multiSendCallOnlyVersion,
network: domainId,
network: chainId,
});
}
@ -78,13 +78,12 @@ export async function getSafe(chain, multiProvider, safeAddress) {
ethAdapter,
safeAddress,
contractNetworks: {
// DomainId == ChainId for EVM Chains
[domainId]: {
[chainId]: {
// Use the safe address for multiSendAddress and multiSendCallOnlyAddress
// if the contract is not deployed or if the version is not found.
multiSendAddress: multiSend?.networkAddresses[domainId] || safeAddress,
multiSendAddress: multiSend?.networkAddresses[chainId] || safeAddress,
multiSendCallOnlyAddress:
multiSendCallOnly?.networkAddresses[domainId] || safeAddress,
multiSendCallOnly?.networkAddresses[chainId] || safeAddress,
},
},
});

@ -0,0 +1,26 @@
import { EvmChainId, assert } from '@hyperlane-xyz/utils';
import { AnnotatedEV5Transaction } from '../providers/ProviderType.js';
/**
* Retrieves the chain ID from the first transaction and verifies all transactions
* are for the same chain.
*
* @param transactions - The list of populated transactions.
* @returns The EVM chain ID that the transactions are for.
* @throws If the transactions are not all for the same chain ID or if chain ID is missing
*/
export function getChainIdFromTxs(
transactions: AnnotatedEV5Transaction[],
): EvmChainId {
const firstTransaction = transactions[0];
const sameChainIds = transactions.every(
(t: AnnotatedEV5Transaction) => t.chainId === firstTransaction.chainId,
);
assert(sameChainIds, 'Transactions must be submitted on the same chains');
assert(
firstTransaction.chainId,
'Invalid PopulatedTransaction: "chainId" is required',
);
return firstTransaction.chainId;
}

@ -151,6 +151,7 @@ export {
Checkpoint,
CheckpointWithId,
Domain,
EvmChainId,
HexString,
MerkleProof,
MessageStatus,

@ -17,6 +17,7 @@ export const ProtocolSmallestUnit = {
/********* BASIC TYPES *********/
export type Domain = number;
export type EvmChainId = number;
export type ChainId = string | number;
export type Address = string;
export type AddressBytes32 = string;

@ -155,14 +155,7 @@ function tryParseMetadataInput(
return failure('name is already in use by another chain');
}
if (multiProvider.tryGetChainMetadata(newMetadata.chainId)) {
return failure('chainId is already in use by another chain');
}
if (
newMetadata.domainId &&
multiProvider.tryGetChainMetadata(newMetadata.domainId)
) {
if (multiProvider.tryGetChainMetadata(newMetadata.domainId)) {
return failure('domainId is already in use by another chain');
}

@ -241,7 +241,7 @@ function chainSearch({
chain.name.includes(queryFormatted) ||
chain.displayName?.toLowerCase().includes(queryFormatted) ||
chain.chainId.toString().includes(queryFormatted) ||
chain.domainId?.toString().includes(queryFormatted),
chain.domainId.toString().includes(queryFormatted),
)
// Filter options
.filter((chain) => {

Loading…
Cancel
Save